change mailbox behaviour to use reception confirmations
This commit is contained in:
@@ -147,8 +147,8 @@ As you can see, there are many ways to connect multiple servers and communicate
|
|||||||
Anyone can develop apps for the UDN project. Examples of such apps are listed below. If you have developed an app for the UDN project and you want your app to be listed here, create an issue.
|
Anyone can develop apps for the UDN project. Examples of such apps are listed below. If you have developed an app for the UDN project and you want your app to be listed here, create an issue.
|
||||||
|
|
||||||
| App Name | Description | Links |
|
| App Name | Description | Links |
|
||||||
| -- | -- | -- |
|
| -------- | ----------------- | ---------------------------------------------------------------------------------------------------- |
|
||||||
| Comms | Messenger for UDN | [more info](https://github.com/marlon-erler/udn-comms/) - [install](https://udn-comms.onrender.com/)
|
| Comms | Messenger for UDN | [more info](https://github.com/marlon-erler/udn-comms/) - [install](https://udn-comms.onrender.com/) |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -119,11 +119,12 @@ async function main() {
|
|||||||
|
|
||||||
// CLI
|
// CLI
|
||||||
function updateCLI() {
|
function updateCLI() {
|
||||||
|
return;
|
||||||
console.clear();
|
console.clear();
|
||||||
|
|
||||||
console.log(Colors.bold.bgWhite("UNIVERSAL DECENTRALIZED NETWORK"));
|
console.log(Colors.bold.bgWhite("UNIVERSAL DECENTRALIZED NETWORK"));
|
||||||
console.log(
|
console.log(
|
||||||
Colors.yellow("relevant output is available in the 'logs' file")
|
Colors.yellow("relevant output is available in the 'logs' file"),
|
||||||
);
|
);
|
||||||
console.log();
|
console.log();
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "udn",
|
"name": "udn",
|
||||||
"version": "1.0.0-beta14",
|
"version": "1.0.0-beta15",
|
||||||
"description": "A websocket-based infrastructure for decentralized networks ",
|
"description": "A websocket-based infrastructure for decentralized networks ",
|
||||||
"bin": {
|
"bin": {
|
||||||
"start": "index.ts"
|
"start": "index.ts"
|
||||||
|
|||||||
Vendored
+341
-91
@@ -73,8 +73,8 @@
|
|||||||
};
|
};
|
||||||
function createProxyState(statesToSubscibe, fn) {
|
function createProxyState(statesToSubscibe, fn) {
|
||||||
const proxyState = new State(fn());
|
const proxyState = new State(fn());
|
||||||
statesToSubscibe.forEach(
|
statesToSubscibe.forEach((state) =>
|
||||||
(state) => state.subscribe(() => proxyState.value = fn())
|
state.subscribe(() => (proxyState.value = fn())),
|
||||||
);
|
);
|
||||||
return proxyState;
|
return proxyState;
|
||||||
}
|
}
|
||||||
@@ -85,7 +85,9 @@
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
function restoreState(localStorageKey, initialStateValue) {
|
function restoreState(localStorageKey, initialStateValue) {
|
||||||
const storedString = localStorage.getItem(localStorageKey) ?? JSON.stringify(initialStateValue);
|
const storedString =
|
||||||
|
localStorage.getItem(localStorageKey) ??
|
||||||
|
JSON.stringify(initialStateValue);
|
||||||
const convertedValue = JSON.parse(storedString);
|
const convertedValue = JSON.parse(storedString);
|
||||||
const state = new State(convertedValue);
|
const state = new State(convertedValue);
|
||||||
persistState(localStorageKey, state);
|
persistState(localStorageKey, state);
|
||||||
@@ -120,9 +122,8 @@
|
|||||||
const [listState, toElement] = value;
|
const [listState, toElement] = value;
|
||||||
listState.handleAddition((newItem) => {
|
listState.handleAddition((newItem) => {
|
||||||
const child = toElement(newItem);
|
const child = toElement(newItem);
|
||||||
listState.handleRemoval(
|
listState.handleRemoval(newItem, () =>
|
||||||
newItem,
|
child.remove(),
|
||||||
() => child.remove()
|
|
||||||
);
|
);
|
||||||
element.append(child);
|
element.append(child);
|
||||||
element.scrollTop = element.scrollHeight;
|
element.scrollTop = element.scrollHeight;
|
||||||
@@ -133,7 +134,8 @@
|
|||||||
} else {
|
} else {
|
||||||
const state = value;
|
const state = value;
|
||||||
state.subscribe(
|
state.subscribe(
|
||||||
(newValue) => element[directiveValue] = newValue
|
(newValue) =>
|
||||||
|
(element[directiveValue] = newValue),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -141,19 +143,22 @@
|
|||||||
case "bind": {
|
case "bind": {
|
||||||
const state = value;
|
const state = value;
|
||||||
state.subscribe(
|
state.subscribe(
|
||||||
(newValue) => element[directiveValue] = newValue
|
(newValue) => (element[directiveValue] = newValue),
|
||||||
);
|
);
|
||||||
element.addEventListener(
|
element.addEventListener(
|
||||||
"input",
|
"input",
|
||||||
() => state.value = element[directiveValue]
|
() => (state.value = element[directiveValue]),
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "toggle": {
|
case "toggle": {
|
||||||
if (value.subscribe) {
|
if (value.subscribe) {
|
||||||
const state = value;
|
const state = value;
|
||||||
state.subscribe(
|
state.subscribe((newValue) =>
|
||||||
(newValue) => element.toggleAttribute(directiveValue, newValue)
|
element.toggleAttribute(
|
||||||
|
directiveValue,
|
||||||
|
newValue,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
element.toggleAttribute(directiveValue, value);
|
element.toggleAttribute(directiveValue, value);
|
||||||
@@ -162,8 +167,8 @@
|
|||||||
}
|
}
|
||||||
case "set": {
|
case "set": {
|
||||||
const state = value;
|
const state = value;
|
||||||
state.subscribe(
|
state.subscribe((newValue) =>
|
||||||
(newValue) => element.setAttribute(directiveValue, newValue)
|
element.setAttribute(directiveValue, newValue),
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -179,18 +184,12 @@
|
|||||||
var UDNFrontend = class {
|
var UDNFrontend = class {
|
||||||
ws;
|
ws;
|
||||||
// HANDLERS
|
// HANDLERS
|
||||||
connectionHandler = () => {
|
connectionHandler = () => {};
|
||||||
};
|
disconnectionHandler = () => {};
|
||||||
disconnectionHandler = () => {
|
messageHandler = (data) => {};
|
||||||
};
|
mailboxHandler = (mailboxId2) => {};
|
||||||
messageHandler = (data) => {
|
mailboxConnectionHandler = (mailboxId2) => {};
|
||||||
};
|
mailboxDeleteHandler = (mailboxId2) => {};
|
||||||
mailboxHandler = (mailboxId2) => {
|
|
||||||
};
|
|
||||||
mailboxConnectionHandler = (mailboxId2) => {
|
|
||||||
};
|
|
||||||
mailboxDeleteHandler = (mailboxId2) => {
|
|
||||||
};
|
|
||||||
// INIT
|
// INIT
|
||||||
set onconnect(handler) {
|
set onconnect(handler) {
|
||||||
this.connectionHandler = handler;
|
this.connectionHandler = handler;
|
||||||
@@ -231,7 +230,9 @@
|
|||||||
if (data.assignedMailboxId) {
|
if (data.assignedMailboxId) {
|
||||||
return this.mailboxHandler(data.assignedMailboxId);
|
return this.mailboxHandler(data.assignedMailboxId);
|
||||||
} else if (data.connectedMailboxId) {
|
} else if (data.connectedMailboxId) {
|
||||||
return this.mailboxConnectionHandler(data.connectedMailboxId);
|
return this.mailboxConnectionHandler(
|
||||||
|
data.connectedMailboxId,
|
||||||
|
);
|
||||||
} else if (data.deletedMailbox) {
|
} else if (data.deletedMailbox) {
|
||||||
return this.mailboxDeleteHandler(data.deletedMailbox);
|
return this.mailboxDeleteHandler(data.deletedMailbox);
|
||||||
} else {
|
} else {
|
||||||
@@ -249,39 +250,39 @@
|
|||||||
sendMessage(channel, body) {
|
sendMessage(channel, body) {
|
||||||
const messageObject = {
|
const messageObject = {
|
||||||
messageChannel: channel,
|
messageChannel: channel,
|
||||||
messageBody: body
|
messageBody: body,
|
||||||
};
|
};
|
||||||
return this.send(messageObject);
|
return this.send(messageObject);
|
||||||
}
|
}
|
||||||
// subscription
|
// subscription
|
||||||
subscribe(channel) {
|
subscribe(channel) {
|
||||||
const messageObject = {
|
const messageObject = {
|
||||||
subscribeChannel: channel
|
subscribeChannel: channel,
|
||||||
};
|
};
|
||||||
return this.send(messageObject);
|
return this.send(messageObject);
|
||||||
}
|
}
|
||||||
unsubscribe(channel) {
|
unsubscribe(channel) {
|
||||||
const messageObject = {
|
const messageObject = {
|
||||||
unsubscribeChannel: channel
|
unsubscribeChannel: channel,
|
||||||
};
|
};
|
||||||
return this.send(messageObject);
|
return this.send(messageObject);
|
||||||
}
|
}
|
||||||
// mailbox
|
// mailbox
|
||||||
requestMailbox() {
|
requestMailbox() {
|
||||||
const messageObject = {
|
const messageObject = {
|
||||||
requestingMailboxSetup: true
|
requestingMailboxSetup: true,
|
||||||
};
|
};
|
||||||
return this.send(messageObject);
|
return this.send(messageObject);
|
||||||
}
|
}
|
||||||
connectMailbox(mailboxId2) {
|
connectMailbox(mailboxId2) {
|
||||||
const messageObject = {
|
const messageObject = {
|
||||||
requestedMailbox: mailboxId2
|
requestedMailbox: mailboxId2,
|
||||||
};
|
};
|
||||||
return this.send(messageObject);
|
return this.send(messageObject);
|
||||||
}
|
}
|
||||||
deleteMailbox(mailboxId2) {
|
deleteMailbox(mailboxId2) {
|
||||||
const messageObject = {
|
const messageObject = {
|
||||||
deletingMailbox: mailboxId2
|
deletingMailbox: mailboxId2,
|
||||||
};
|
};
|
||||||
return this.send(messageObject);
|
return this.send(messageObject);
|
||||||
}
|
}
|
||||||
@@ -310,7 +311,7 @@
|
|||||||
settings: "Settings",
|
settings: "Settings",
|
||||||
subscribeToChannel: "Subscribe to channel",
|
subscribeToChannel: "Subscribe to channel",
|
||||||
subscribe: "Subscribe",
|
subscribe: "Subscribe",
|
||||||
unsubscribe: "Unubscribe"
|
unsubscribe: "Unubscribe",
|
||||||
};
|
};
|
||||||
var allTranslations = {
|
var allTranslations = {
|
||||||
en: staticTextEnglish,
|
en: staticTextEnglish,
|
||||||
@@ -336,7 +337,7 @@
|
|||||||
settings: "Configuraci\xF3n",
|
settings: "Configuraci\xF3n",
|
||||||
subscribeToChannel: "Suscribirse a un canal",
|
subscribeToChannel: "Suscribirse a un canal",
|
||||||
subscribe: "Suscribirse",
|
subscribe: "Suscribirse",
|
||||||
unsubscribe: "Cancelar"
|
unsubscribe: "Cancelar",
|
||||||
},
|
},
|
||||||
de: {
|
de: {
|
||||||
mailbox: "Briefkasten",
|
mailbox: "Briefkasten",
|
||||||
@@ -360,8 +361,8 @@
|
|||||||
settings: "Einstellungen",
|
settings: "Einstellungen",
|
||||||
subscribeToChannel: "Kanal beitreten",
|
subscribeToChannel: "Kanal beitreten",
|
||||||
subscribe: "Beitreten",
|
subscribe: "Beitreten",
|
||||||
unsubscribe: "Verlassen"
|
unsubscribe: "Verlassen",
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
var language = navigator.language.substring(0, 2);
|
var language = navigator.language.substring(0, 2);
|
||||||
var translations = allTranslations[language];
|
var translations = allTranslations[language];
|
||||||
@@ -377,18 +378,25 @@
|
|||||||
var mailboxId = restoreState("mailbox-id", "");
|
var mailboxId = restoreState("mailbox-id", "");
|
||||||
var isMailboxDisonnected = new State(true);
|
var isMailboxDisonnected = new State(true);
|
||||||
var messages = new ListState();
|
var messages = new ListState();
|
||||||
var lastReceivedMessage = new State(
|
var lastReceivedMessage = new State(translations.noMessagesReceived);
|
||||||
translations.noMessagesReceived
|
|
||||||
);
|
|
||||||
var statHTMLString = new State("");
|
var statHTMLString = new State("");
|
||||||
async function updateStats() {
|
async function updateStats() {
|
||||||
const response = await fetch(
|
const response = await fetch(
|
||||||
`${window.location.protocol}//${window.location.host}/stats`
|
`${window.location.protocol}//${window.location.host}/stats`,
|
||||||
);
|
);
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
let html = "";
|
let html = "";
|
||||||
data.forEach((item) => {
|
data.forEach((item) => {
|
||||||
const tile = /* @__PURE__ */ createElement("div", { class: "tile" }, /* @__PURE__ */ createElement("span", { class: "secondary flex width-100" }, item[0].toString()), /* @__PURE__ */ createElement("b", null, item[1].toString()));
|
const tile = /* @__PURE__ */ createElement(
|
||||||
|
"div",
|
||||||
|
{ class: "tile" },
|
||||||
|
/* @__PURE__ */ createElement(
|
||||||
|
"span",
|
||||||
|
{ class: "secondary flex width-100" },
|
||||||
|
item[0].toString(),
|
||||||
|
),
|
||||||
|
/* @__PURE__ */ createElement("b", null, item[1].toString()),
|
||||||
|
);
|
||||||
html += tile.outerHTML;
|
html += tile.outerHTML;
|
||||||
});
|
});
|
||||||
statHTMLString.value = html;
|
statHTMLString.value = html;
|
||||||
@@ -398,7 +406,7 @@
|
|||||||
var newMessageBody = new State("");
|
var newMessageBody = new State("");
|
||||||
var isMessageEmpty = createProxyState(
|
var isMessageEmpty = createProxyState(
|
||||||
[newMessageChannel, newMessageBody],
|
[newMessageChannel, newMessageBody],
|
||||||
() => newMessageChannel.value == "" || newMessageBody.value == ""
|
() => newMessageChannel.value == "" || newMessageBody.value == "",
|
||||||
);
|
);
|
||||||
var UDN = new UDNFrontend();
|
var UDN = new UDNFrontend();
|
||||||
UDN.onconnect = () => {
|
UDN.onconnect = () => {
|
||||||
@@ -434,7 +442,7 @@
|
|||||||
};
|
};
|
||||||
function connect() {
|
function connect() {
|
||||||
UDN.connect(
|
UDN.connect(
|
||||||
`${window.location.protocol.replace("http", "ws")}//${window.location.host}`
|
`${window.location.protocol.replace("http", "ws")}//${window.location.host}`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
connect();
|
connect();
|
||||||
@@ -459,106 +467,348 @@
|
|||||||
|
|
||||||
// src/infoScreen.tsx
|
// src/infoScreen.tsx
|
||||||
function InfoScreen() {
|
function InfoScreen() {
|
||||||
return /* @__PURE__ */ createElement("article", { id: "info-screen" }, /* @__PURE__ */ createElement("header", null, translations.serverInfo, /* @__PURE__ */ createElement("span", null, /* @__PURE__ */ createElement("button", { "on:click": updateStats }, /* @__PURE__ */ createElement("span", { class: "icon" }, "refresh")))), /* @__PURE__ */ createElement("div", null, /* @__PURE__ */ createElement("div", { class: "flex-column gap", "subscribe:innerHTML": statHTMLString })));
|
return /* @__PURE__ */ createElement(
|
||||||
|
"article",
|
||||||
|
{ id: "info-screen" },
|
||||||
|
/* @__PURE__ */ createElement(
|
||||||
|
"header",
|
||||||
|
null,
|
||||||
|
translations.serverInfo,
|
||||||
|
/* @__PURE__ */ createElement(
|
||||||
|
"span",
|
||||||
|
null,
|
||||||
|
/* @__PURE__ */ createElement(
|
||||||
|
"button",
|
||||||
|
{ "on:click": updateStats },
|
||||||
|
/* @__PURE__ */ createElement(
|
||||||
|
"span",
|
||||||
|
{ class: "icon" },
|
||||||
|
"refresh",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
/* @__PURE__ */ createElement(
|
||||||
|
"div",
|
||||||
|
null,
|
||||||
|
/* @__PURE__ */ createElement("div", {
|
||||||
|
class: "flex-column gap",
|
||||||
|
"subscribe:innerHTML": statHTMLString,
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// src/mainScreen.tsx
|
// src/mainScreen.tsx
|
||||||
function MainScreen() {
|
function MainScreen() {
|
||||||
return /* @__PURE__ */ createElement("article", { id: "main-screen" }, /* @__PURE__ */ createElement("header", null, translations.settings), /* @__PURE__ */ createElement("div", null, /* @__PURE__ */ createElement("div", { class: "tile width-input" }, /* @__PURE__ */ createElement("div", null, /* @__PURE__ */ createElement("b", null, translations.messageLastReceived), /* @__PURE__ */ createElement("p", { class: "secondary", "subscribe:innerText": lastReceivedMessage }))), /* @__PURE__ */ createElement("hr", null), /* @__PURE__ */ createElement("div", { class: "tile width-input" }, /* @__PURE__ */ createElement("div", null, /* @__PURE__ */ createElement("b", null, translations.mailbox), /* @__PURE__ */ createElement("p", { class: "secondary", "toggle:hidden": isMailboxDisonnected }, translations.mailboxConnected))), /* @__PURE__ */ createElement("div", { class: "flex-row width-input justify-end" }, /* @__PURE__ */ createElement(
|
return /* @__PURE__ */ createElement(
|
||||||
|
"article",
|
||||||
|
{ id: "main-screen" },
|
||||||
|
/* @__PURE__ */ createElement(
|
||||||
|
"header",
|
||||||
|
null,
|
||||||
|
translations.settings,
|
||||||
|
),
|
||||||
|
/* @__PURE__ */ createElement(
|
||||||
|
"div",
|
||||||
|
null,
|
||||||
|
/* @__PURE__ */ createElement(
|
||||||
|
"div",
|
||||||
|
{ class: "tile width-input" },
|
||||||
|
/* @__PURE__ */ createElement(
|
||||||
|
"div",
|
||||||
|
null,
|
||||||
|
/* @__PURE__ */ createElement(
|
||||||
|
"b",
|
||||||
|
null,
|
||||||
|
translations.messageLastReceived,
|
||||||
|
),
|
||||||
|
/* @__PURE__ */ createElement("p", {
|
||||||
|
class: "secondary",
|
||||||
|
"subscribe:innerText": lastReceivedMessage,
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
/* @__PURE__ */ createElement("hr", null),
|
||||||
|
/* @__PURE__ */ createElement(
|
||||||
|
"div",
|
||||||
|
{ class: "tile width-input" },
|
||||||
|
/* @__PURE__ */ createElement(
|
||||||
|
"div",
|
||||||
|
null,
|
||||||
|
/* @__PURE__ */ createElement(
|
||||||
|
"b",
|
||||||
|
null,
|
||||||
|
translations.mailbox,
|
||||||
|
),
|
||||||
|
/* @__PURE__ */ createElement(
|
||||||
|
"p",
|
||||||
|
{
|
||||||
|
class: "secondary",
|
||||||
|
"toggle:hidden": isMailboxDisonnected,
|
||||||
|
},
|
||||||
|
translations.mailboxConnected,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
/* @__PURE__ */ createElement(
|
||||||
|
"div",
|
||||||
|
{ class: "flex-row width-input justify-end" },
|
||||||
|
/* @__PURE__ */ createElement(
|
||||||
"button",
|
"button",
|
||||||
{
|
{
|
||||||
class: "danger width-50",
|
class: "danger width-50",
|
||||||
"on:click": deleteMailbox,
|
"on:click": deleteMailbox,
|
||||||
"toggle:disabled": isMailboxDisonnected
|
"toggle:disabled": isMailboxDisonnected,
|
||||||
},
|
},
|
||||||
translations.deleteMailbox
|
translations.deleteMailbox,
|
||||||
), /* @__PURE__ */ createElement(
|
),
|
||||||
|
/* @__PURE__ */ createElement(
|
||||||
"button",
|
"button",
|
||||||
{
|
{
|
||||||
class: "primary width-50",
|
class: "primary width-50",
|
||||||
"on:click": requestMailbox,
|
"on:click": requestMailbox,
|
||||||
"toggle:disabled": isDisconnected
|
"toggle:disabled": isDisconnected,
|
||||||
},
|
},
|
||||||
translations.requestMailbox,
|
translations.requestMailbox,
|
||||||
/* @__PURE__ */ createElement("span", { class: "icon" }, "inbox")
|
/* @__PURE__ */ createElement(
|
||||||
)), /* @__PURE__ */ createElement("hr", null), /* @__PURE__ */ createElement("label", { class: "tile" }, /* @__PURE__ */ createElement("div", null, /* @__PURE__ */ createElement("span", null, translations.subscribeToChannel), /* @__PURE__ */ createElement(
|
"span",
|
||||||
"input",
|
{ class: "icon" },
|
||||||
{
|
"inbox",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
/* @__PURE__ */ createElement("hr", null),
|
||||||
|
/* @__PURE__ */ createElement(
|
||||||
|
"label",
|
||||||
|
{ class: "tile" },
|
||||||
|
/* @__PURE__ */ createElement(
|
||||||
|
"div",
|
||||||
|
null,
|
||||||
|
/* @__PURE__ */ createElement(
|
||||||
|
"span",
|
||||||
|
null,
|
||||||
|
translations.subscribeToChannel,
|
||||||
|
),
|
||||||
|
/* @__PURE__ */ createElement("input", {
|
||||||
placeholder: translations.channel_placeholder,
|
placeholder: translations.channel_placeholder,
|
||||||
"bind:value": subscriptionChannel,
|
"bind:value": subscriptionChannel,
|
||||||
"on:enter": subscribe
|
"on:enter": subscribe,
|
||||||
}
|
}),
|
||||||
))), /* @__PURE__ */ createElement("div", { class: "flex-row width-input justify-end" }, /* @__PURE__ */ createElement("button", { class: "danger width-50", "on:click": unsubscribe }, translations.unsubscribe), /* @__PURE__ */ createElement("button", { class: "primary width-50", "on:click": subscribe }, translations.subscribe, /* @__PURE__ */ createElement("span", { class: "icon" }, "arrow_forward"))), /* @__PURE__ */ createElement("hr", null), /* @__PURE__ */ createElement("label", { class: "tile" }, /* @__PURE__ */ createElement("div", null, /* @__PURE__ */ createElement("span", null, translations.channel), /* @__PURE__ */ createElement(
|
),
|
||||||
"input",
|
),
|
||||||
{
|
/* @__PURE__ */ createElement(
|
||||||
|
"div",
|
||||||
|
{ class: "flex-row width-input justify-end" },
|
||||||
|
/* @__PURE__ */ createElement(
|
||||||
|
"button",
|
||||||
|
{ class: "danger width-50", "on:click": unsubscribe },
|
||||||
|
translations.unsubscribe,
|
||||||
|
),
|
||||||
|
/* @__PURE__ */ createElement(
|
||||||
|
"button",
|
||||||
|
{ class: "primary width-50", "on:click": subscribe },
|
||||||
|
translations.subscribe,
|
||||||
|
/* @__PURE__ */ createElement(
|
||||||
|
"span",
|
||||||
|
{ class: "icon" },
|
||||||
|
"arrow_forward",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
/* @__PURE__ */ createElement("hr", null),
|
||||||
|
/* @__PURE__ */ createElement(
|
||||||
|
"label",
|
||||||
|
{ class: "tile" },
|
||||||
|
/* @__PURE__ */ createElement(
|
||||||
|
"div",
|
||||||
|
null,
|
||||||
|
/* @__PURE__ */ createElement(
|
||||||
|
"span",
|
||||||
|
null,
|
||||||
|
translations.channel,
|
||||||
|
),
|
||||||
|
/* @__PURE__ */ createElement("input", {
|
||||||
placeholder: translations.channel_placeholder,
|
placeholder: translations.channel_placeholder,
|
||||||
"bind:value": newMessageChannel,
|
"bind:value": newMessageChannel,
|
||||||
"on:enter": sendMessage
|
"on:enter": sendMessage,
|
||||||
}
|
}),
|
||||||
))), /* @__PURE__ */ createElement("label", { class: "tile" }, /* @__PURE__ */ createElement("div", null, /* @__PURE__ */ createElement("span", null, translations.message), /* @__PURE__ */ createElement(
|
),
|
||||||
"input",
|
),
|
||||||
{
|
/* @__PURE__ */ createElement(
|
||||||
|
"label",
|
||||||
|
{ class: "tile" },
|
||||||
|
/* @__PURE__ */ createElement(
|
||||||
|
"div",
|
||||||
|
null,
|
||||||
|
/* @__PURE__ */ createElement(
|
||||||
|
"span",
|
||||||
|
null,
|
||||||
|
translations.message,
|
||||||
|
),
|
||||||
|
/* @__PURE__ */ createElement("input", {
|
||||||
placeholder: translations.message_placeholder,
|
placeholder: translations.message_placeholder,
|
||||||
"bind:value": newMessageBody,
|
"bind:value": newMessageBody,
|
||||||
"on:enter": sendMessage
|
"on:enter": sendMessage,
|
||||||
}
|
}),
|
||||||
))), /* @__PURE__ */ createElement("div", { class: "flex-row width-input justify-end" }, /* @__PURE__ */ createElement(
|
),
|
||||||
|
),
|
||||||
|
/* @__PURE__ */ createElement(
|
||||||
|
"div",
|
||||||
|
{ class: "flex-row width-input justify-end" },
|
||||||
|
/* @__PURE__ */ createElement(
|
||||||
"button",
|
"button",
|
||||||
{
|
{
|
||||||
class: "primary width-50",
|
class: "primary width-50",
|
||||||
"on:click": sendMessage,
|
"on:click": sendMessage,
|
||||||
"toggle:disabled": isMessageEmpty
|
"toggle:disabled": isMessageEmpty,
|
||||||
},
|
},
|
||||||
translations.send,
|
translations.send,
|
||||||
/* @__PURE__ */ createElement("span", { class: "icon" }, "send")
|
/* @__PURE__ */ createElement(
|
||||||
))));
|
"span",
|
||||||
|
{ class: "icon" },
|
||||||
|
"send",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// src/messageScreen.tsx
|
// src/messageScreen.tsx
|
||||||
var convertMessageToElement = (message) => {
|
var convertMessageToElement = (message) => {
|
||||||
return /* @__PURE__ */ createElement("div", { class: "tile", style: "flex: 0" }, /* @__PURE__ */ createElement("div", null, /* @__PURE__ */ createElement("span", { class: "secondary" }, message.channel), /* @__PURE__ */ createElement("b", null, message.body)));
|
return /* @__PURE__ */ createElement(
|
||||||
|
"div",
|
||||||
|
{ class: "tile", style: "flex: 0" },
|
||||||
|
/* @__PURE__ */ createElement(
|
||||||
|
"div",
|
||||||
|
null,
|
||||||
|
/* @__PURE__ */ createElement(
|
||||||
|
"span",
|
||||||
|
{ class: "secondary" },
|
||||||
|
message.channel,
|
||||||
|
),
|
||||||
|
/* @__PURE__ */ createElement("b", null, message.body),
|
||||||
|
),
|
||||||
|
);
|
||||||
};
|
};
|
||||||
function MessageScreen() {
|
function MessageScreen() {
|
||||||
return /* @__PURE__ */ createElement("article", { id: "message-screen" }, /* @__PURE__ */ createElement("header", null, translations.messagesReceived), /* @__PURE__ */ createElement("div", null, /* @__PURE__ */ createElement(
|
return /* @__PURE__ */ createElement(
|
||||||
|
"article",
|
||||||
|
{ id: "message-screen" },
|
||||||
|
/* @__PURE__ */ createElement(
|
||||||
|
"header",
|
||||||
|
null,
|
||||||
|
translations.messagesReceived,
|
||||||
|
),
|
||||||
|
/* @__PURE__ */ createElement(
|
||||||
"div",
|
"div",
|
||||||
{
|
null,
|
||||||
|
/* @__PURE__ */ createElement("div", {
|
||||||
class: "flex-column gap",
|
class: "flex-column gap",
|
||||||
"subscribe:children": [messages, convertMessageToElement]
|
"subscribe:children": [messages, convertMessageToElement],
|
||||||
}
|
}),
|
||||||
)), /* @__PURE__ */ createElement("footer", null, /* @__PURE__ */ createElement(
|
),
|
||||||
"input",
|
/* @__PURE__ */ createElement(
|
||||||
{
|
"footer",
|
||||||
|
null,
|
||||||
|
/* @__PURE__ */ createElement("input", {
|
||||||
style: "max-width: unset",
|
style: "max-width: unset",
|
||||||
placeholder: translations.message_placeholder_generic,
|
placeholder: translations.message_placeholder_generic,
|
||||||
"bind:value": newMessageBody,
|
"bind:value": newMessageBody,
|
||||||
"on:enter": sendMessage
|
"on:enter": sendMessage,
|
||||||
}
|
}),
|
||||||
), /* @__PURE__ */ createElement(
|
/* @__PURE__ */ createElement(
|
||||||
"button",
|
"button",
|
||||||
{
|
{
|
||||||
class: "primary",
|
class: "primary",
|
||||||
"on:click": sendMessage,
|
"on:click": sendMessage,
|
||||||
"toggle:disabled": isMessageEmpty
|
"toggle:disabled": isMessageEmpty,
|
||||||
},
|
},
|
||||||
/* @__PURE__ */ createElement("span", { class: "icon" }, "send")
|
/* @__PURE__ */ createElement(
|
||||||
)));
|
"span",
|
||||||
|
{ class: "icon" },
|
||||||
|
"send",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// src/index.tsx
|
// src/index.tsx
|
||||||
document.body.prepend(
|
document.body.prepend(
|
||||||
/* @__PURE__ */ createElement("menu", null, /* @__PURE__ */ createElement("a", { class: "tab-link", href: "#info-screen", active: true }, /* @__PURE__ */ createElement("span", { class: "icon" }, "info"), translations.info), /* @__PURE__ */ createElement("a", { class: "tab-link", href: "#main-screen" }, /* @__PURE__ */ createElement("span", { class: "icon" }, "settings"), translations.settings), /* @__PURE__ */ createElement("a", { class: "tab-link", href: "#message-screen" }, /* @__PURE__ */ createElement("span", { class: "icon" }, "chat"), translations.messages))
|
/* @__PURE__ */ createElement(
|
||||||
|
"menu",
|
||||||
|
null,
|
||||||
|
/* @__PURE__ */ createElement(
|
||||||
|
"a",
|
||||||
|
{ class: "tab-link", href: "#info-screen", active: true },
|
||||||
|
/* @__PURE__ */ createElement(
|
||||||
|
"span",
|
||||||
|
{ class: "icon" },
|
||||||
|
"info",
|
||||||
|
),
|
||||||
|
translations.info,
|
||||||
|
),
|
||||||
|
/* @__PURE__ */ createElement(
|
||||||
|
"a",
|
||||||
|
{ class: "tab-link", href: "#main-screen" },
|
||||||
|
/* @__PURE__ */ createElement(
|
||||||
|
"span",
|
||||||
|
{ class: "icon" },
|
||||||
|
"settings",
|
||||||
|
),
|
||||||
|
translations.settings,
|
||||||
|
),
|
||||||
|
/* @__PURE__ */ createElement(
|
||||||
|
"a",
|
||||||
|
{ class: "tab-link", href: "#message-screen" },
|
||||||
|
/* @__PURE__ */ createElement(
|
||||||
|
"span",
|
||||||
|
{ class: "icon" },
|
||||||
|
"chat",
|
||||||
|
),
|
||||||
|
translations.messages,
|
||||||
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
document.querySelector("main").append(InfoScreen(), MainScreen(), MessageScreen());
|
document
|
||||||
|
.querySelector("main")
|
||||||
|
.append(InfoScreen(), MainScreen(), MessageScreen());
|
||||||
document.body.append(
|
document.body.append(
|
||||||
/* @__PURE__ */ createElement("div", { class: "modal", "toggle:open": isDisconnected }, /* @__PURE__ */ createElement("div", null, /* @__PURE__ */ createElement("main", null, /* @__PURE__ */ createElement(
|
/* @__PURE__ */ createElement(
|
||||||
|
"div",
|
||||||
|
{ class: "modal", "toggle:open": isDisconnected },
|
||||||
|
/* @__PURE__ */ createElement(
|
||||||
|
"div",
|
||||||
|
null,
|
||||||
|
/* @__PURE__ */ createElement(
|
||||||
|
"main",
|
||||||
|
null,
|
||||||
|
/* @__PURE__ */ createElement(
|
||||||
"div",
|
"div",
|
||||||
{
|
{
|
||||||
class: "flex-column align-center justify-center width-100 height-100",
|
class: "flex-column align-center justify-center width-100 height-100",
|
||||||
style: "gap: 1rem"
|
style: "gap: 1rem",
|
||||||
},
|
},
|
||||||
/* @__PURE__ */ createElement("span", { class: "icon error", style: "font-size: 3rem" }, "signal_disconnected"),
|
/* @__PURE__ */ createElement(
|
||||||
/* @__PURE__ */ createElement("h1", { class: "error" }, translations.disconnected),
|
"span",
|
||||||
/* @__PURE__ */ createElement("p", { class: "secondary" }, translations.reconnecting)
|
{ class: "icon error", style: "font-size: 3rem" },
|
||||||
))))
|
"signal_disconnected",
|
||||||
|
),
|
||||||
|
/* @__PURE__ */ createElement(
|
||||||
|
"h1",
|
||||||
|
{ class: "error" },
|
||||||
|
translations.disconnected,
|
||||||
|
),
|
||||||
|
/* @__PURE__ */ createElement(
|
||||||
|
"p",
|
||||||
|
{ class: "secondary" },
|
||||||
|
translations.reconnecting,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
})();
|
})();
|
||||||
|
|||||||
Vendored
+8
-3
@@ -245,7 +245,10 @@ SIZES
|
|||||||
--safe-area-top: env(safe-area-inset-top);
|
--safe-area-top: env(safe-area-inset-top);
|
||||||
--safe-area-left: env(safe-area-inset-left);
|
--safe-area-left: env(safe-area-inset-left);
|
||||||
--safe-area-right: env(safe-area-inset-right);
|
--safe-area-right: env(safe-area-inset-right);
|
||||||
--safe-area-bottom: max(env(safe-area-inset-bottom), var(--control-padding));
|
--safe-area-bottom: max(
|
||||||
|
env(safe-area-inset-bottom),
|
||||||
|
var(--control-padding)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -593,7 +596,8 @@ label.tile:has(> span.icon) input {
|
|||||||
|
|
||||||
article > div {
|
article > div {
|
||||||
padding-bottom: calc(
|
padding-bottom: calc(
|
||||||
var(--menu-height-mobile) + var(--control-height) + var(--content-padding)
|
var(--menu-height-mobile) + var(--control-height) +
|
||||||
|
var(--content-padding)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -909,7 +913,8 @@ menu {
|
|||||||
|
|
||||||
article > div {
|
article > div {
|
||||||
padding-bottom: calc(
|
padding-bottom: calc(
|
||||||
var(--menu-height-mobile) + var(--header-height) + var(--content-padding)
|
var(--menu-height-mobile) + var(--header-height) +
|
||||||
|
var(--content-padding)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Vendored
+5
-2
@@ -14,9 +14,12 @@ document.querySelector("main").addEventListener("scroll", () => {
|
|||||||
async function registerServiceWorker() {
|
async function registerServiceWorker() {
|
||||||
if ("serviceWorker" in navigator) {
|
if ("serviceWorker" in navigator) {
|
||||||
try {
|
try {
|
||||||
const registration = await navigator.serviceWorker.register("/sw.js", {
|
const registration = await navigator.serviceWorker.register(
|
||||||
|
"/sw.js",
|
||||||
|
{
|
||||||
scope: "/",
|
scope: "/",
|
||||||
});
|
},
|
||||||
|
);
|
||||||
if (registration.installing) {
|
if (registration.installing) {
|
||||||
setTimeout(() => window.location.reload(), 500);
|
setTimeout(() => window.location.reload(), 500);
|
||||||
} else if (registration.active) {
|
} else if (registration.active) {
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ document.body.prepend(
|
|||||||
<span class="icon">chat</span>
|
<span class="icon">chat</span>
|
||||||
{translations.messages}
|
{translations.messages}
|
||||||
</a>
|
</a>
|
||||||
</menu>
|
</menu>,
|
||||||
);
|
);
|
||||||
|
|
||||||
document
|
document
|
||||||
@@ -43,5 +43,5 @@ document.body.append(
|
|||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -16,7 +16,10 @@ export function InfoScreen() {
|
|||||||
</span>
|
</span>
|
||||||
</header>
|
</header>
|
||||||
<div>
|
<div>
|
||||||
<div class="flex-column gap" subscribe:innerHTML={statHTMLString}></div>
|
<div
|
||||||
|
class="flex-column gap"
|
||||||
|
subscribe:innerHTML={statHTMLString}
|
||||||
|
></div>
|
||||||
</div>
|
</div>
|
||||||
</article>
|
</article>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -26,7 +26,10 @@ export function MainScreen() {
|
|||||||
<div class="tile width-input">
|
<div class="tile width-input">
|
||||||
<div>
|
<div>
|
||||||
<b>{translations.messageLastReceived}</b>
|
<b>{translations.messageLastReceived}</b>
|
||||||
<p class="secondary" subscribe:innerText={lastReceivedMessage}></p>
|
<p
|
||||||
|
class="secondary"
|
||||||
|
subscribe:innerText={lastReceivedMessage}
|
||||||
|
></p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -35,7 +38,10 @@ export function MainScreen() {
|
|||||||
<div class="tile width-input">
|
<div class="tile width-input">
|
||||||
<div>
|
<div>
|
||||||
<b>{translations.mailbox}</b>
|
<b>{translations.mailbox}</b>
|
||||||
<p class="secondary" toggle:hidden={isMailboxDisonnected}>
|
<p
|
||||||
|
class="secondary"
|
||||||
|
toggle:hidden={isMailboxDisonnected}
|
||||||
|
>
|
||||||
{translations.mailboxConnected}
|
{translations.mailboxConnected}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
+12
-7
@@ -4,7 +4,10 @@ import UDNFrontend from "udn-frontend";
|
|||||||
import { translations } from "./translations";
|
import { translations } from "./translations";
|
||||||
|
|
||||||
export class Message {
|
export class Message {
|
||||||
constructor(public channel: string, public body: string) {}
|
constructor(
|
||||||
|
public channel: string,
|
||||||
|
public body: string,
|
||||||
|
) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
// STATE
|
// STATE
|
||||||
@@ -18,14 +21,14 @@ export const isMailboxDisonnected = 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(
|
||||||
translations.noMessagesReceived
|
translations.noMessagesReceived,
|
||||||
);
|
);
|
||||||
|
|
||||||
// stats
|
// stats
|
||||||
export const statHTMLString = new React.State<string>("");
|
export const statHTMLString = new React.State<string>("");
|
||||||
export async function updateStats() {
|
export async function updateStats() {
|
||||||
const response = await fetch(
|
const response = await fetch(
|
||||||
`${window.location.protocol}//${window.location.host}/stats`
|
`${window.location.protocol}//${window.location.host}/stats`,
|
||||||
);
|
);
|
||||||
const data: [string, string][] = await response.json();
|
const data: [string, string][] = await response.json();
|
||||||
|
|
||||||
@@ -33,7 +36,9 @@ export async function updateStats() {
|
|||||||
data.forEach((item) => {
|
data.forEach((item) => {
|
||||||
const tile = (
|
const tile = (
|
||||||
<div class="tile">
|
<div class="tile">
|
||||||
<span class="secondary flex width-100">{item[0].toString()}</span>
|
<span class="secondary flex width-100">
|
||||||
|
{item[0].toString()}
|
||||||
|
</span>
|
||||||
<b>{item[1].toString()}</b>
|
<b>{item[1].toString()}</b>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@@ -50,7 +55,7 @@ export const newMessageBody = new React.State("");
|
|||||||
|
|
||||||
export const isMessageEmpty = React.createProxyState(
|
export const isMessageEmpty = React.createProxyState(
|
||||||
[newMessageChannel, newMessageBody],
|
[newMessageChannel, newMessageBody],
|
||||||
() => newMessageChannel.value == "" || newMessageBody.value == ""
|
() => newMessageChannel.value == "" || newMessageBody.value == "",
|
||||||
);
|
);
|
||||||
|
|
||||||
// UDN Frontend
|
// UDN Frontend
|
||||||
@@ -87,7 +92,7 @@ UDN.onmailboxconnect = () => {
|
|||||||
|
|
||||||
UDN.onmailboxdelete = () => {
|
UDN.onmailboxdelete = () => {
|
||||||
isMailboxDisonnected.value = true;
|
isMailboxDisonnected.value = true;
|
||||||
}
|
};
|
||||||
|
|
||||||
UDN.ondisconnect = () => {
|
UDN.ondisconnect = () => {
|
||||||
isDisconnected.value = true;
|
isDisconnected.value = true;
|
||||||
@@ -97,7 +102,7 @@ UDN.ondisconnect = () => {
|
|||||||
|
|
||||||
function connect() {
|
function connect() {
|
||||||
UDN.connect(
|
UDN.connect(
|
||||||
`${window.location.protocol.replace("http", "ws")}//${window.location.host}`
|
`${window.location.protocol.replace("http", "ws")}//${window.location.host}`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
connect();
|
connect();
|
||||||
|
|||||||
+17
-11
@@ -8,7 +8,7 @@ import Crypto from "crypto";
|
|||||||
import { WS } from "./index";
|
import { WS } from "./index";
|
||||||
|
|
||||||
export interface Subscriber {
|
export interface Subscriber {
|
||||||
send: (message: string) => void;
|
send: (message: string, compress?: boolean, id?: string) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Mailbox implements Subscriber {
|
export class Mailbox implements Subscriber {
|
||||||
@@ -35,7 +35,7 @@ export class Mailbox implements Subscriber {
|
|||||||
{
|
{
|
||||||
assignedMailboxId: this.id,
|
assignedMailboxId: this.id,
|
||||||
},
|
},
|
||||||
ws
|
ws,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -46,7 +46,7 @@ export class Mailbox implements Subscriber {
|
|||||||
{
|
{
|
||||||
connectedMailboxId: this.id,
|
connectedMailboxId: this.id,
|
||||||
},
|
},
|
||||||
this.ws
|
this.ws,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -57,7 +57,7 @@ export class Mailbox implements Subscriber {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// storage
|
// storage
|
||||||
messages = new Set<string>();
|
messages = new Map<string, string>();
|
||||||
|
|
||||||
// websocket
|
// websocket
|
||||||
private _ws: WS | undefined;
|
private _ws: WS | undefined;
|
||||||
@@ -90,13 +90,13 @@ export class Mailbox implements Subscriber {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// sending
|
// sending
|
||||||
send(message: string): void {
|
send(message: string, _?: boolean, uuid?: string): void {
|
||||||
if (this._ws?.readyState == 1) {
|
this._ws?.send(message);
|
||||||
this._ws.send(message);
|
|
||||||
this.dateLastUsed = new Date();
|
console.log(this.id, uuid, message, "sending");
|
||||||
} else {
|
|
||||||
this.messages.add(message);
|
if (!uuid) return;
|
||||||
}
|
this.messages.set(uuid, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
sendUnreadMessages(): void {
|
sendUnreadMessages(): void {
|
||||||
@@ -107,6 +107,12 @@ export class Mailbox implements Subscriber {
|
|||||||
this.messages.delete(message);
|
this.messages.delete(message);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
checkMessageReceivedConfirmation(uuid: string): void {
|
||||||
|
if (!this.messages.has(uuid)) return;
|
||||||
|
this.dateLastUsed = new Date();
|
||||||
|
this.messages.delete(uuid);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class SubscriptionMap {
|
export class SubscriptionMap {
|
||||||
|
|||||||
+5
-5
@@ -3,9 +3,7 @@ import { PACKAGE_FILE, STATIC_DIR, WS } from ".";
|
|||||||
import Colors from "colors";
|
import Colors from "colors";
|
||||||
import Fs from "fs/promises";
|
import Fs from "fs/promises";
|
||||||
import Path from "path";
|
import Path from "path";
|
||||||
import {
|
import { WebSocketMessage } from "./websocket-handler";
|
||||||
WebSocketMessage,
|
|
||||||
} from "./websocket-handler";
|
|
||||||
|
|
||||||
// CONFIG
|
// CONFIG
|
||||||
const STAT_INDENT = 25;
|
const STAT_INDENT = 25;
|
||||||
@@ -39,12 +37,14 @@ async function writeToLogFile(message: string): Promise<void> {
|
|||||||
|
|
||||||
// stats
|
// stats
|
||||||
export function writeStatString(label: string, value: string): void {
|
export function writeStatString(label: string, value: string): void {
|
||||||
console.log(`${label.padEnd(STAT_INDENT, " ")} ${Colors.bold.green(value)}`);
|
console.log(
|
||||||
|
`${label.padEnd(STAT_INDENT, " ")} ${Colors.bold.green(value)}`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function writeStatNumber(label: string, value: number): void {
|
export function writeStatNumber(label: string, value: number): void {
|
||||||
console.log(
|
console.log(
|
||||||
`${label.padEnd(STAT_INDENT, " ")} ${Colors.bold.blue(value.toString())}`
|
`${label.padEnd(STAT_INDENT, " ")} ${Colors.bold.blue(value.toString())}`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+28
-11
@@ -34,6 +34,9 @@ export interface WebSocketMessage {
|
|||||||
//sending message
|
//sending message
|
||||||
messageChannel?: string;
|
messageChannel?: string;
|
||||||
messageBody?: string;
|
messageBody?: string;
|
||||||
|
|
||||||
|
// confirming message
|
||||||
|
confirmingMessageReceived?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TRACKING
|
// TRACKING
|
||||||
@@ -64,7 +67,7 @@ export function forgetConnection(ws: WS): void {
|
|||||||
|
|
||||||
export function trackSubscription(
|
export function trackSubscription(
|
||||||
subscriber: Subscriber,
|
subscriber: Subscriber,
|
||||||
channel: string
|
channel: string,
|
||||||
): void {
|
): void {
|
||||||
subscriptionMap.set(subscriber, channel);
|
subscriptionMap.set(subscriber, channel);
|
||||||
confirmSubscription(subscriber, channel);
|
confirmSubscription(subscriber, channel);
|
||||||
@@ -72,7 +75,7 @@ export function trackSubscription(
|
|||||||
|
|
||||||
export function forgetSubscription(
|
export function forgetSubscription(
|
||||||
subscriber: Subscriber,
|
subscriber: Subscriber,
|
||||||
channel: string
|
channel: string,
|
||||||
): void {
|
): void {
|
||||||
subscriptionMap.delete(subscriber, channel);
|
subscriptionMap.delete(subscriber, channel);
|
||||||
confirmSubscription(subscriber, channel);
|
confirmSubscription(subscriber, channel);
|
||||||
@@ -104,7 +107,7 @@ export function reconnectServers(config: typeof defaultConfig): void {
|
|||||||
|
|
||||||
export function connectServer(
|
export function connectServer(
|
||||||
address: string,
|
address: string,
|
||||||
config: typeof defaultConfig
|
config: typeof defaultConfig,
|
||||||
): void {
|
): void {
|
||||||
try {
|
try {
|
||||||
// connect
|
// connect
|
||||||
@@ -153,7 +156,7 @@ export function subscribeChannel(server: WS, channel: string): void {
|
|||||||
export function processMessage(
|
export function processMessage(
|
||||||
ws: WS,
|
ws: WS,
|
||||||
messageString: string,
|
messageString: string,
|
||||||
config: typeof defaultConfig
|
config: typeof defaultConfig,
|
||||||
): void {
|
): void {
|
||||||
// MESSAGE ID
|
// MESSAGE ID
|
||||||
// check id
|
// check id
|
||||||
@@ -161,6 +164,14 @@ export function processMessage(
|
|||||||
if (!messageObject.uuid) {
|
if (!messageObject.uuid) {
|
||||||
// assign if no id
|
// assign if no id
|
||||||
messageObject.uuid = Crypto.randomUUID();
|
messageObject.uuid = Crypto.randomUUID();
|
||||||
|
} else if (messageObject.confirmingMessageReceived == true) {
|
||||||
|
// received confirmation
|
||||||
|
mailboxes.forEach((mailbox) => {
|
||||||
|
if (mailbox.ws != ws) return;
|
||||||
|
return mailbox.checkMessageReceivedConfirmation(
|
||||||
|
messageObject.uuid!,
|
||||||
|
);
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
// ignore if already seen
|
// ignore if already seen
|
||||||
if (knownMessageIds.has(messageObject.uuid)) return;
|
if (knownMessageIds.has(messageObject.uuid)) return;
|
||||||
@@ -179,7 +190,11 @@ export function processMessage(
|
|||||||
// MESSAGE
|
// MESSAGE
|
||||||
doIfIsString(messageObject.messageChannel, (messageChannel) => {
|
doIfIsString(messageObject.messageChannel, (messageChannel) => {
|
||||||
if (messageObject.messageBody == undefined) return;
|
if (messageObject.messageBody == undefined) return;
|
||||||
sendMessage(messageChannel, messageObject.messageBody, messageObject.uuid!);
|
sendMessage(
|
||||||
|
messageChannel,
|
||||||
|
messageObject.messageBody,
|
||||||
|
messageObject.uuid!,
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
// MAILBOX
|
// MAILBOX
|
||||||
@@ -192,7 +207,7 @@ export function processMessage(
|
|||||||
if (!mailbox)
|
if (!mailbox)
|
||||||
return sendWebSocketMessage(
|
return sendWebSocketMessage(
|
||||||
{ deletedMailbox: requestedMailbox },
|
{ deletedMailbox: requestedMailbox },
|
||||||
ws
|
ws,
|
||||||
);
|
);
|
||||||
mailbox.ws = ws;
|
mailbox.ws = ws;
|
||||||
});
|
});
|
||||||
@@ -225,16 +240,16 @@ export function removeMailbox(mailbox: Mailbox) {
|
|||||||
// MESSAGING
|
// MESSAGING
|
||||||
export function sendWebSocketMessage(
|
export function sendWebSocketMessage(
|
||||||
messageObject: WebSocketMessage,
|
messageObject: WebSocketMessage,
|
||||||
destination: Subscriber
|
destination: Subscriber,
|
||||||
): void {
|
): void {
|
||||||
const messageString = JSON.stringify(messageObject);
|
const messageString = JSON.stringify(messageObject);
|
||||||
destination.send(messageString);
|
destination.send(messageString, false, messageObject.uuid);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function sendMessage(
|
export function sendMessage(
|
||||||
messageChannel: string,
|
messageChannel: string,
|
||||||
messageBody: string,
|
messageBody: string,
|
||||||
uuid: string
|
uuid: string,
|
||||||
): void {
|
): void {
|
||||||
const channels = messageChannel.split("/");
|
const channels = messageChannel.split("/");
|
||||||
subscriptionMap.forwardMessage(channels, {
|
subscriptionMap.forwardMessage(channels, {
|
||||||
@@ -254,11 +269,13 @@ function requestServerConnection(ws: WS): void {
|
|||||||
|
|
||||||
function confirmSubscription(
|
function confirmSubscription(
|
||||||
subscriber: Subscriber,
|
subscriber: Subscriber,
|
||||||
messageChannel: string
|
messageChannel: string,
|
||||||
): void {
|
): void {
|
||||||
const messageObject: WebSocketMessage = {
|
const messageObject: WebSocketMessage = {
|
||||||
messageChannel,
|
messageChannel,
|
||||||
subscribed: subscriptionMap.getChannelList(subscriber)?.has(messageChannel)
|
subscribed: subscriptionMap
|
||||||
|
.getChannelList(subscriber)
|
||||||
|
?.has(messageChannel)
|
||||||
? true
|
? true
|
||||||
: false,
|
: false,
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user