(() => { // node_modules/udn-frontend/index.ts var UDNFrontend = class { ws; // HANDLERS connectionHandler = () => { }; disconnectionHandler = () => { }; messageHandler = (data) => { }; mailboxHandler = (mailboxId) => { }; mailboxConnectionHandler = (mailboxId) => { }; mailboxDeleteHandler = (mailboxId) => { }; // INIT set onconnect(handler) { this.connectionHandler = handler; } set ondisconnect(handler) { this.disconnectionHandler = handler; } set onmessage(handler) { this.messageHandler = handler; } set onmailboxcreate(handler) { this.mailboxHandler = handler; } set onmailboxconnect(handler) { this.mailboxConnectionHandler = handler; } set onmailboxdelete(handler) { this.mailboxDeleteHandler = handler; } // UTILITY METHODS send(messageObject) { if (this.ws == void 0) return false; const messageString = JSON.stringify(messageObject); this.ws.send(messageString); return true; } // PUBLIC METHODS // connection connect(address) { try { this.disconnect(); this.ws = new WebSocket(address); this.ws.addEventListener("open", this.connectionHandler); this.ws.addEventListener("close", this.disconnectionHandler); this.ws.addEventListener("message", (message) => { const dataString = message.data.toString(); const data = JSON.parse(dataString); if (data.assignedMailboxId) { return this.mailboxHandler(data.assignedMailboxId); } else if (data.connectedMailboxId) { return this.mailboxConnectionHandler(data.connectedMailboxId); } else if (data.deletedMailbox) { return this.mailboxDeleteHandler(data.deletedMailbox); } else { this.messageHandler(data); } }); } catch (error) { console.error(error); } } disconnect() { this.ws?.close(); } // message sendMessage(channel, body) { const messageObject = { messageChannel: channel, messageBody: body }; return this.send(messageObject); } // subscription subscribe(channel) { const messageObject = { subscribeChannel: channel }; return this.send(messageObject); } unsubscribe(channel) { const messageObject = { unsubscribeChannel: channel }; return this.send(messageObject); } // mailbox requestMailbox() { const messageObject = { requestingMailboxSetup: true }; return this.send(messageObject); } connectMailbox(mailboxId) { const messageObject = { requestedMailbox: mailboxId }; return this.send(messageObject); } deleteMailbox(mailboxId) { const messageObject = { deletingMailbox: mailboxId }; return this.send(messageObject); } }; // src/Model/Utility/utility.ts function stringify(data) { return JSON.stringify(data); } function parse(string) { return JSON.parse(string); } // src/Model/connectionModel.ts var ConnectionModel = class { // basic udn; // data get isConnected() { return this.udn.ws != void 0 && this.udn.ws.readyState == 1; } get address() { return this.udn.ws?.url; } // connection connect = (address) => { this.udn.connect(address); }; disconnect = () => { this.udn.disconnect(); }; handleConnectionChange = () => { console.log("connection status:", this.isConnected, this.address); }; // messaging sendChatMessage = (chatMessage) => { const stringifiedBody = stringify(chatMessage); return this.udn.sendMessage(chatMessage.channel, stringifiedBody); }; // setup constructor(configuration) { this.udn = new UDNFrontend(); this.udn.onmessage = (data) => { configuration.messageHandler(data); }; this.udn.onconnect = () => { this.handleConnectionChange(); configuration.connectionChangeHandler(); }; this.udn.ondisconnect = () => { this.handleConnectionChange(); configuration.connectionChangeHandler(); }; } }; // node_modules/bloatless-react/index.ts function createElement(tagName, attributes = {}, ...children) { const element = document.createElement(tagName); if (attributes != null) Object.entries(attributes).forEach((entry) => { const [attributename, value] = entry; const [directiveKey, directiveValue] = attributename.split(":"); switch (directiveKey) { case "on": { switch (directiveValue) { case "enter": { element.addEventListener("keydown", (e) => { if (e.key != "Enter") return; value(); }); break; } default: { element.addEventListener(directiveValue, value); } } break; } case "subscribe": { const state = value; state.subscribe( (newValue) => element[directiveValue] = newValue ); break; } case "bind": { const state = value; state.subscribe( (newValue) => element[directiveValue] = newValue ); element.addEventListener( "input", () => state.value = element[directiveValue] ); break; } case "toggle": { if (value.subscribe) { const state = value; state.subscribe( (newValue) => element.toggleAttribute(directiveValue, newValue) ); } else { element.toggleAttribute(directiveValue, value); } break; } case "set": { const state = value; state.subscribe( (newValue) => element.setAttribute(directiveValue, newValue) ); break; } case "children": { switch (directiveValue) { case "set": { const state = value; state.subscribe((newValue) => { element.innerHTML = ""; element.append(...[newValue].flat()); }); break; } case "append": case "appendandscroll": case "prepend": { element.style.scrollBehavior = "smooth"; try { const [listState, toElement] = value; listState.handleAddition((newItem) => { const child = toElement(newItem); listState.handleRemoval( newItem, () => child.remove() ); if (directiveValue == "append") { element.append(child); } else if (directiveValue == "prepend") { element.prepend(child); } }); } catch { throw `error: cannot process subscribe:children directive because StateItemConverter is not defined. Usage: "subscribe:children={[list, converter]}"; you can find a more detailed example in the documentation`; } } } } default: element.setAttribute(attributename, value); } }); children.filter((x) => x).forEach((child) => element.append(child)); return element; } // src/View/translations.ts var englishTranslations = { general: { closeButton: "close" }, homePage: { appName: "Comms", /// overviewHeadline: "Overview", statusHeadline: "Status", settingsButton: "Settings", /// chatsHeadline: "Chats", addChatAudioLabel: "name of new chat", addChatPlaceholder: "Add chat", addChatButton: "Add chat" }, settings: { settingsHeadline: "Settings" /// } }; var allTranslations = { en: englishTranslations }; var language = navigator.language.substring(0, 2); var translations = allTranslations[language] || allTranslations.en; // src/View/homePage.tsx function HomePage() { return /* @__PURE__ */ createElement("article", { id: "home-page" }, /* @__PURE__ */ createElement("header", null, /* @__PURE__ */ createElement("span", null, translations.homePage.appName)), /* @__PURE__ */ createElement("div", null, /* @__PURE__ */ createElement("div", { id: "overview-section" }, /* @__PURE__ */ createElement("h2", null, translations.homePage.overviewHeadline), /* @__PURE__ */ createElement("div", { class: "tile flex-no" }, /* @__PURE__ */ createElement("span", { class: "icon" }, "cell_tower"), /* @__PURE__ */ createElement("div", null, /* @__PURE__ */ createElement("h3", null, translations.homePage.statusHeadline))), /* @__PURE__ */ createElement("button", { class: "tile flex-no" }, /* @__PURE__ */ createElement("span", { class: "icon" }, "settings"), /* @__PURE__ */ createElement("div", null, translations.homePage.settingsButton))), /* @__PURE__ */ createElement("div", { id: "chat-section" }, /* @__PURE__ */ createElement("h2", null, translations.homePage.chatsHeadline), /* @__PURE__ */ createElement("div", { class: "flex-row width-input" }, /* @__PURE__ */ createElement( "input", { placeholder: translations.homePage.addChatPlaceholder, "aria-label": translations.homePage.addChatAudioLabel } ), /* @__PURE__ */ createElement( "button", { class: "primary", "aria-label": translations.homePage.addChatButton }, /* @__PURE__ */ createElement("span", { class: "icon" }, "add") ))))); } // src/Model/Utility/typeSafety.ts var DATA_VERSION = "v2"; // src/Model/storageModel.ts var StorageModel = class _StorageModel { storageEntryTree = {}; // basic store = (key, value) => { localStorage.setItem(key, value); const pathComponents = _StorageModel.keyToPathComponents(key); this.updateTree(...pathComponents); }; restore = (key) => { return localStorage.getItem(key); }; remove = (key) => { localStorage.removeItem(key); }; list = (key) => { const pathComponents = _StorageModel.keyToPathComponents(key); let currentParent = this.storageEntryTree; for (const component of pathComponents) { const nextParent = currentParent[component]; if (nextParent == void 0) return []; currentParent = nextParent; } return [...Object.keys(currentParent)]; }; // stringifiable storeStringifiable = (key, value) => { const valueString = stringify(value); this.store(key, valueString); }; restoreStringifiable = (key) => { const valueString = this.restore(key); if (!valueString) return null; return parse(valueString); }; // init constructor() { for (const key of Object.keys(localStorage)) { const components = _StorageModel.keyToPathComponents(key); this.updateTree(...components); } } // utility updateTree = (...pathComponents) => { let currentParent = this.storageEntryTree; for (const pathPart of pathComponents) { if (!currentParent[pathPart]) { currentParent[pathPart] = {}; } currentParent = currentParent[pathPart]; } }; static pathComponentsToKey = (...pathComponents) => { return pathComponents.join("/"); }; static keyToPathComponents = (key) => { return key.split("/"); }; static join = (...items) => { let allComponents = []; for (const item of items) { const parts = this.keyToPathComponents(item); allComponents.push(...parts); } return _StorageModel.pathComponentsToKey(...allComponents); }; }; var storageKeys = { // connection socketAddress: `${DATA_VERSION}/connection/socket-address`, // settings userName: `${DATA_VERSION}/settings/user-name`, firstDayOfWeek: `${DATA_VERSION}/settings/first-day-of-week`, // history previousAddresses: `${DATA_VERSION}/history/previous-addresses`, previousObjectCategories: `${DATA_VERSION}/history/object-categories`, previousObjectStatuses: `${DATA_VERSION}/history/object-statuses`, previousObjectFilters: `${DATA_VERSION}/history/object-filters`, // chat etc chatInfo: (id) => `${DATA_VERSION}/chat/${id}/info`, chatMessages: (id) => `${DATA_VERSION}/chat/${id}/messages`, chatObjects: (id) => `${DATA_VERSION}/chat/${id}/objects`, chatOutbox: (id) => `${DATA_VERSION}/chat/${id}/outbox` }; // src/index.tsx var storageModel = new StorageModel(); var connectionModel = new ConnectionModel({ connectionChangeHandler() { }, messageHandler(data) { } }); document.querySelector("main").append(HomePage()); })();