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(
+
+
+
+
+
+ signal_disconnected
+
+
{getText("disconnected")}
+
{getText("reconnecting")}
+
+
+
+
+);
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",