handle disconnection on frontend

This commit is contained in:
marlon-erler
2024-07-07 14:02:01 +02:00
parent 9ef5c2f0a2
commit e010de6a30
10 changed files with 70 additions and 9 deletions
+5 -4
View File
@@ -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
BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.4 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 KiB

After

Width:  |  Height:  |  Size: 33 KiB

+2 -1
View File
@@ -1,6 +1,6 @@
<html lang="en">
<head>
<title>UDN Server</title>
<title>My App</title>
<meta charset="UTF-8" />
<meta
@@ -21,6 +21,7 @@
<link rel="stylesheet" href="styles.css" />
<link rel="manifest" href="manifest.json" />
<link rel="icon" href="icon.png" />
<script src="support.js" defer></script>
<script src="index.js" defer></script>
+18
View File
@@ -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.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"))))))
);
})();
+1 -1
View File
@@ -3,7 +3,7 @@
"display": "standalone",
"icons": [
{
"src": "favicon.ico",
"src": "icon.png",
"sizes": "any"
}
]
+8 -1
View File
@@ -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);
+16
View File
@@ -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(
<div class="modal" toggle:open={isDisconnected}>
<div>
<main>
<div class="flex-column align-center justify-center width-100 height-100" style="gap: 1rem">
<span class="icon error" style="font-size: 3rem">
signal_disconnected
</span>
<h1 class="error">{getText("disconnected")}</h1>
<p class="secondary">{getText("reconnecting")}</p>
</div>
</main>
</div>
</div>
);
+13 -1
View File
@@ -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<Message>();
export const lastReceivedMessage = new React.State(
+6
View File
@@ -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",