diff --git a/README.md b/README.md index 8d0b0b6..8ed42cd 100644 --- a/README.md +++ b/README.md @@ -73,10 +73,11 @@ For TypeScript-based apps, you can use the [udn-frontend](https://github.com/mar The web interface of the server itself is based on my other two projects, [carbon-mini](https://github.com/marlon-erler/carbon-mini) and [bloatless-react](https://github.com/marlon-erler/bloatless-react). Both of these projects are very minimal, bloat-free, and quick to get started with. I'd suggest you to build your app based on the same foundation for a consistent user experience. -1. Download [carbon-mini](https://github.com/marlon-erler/carbon-mini) from the releases page -2. Install [bloatless-react](https://github.com/marlon-erler/bloatless-react) -3. Install [udn-frontend](https://github.com/marlon-erler/udn-frontend) -4. Start developing +1. Download [carbon-mini](https://github.com/marlon-erler/carbon-mini) from the releases page and read the docs +2. Install [bloatless-react](https://github.com/marlon-erler/bloatless-react) and read the docs +3. Install [udn-frontend](https://github.com/marlon-erler/udn-frontend) and read the docs +4. Generate your app icon [here](https://icongen.onrender.com/), move it to the `dist` directory +5. Start developing ## Manual way diff --git a/static/dist/favicon.ico b/static/dist/favicon.ico deleted file mode 100644 index a4323fe..0000000 Binary files a/static/dist/favicon.ico and /dev/null differ diff --git a/static/dist/icon.png b/static/dist/icon.png index c57a11d..8c3d9b2 100644 Binary files a/static/dist/icon.png and b/static/dist/icon.png differ diff --git a/static/dist/index.html b/static/dist/index.html index d7950a8..b112b2e 100644 --- a/static/dist/index.html +++ b/static/dist/index.html @@ -1,6 +1,6 @@ - UDN Server + My App + diff --git a/static/dist/index.js b/static/dist/index.js index bf55f32..ca506c1 100644 --- a/static/dist/index.js +++ b/static/dist/index.js @@ -245,6 +245,8 @@ var staticTextEnglish = { channel: "Channel", channel_placeholder: "my-channel", + disconnected: "Server disconnected", + reconnecting: "Reconnecting...", info: "Info", message: "Message", messages: "Messages", @@ -265,6 +267,8 @@ es: { channel: "Canal", channel_placeholder: "mi-canal", + disconnected: "Sin conneci\xF3n", + reconnecting: "Conectando...", info: "Info", message: "Mensaje", messages: "Mensajes", @@ -283,6 +287,8 @@ de: { channel: "Kanal", channel_placeholder: "mein-kanal", + disconnected: "Verbindung getrennt", + reconnecting: "Verbindung wird hergestellt...", info: "Daten", message: "Nachricht", messages: "Nachrichten", @@ -316,6 +322,7 @@ }; var UDN = new UDNFrontend(); UDN.onconnect = () => { + isDisconnected.value = false; updateStats(); }; UDN.onmessage = (data) => { @@ -326,7 +333,15 @@ if (messageBody) messages.add(messageObject); } }; - UDN.connect(`ws://${window.location.host}`); + UDN.ondisconnect = () => { + isDisconnected.value = true; + setTimeout(connect, 2e3); + }; + function connect() { + UDN.connect(`ws://${window.location.host}`); + } + connect(); + var isDisconnected = new State(true); var messages = new ListState(); var lastReceivedMessage = new State( getText("noMessagesReceived") @@ -438,4 +453,7 @@ /* @__PURE__ */ createElement("menu", null, /* @__PURE__ */ createElement("a", { class: "tab-link", href: "#info-screen", active: true }, /* @__PURE__ */ createElement("span", { class: "icon" }, "info"), getText("info")), /* @__PURE__ */ createElement("a", { class: "tab-link", href: "#main-screen" }, /* @__PURE__ */ createElement("span", { class: "icon" }, "settings"), getText("settings")), /* @__PURE__ */ createElement("a", { class: "tab-link", href: "#message-screen" }, /* @__PURE__ */ createElement("span", { class: "icon" }, "chat"), getText("messages"))) ); document.querySelector("main").append(InfoScreen(), MainScreen(), MessageScreen()); + document.body.append( + /* @__PURE__ */ createElement("div", { class: "modal", "toggle:open": isDisconnected }, /* @__PURE__ */ createElement("div", null, /* @__PURE__ */ createElement("main", null, /* @__PURE__ */ createElement("div", { class: "flex-column align-center justify-center width-100 height-100", style: "gap: 1rem" }, /* @__PURE__ */ createElement("span", { class: "icon error", style: "font-size: 3rem" }, "signal_disconnected"), /* @__PURE__ */ createElement("h1", { class: "error" }, getText("disconnected")), /* @__PURE__ */ createElement("p", { class: "secondary" }, getText("reconnecting")))))) + ); })(); diff --git a/static/dist/manifest.json b/static/dist/manifest.json index ec84f7f..1ed9dea 100644 --- a/static/dist/manifest.json +++ b/static/dist/manifest.json @@ -3,7 +3,7 @@ "display": "standalone", "icons": [ { - "src": "favicon.ico", + "src": "icon.png", "sizes": "any" } ] diff --git a/static/dist/styles.css b/static/dist/styles.css index c5a98a1..05382cf 100644 --- a/static/dist/styles.css +++ b/static/dist/styles.css @@ -279,6 +279,7 @@ select { header, menu { backdrop-filter: blur(70px); + -webkit-backdrop-filter: blur(70px); } /* border, outline, etc */ @@ -604,6 +605,7 @@ select + .icon, article, main, select + .icon, +.height-100, .modal > div, .modal main { height: 100%; @@ -757,12 +759,17 @@ body { height: 100%; } -body { +body, +.modal { padding-left: var(--safe-area-left); padding-right: var(--safe-area-right); padding-top: var(--safe-area-top); } +.modal { + padding-bottom: var(--safe-area-bottom); +} + menu { width: 100%; height: var(--menu-height-mobile); diff --git a/static/src/index.tsx b/static/src/index.tsx index 1dc3e33..2e33016 100644 --- a/static/src/index.tsx +++ b/static/src/index.tsx @@ -4,6 +4,7 @@ import { InfoScreen } from "./infoScreen"; import { MainScreen } from "./mainScreen"; import { MessageScreen } from "./messageScreen"; import { getText } from "./translations"; +import { isDisconnected } from "./model"; // WS document.body.prepend( @@ -25,3 +26,18 @@ document.body.prepend( document .querySelector("main")! .append(InfoScreen(), MainScreen(), MessageScreen()); +document.body.append( + +); diff --git a/static/src/model.tsx b/static/src/model.tsx index 78bc064..4259e42 100644 --- a/static/src/model.tsx +++ b/static/src/model.tsx @@ -13,6 +13,7 @@ export class Message implements React.Identifiable { const UDN = new UDNFrontend(); UDN.onconnect = () => { + isDisconnected.value = false; updateStats(); }; @@ -26,9 +27,20 @@ UDN.onmessage = (data) => { } }; -UDN.connect(`ws://${window.location.host}`) +UDN.ondisconnect = () => { + isDisconnected.value = true; + setTimeout(connect, 2000); +}; + +function connect() { + UDN.connect(`ws://${window.location.host}`); +} +connect(); // STATE +// connection +export const isDisconnected = new React.State(true); + // messages export const messages = new React.ListState(); export const lastReceivedMessage = new React.State( diff --git a/static/src/translations.tsx b/static/src/translations.tsx index c776f34..db2e8e0 100644 --- a/static/src/translations.tsx +++ b/static/src/translations.tsx @@ -2,6 +2,8 @@ export const staticTextEnglish = { channel: "Channel", channel_placeholder: "my-channel", + disconnected: "Server disconnected", + reconnecting: "Reconnecting...", info: "Info", message: "Message", messages: "Messages", @@ -23,6 +25,8 @@ export const translations: { [key: string]: typeof staticTextEnglish } = { es: { channel: "Canal", channel_placeholder: "mi-canal", + disconnected: "Sin conneción", + reconnecting: "Conectando...", info: "Info", message: "Mensaje", messages: "Mensajes", @@ -41,6 +45,8 @@ export const translations: { [key: string]: typeof staticTextEnglish } = { de: { channel: "Kanal", channel_placeholder: "mein-kanal", + disconnected: "Verbindung getrennt", + reconnecting: "Verbindung wird hergestellt...", info: "Daten", message: "Nachricht", messages: "Nachrichten",