handle disconnection on frontend
This commit is contained in:
@@ -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).
|
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.
|
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
|
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)
|
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)
|
3. Install [udn-frontend](https://github.com/marlon-erler/udn-frontend) and read the docs
|
||||||
4. Start developing
|
4. Generate your app icon [here](https://icongen.onrender.com/), move it to the `dist` directory
|
||||||
|
5. Start developing
|
||||||
|
|
||||||
## Manual way
|
## Manual way
|
||||||
|
|
||||||
|
|||||||
Vendored
BIN
Binary file not shown.
|
Before Width: | Height: | Size: 4.4 KiB |
Vendored
BIN
Binary file not shown.
|
Before Width: | Height: | Size: 38 KiB After Width: | Height: | Size: 33 KiB |
Vendored
+2
-1
@@ -1,6 +1,6 @@
|
|||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<title>UDN Server</title>
|
<title>My App</title>
|
||||||
|
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<meta
|
<meta
|
||||||
@@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
<link rel="stylesheet" href="styles.css" />
|
<link rel="stylesheet" href="styles.css" />
|
||||||
<link rel="manifest" href="manifest.json" />
|
<link rel="manifest" href="manifest.json" />
|
||||||
|
<link rel="icon" href="icon.png" />
|
||||||
<script src="support.js" defer></script>
|
<script src="support.js" defer></script>
|
||||||
|
|
||||||
<script src="index.js" defer></script>
|
<script src="index.js" defer></script>
|
||||||
|
|||||||
Vendored
+18
@@ -245,6 +245,8 @@
|
|||||||
var staticTextEnglish = {
|
var staticTextEnglish = {
|
||||||
channel: "Channel",
|
channel: "Channel",
|
||||||
channel_placeholder: "my-channel",
|
channel_placeholder: "my-channel",
|
||||||
|
disconnected: "Server disconnected",
|
||||||
|
reconnecting: "Reconnecting...",
|
||||||
info: "Info",
|
info: "Info",
|
||||||
message: "Message",
|
message: "Message",
|
||||||
messages: "Messages",
|
messages: "Messages",
|
||||||
@@ -265,6 +267,8 @@
|
|||||||
es: {
|
es: {
|
||||||
channel: "Canal",
|
channel: "Canal",
|
||||||
channel_placeholder: "mi-canal",
|
channel_placeholder: "mi-canal",
|
||||||
|
disconnected: "Sin conneci\xF3n",
|
||||||
|
reconnecting: "Conectando...",
|
||||||
info: "Info",
|
info: "Info",
|
||||||
message: "Mensaje",
|
message: "Mensaje",
|
||||||
messages: "Mensajes",
|
messages: "Mensajes",
|
||||||
@@ -283,6 +287,8 @@
|
|||||||
de: {
|
de: {
|
||||||
channel: "Kanal",
|
channel: "Kanal",
|
||||||
channel_placeholder: "mein-kanal",
|
channel_placeholder: "mein-kanal",
|
||||||
|
disconnected: "Verbindung getrennt",
|
||||||
|
reconnecting: "Verbindung wird hergestellt...",
|
||||||
info: "Daten",
|
info: "Daten",
|
||||||
message: "Nachricht",
|
message: "Nachricht",
|
||||||
messages: "Nachrichten",
|
messages: "Nachrichten",
|
||||||
@@ -316,6 +322,7 @@
|
|||||||
};
|
};
|
||||||
var UDN = new UDNFrontend();
|
var UDN = new UDNFrontend();
|
||||||
UDN.onconnect = () => {
|
UDN.onconnect = () => {
|
||||||
|
isDisconnected.value = false;
|
||||||
updateStats();
|
updateStats();
|
||||||
};
|
};
|
||||||
UDN.onmessage = (data) => {
|
UDN.onmessage = (data) => {
|
||||||
@@ -326,7 +333,15 @@
|
|||||||
if (messageBody) messages.add(messageObject);
|
if (messageBody) messages.add(messageObject);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
UDN.ondisconnect = () => {
|
||||||
|
isDisconnected.value = true;
|
||||||
|
setTimeout(connect, 2e3);
|
||||||
|
};
|
||||||
|
function connect() {
|
||||||
UDN.connect(`ws://${window.location.host}`);
|
UDN.connect(`ws://${window.location.host}`);
|
||||||
|
}
|
||||||
|
connect();
|
||||||
|
var isDisconnected = new State(true);
|
||||||
var messages = new ListState();
|
var messages = new ListState();
|
||||||
var lastReceivedMessage = new State(
|
var lastReceivedMessage = new State(
|
||||||
getText("noMessagesReceived")
|
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")))
|
/* @__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.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"))))))
|
||||||
|
);
|
||||||
})();
|
})();
|
||||||
|
|||||||
Vendored
+1
-1
@@ -3,7 +3,7 @@
|
|||||||
"display": "standalone",
|
"display": "standalone",
|
||||||
"icons": [
|
"icons": [
|
||||||
{
|
{
|
||||||
"src": "favicon.ico",
|
"src": "icon.png",
|
||||||
"sizes": "any"
|
"sizes": "any"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
Vendored
+8
-1
@@ -279,6 +279,7 @@ select {
|
|||||||
header,
|
header,
|
||||||
menu {
|
menu {
|
||||||
backdrop-filter: blur(70px);
|
backdrop-filter: blur(70px);
|
||||||
|
-webkit-backdrop-filter: blur(70px);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* border, outline, etc */
|
/* border, outline, etc */
|
||||||
@@ -604,6 +605,7 @@ select + .icon,
|
|||||||
article,
|
article,
|
||||||
main,
|
main,
|
||||||
select + .icon,
|
select + .icon,
|
||||||
|
.height-100,
|
||||||
.modal > div,
|
.modal > div,
|
||||||
.modal main {
|
.modal main {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
@@ -757,12 +759,17 @@ body {
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body,
|
||||||
|
.modal {
|
||||||
padding-left: var(--safe-area-left);
|
padding-left: var(--safe-area-left);
|
||||||
padding-right: var(--safe-area-right);
|
padding-right: var(--safe-area-right);
|
||||||
padding-top: var(--safe-area-top);
|
padding-top: var(--safe-area-top);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.modal {
|
||||||
|
padding-bottom: var(--safe-area-bottom);
|
||||||
|
}
|
||||||
|
|
||||||
menu {
|
menu {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: var(--menu-height-mobile);
|
height: var(--menu-height-mobile);
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { InfoScreen } from "./infoScreen";
|
|||||||
import { MainScreen } from "./mainScreen";
|
import { MainScreen } from "./mainScreen";
|
||||||
import { MessageScreen } from "./messageScreen";
|
import { MessageScreen } from "./messageScreen";
|
||||||
import { getText } from "./translations";
|
import { getText } from "./translations";
|
||||||
|
import { isDisconnected } from "./model";
|
||||||
|
|
||||||
// WS
|
// WS
|
||||||
document.body.prepend(
|
document.body.prepend(
|
||||||
@@ -25,3 +26,18 @@ document.body.prepend(
|
|||||||
document
|
document
|
||||||
.querySelector("main")!
|
.querySelector("main")!
|
||||||
.append(InfoScreen(), MainScreen(), MessageScreen());
|
.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
@@ -13,6 +13,7 @@ export class Message implements React.Identifiable {
|
|||||||
const UDN = new UDNFrontend();
|
const UDN = new UDNFrontend();
|
||||||
|
|
||||||
UDN.onconnect = () => {
|
UDN.onconnect = () => {
|
||||||
|
isDisconnected.value = false;
|
||||||
updateStats();
|
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
|
// STATE
|
||||||
|
// connection
|
||||||
|
export const isDisconnected = new React.State(true);
|
||||||
|
|
||||||
// messages
|
// messages
|
||||||
export const messages = new React.ListState<Message>();
|
export const messages = new React.ListState<Message>();
|
||||||
export const lastReceivedMessage = new React.State(
|
export const lastReceivedMessage = new React.State(
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
export const staticTextEnglish = {
|
export const staticTextEnglish = {
|
||||||
channel: "Channel",
|
channel: "Channel",
|
||||||
channel_placeholder: "my-channel",
|
channel_placeholder: "my-channel",
|
||||||
|
disconnected: "Server disconnected",
|
||||||
|
reconnecting: "Reconnecting...",
|
||||||
info: "Info",
|
info: "Info",
|
||||||
message: "Message",
|
message: "Message",
|
||||||
messages: "Messages",
|
messages: "Messages",
|
||||||
@@ -23,6 +25,8 @@ export const translations: { [key: string]: typeof staticTextEnglish } = {
|
|||||||
es: {
|
es: {
|
||||||
channel: "Canal",
|
channel: "Canal",
|
||||||
channel_placeholder: "mi-canal",
|
channel_placeholder: "mi-canal",
|
||||||
|
disconnected: "Sin conneción",
|
||||||
|
reconnecting: "Conectando...",
|
||||||
info: "Info",
|
info: "Info",
|
||||||
message: "Mensaje",
|
message: "Mensaje",
|
||||||
messages: "Mensajes",
|
messages: "Mensajes",
|
||||||
@@ -41,6 +45,8 @@ export const translations: { [key: string]: typeof staticTextEnglish } = {
|
|||||||
de: {
|
de: {
|
||||||
channel: "Kanal",
|
channel: "Kanal",
|
||||||
channel_placeholder: "mein-kanal",
|
channel_placeholder: "mein-kanal",
|
||||||
|
disconnected: "Verbindung getrennt",
|
||||||
|
reconnecting: "Verbindung wird hergestellt...",
|
||||||
info: "Daten",
|
info: "Daten",
|
||||||
message: "Nachricht",
|
message: "Nachricht",
|
||||||
messages: "Nachrichten",
|
messages: "Nachrichten",
|
||||||
|
|||||||
Reference in New Issue
Block a user