Enhance WebSocket connection handling with improved timeout and error states
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
2026-02-11 14:20:24 +11:00
parent 8698983bbf
commit 9bd2b32003
6 changed files with 229 additions and 81 deletions

View File

@@ -1,3 +1,6 @@
#### 2.2.0.0201-beta
Add UI enhancement for range selecting checkboxes
#### 2.2.0.0200-beta
```diff
+ Major web UI redesign focused on cleaner layout, better information hierarchy, and faster daily workflows.

View File

@@ -701,8 +701,8 @@ nav p {
#clientInfo {
display: grid;
grid-template-columns: minmax(86px, 34%) 1fr;
gap: 7px 8px;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 8px;
border-spacing: 0;
white-space: normal;
background: rgba(8, 20, 33, 0.44);
@@ -713,20 +713,33 @@ nav p {
}
#clientInfo .tdKey {
text-align: right;
font-size: 9px;
letter-spacing: 0.08em;
display: none;
}
#clientInfo .tdVal {
font-size: 11px;
min-height: 34px;
font-size: 12px;
min-height: 54px;
display: flex;
align-items: center;
flex-direction: column;
align-items: flex-start;
justify-content: center;
gap: 4px;
padding: 10px 9px;
background: rgba(17, 34, 53, 0.5);
}
#clientInfo .tdVal::before {
content: attr(data-label);
color: #8bb9d7;
font-size: 9px;
letter-spacing: 0.07em;
text-transform: uppercase;
font-family: "Space Grotesk", "Avenir Next", "Trebuchet MS", sans-serif;
line-height: 1.2;
}
.dashboard-cards {
grid-template-columns: repeat(2, minmax(120px, 1fr));
grid-template-columns: repeat(3, minmax(0, 1fr));
}
#content_table {
@@ -831,12 +844,16 @@ nav p {
}
#clientInfo {
grid-template-columns: minmax(78px, 32%) 1fr;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 6px;
padding-left: 8px;
padding-right: 8px;
}
.dashboard-cards {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
#content-interaction {
flex-direction: column;
align-items: stretch;
@@ -876,3 +893,9 @@ nav p {
margin-right: 0;
}
}
@media only screen and (max-width: 430px) {
#clientInfo {
grid-template-columns: 1fr;
}
}

View File

@@ -58,38 +58,38 @@
<tr>
<td class="tdKey">xTeVe:</td>
<td id="version" class="tdVal">&nbsp;</td>
<td id="version" class="tdVal" data-label="xTeVe">&nbsp;</td>
<td class="tdKey">OS:</td>
<td id="os" class="tdVal">&nbsp;</td>
<td id="os" class="tdVal" data-label="OS">&nbsp;</td>
<td class="tdKey phone">DVR IP:</td>
<td id="DVR" class="tdVal phone">&nbsp;</td>
<td id="DVR" class="tdVal phone" data-label="DVR IP">&nbsp;</td>
</tr>
<tr>
<td class="tdKey">UUID:</td>
<td id="uuid" class="tdVal">&nbsp;</td>
<td id="uuid" class="tdVal" data-label="UUID">&nbsp;</td>
<td class="tdKey">Arch:</td>
<td id="arch" class="tdVal">&nbsp;</td>
<td id="arch" class="tdVal" data-label="Arch">&nbsp;</td>
<td class="tdKey phone">M3U URL:</td>
<td id="m3u-url" class="tdVal phone">&nbsp;</td>
<td id="m3u-url" class="tdVal phone" data-label="M3U URL">&nbsp;</td>
</tr>
<tr>
<td class="tdKey">Available Streams:</td>
<td id="streams" class="tdVal">&nbsp;</td>
<td id="streams" class="tdVal" data-label="Available Streams">&nbsp;</td>
<td class="tdKey">EPG Source:</td>
<td id="epgSource" class="tdVal">&nbsp;</td>
<td id="epgSource" class="tdVal" data-label="EPG Source">&nbsp;</td>
<td class="tdKey phone">XEPG URL:</td>
<td id="xepg-url" class="tdVal phone">&nbsp;</td>
<td id="xepg-url" class="tdVal phone" data-label="XEPG URL">&nbsp;</td>
</tr>
<tr>
<td class="tdKey">XEPG Channels:</td>
<td id="xepg" class="tdVal">&nbsp;</td>
<td id="xepg" class="tdVal" data-label="XEPG Channels">&nbsp;</td>
<td class="tdKey">Errors:</td>
<td id="errors" class="tdVal">&nbsp;</td>
<td id="errors" class="tdVal" data-label="Errors">&nbsp;</td>
<td class="tdKey">Warnings:</td>
<td id="warnings" class="tdVal">&nbsp;</td>
<td id="warnings" class="tdVal" data-label="Warnings">&nbsp;</td>
</tr>
</table>

View File

@@ -21,9 +21,55 @@ var Server = /** @class */ (function () {
this.protocol = "wss://";
break;
}
var url = this.protocol + window.location.hostname + ":" + window.location.port + "/data/" + "?Token=" + getCookie("Token");
var wsHost = window.location.host;
if (wsHost == undefined || wsHost.length < 1) {
wsHost = window.location.hostname;
}
var url = this.protocol + wsHost + "/data/" + "?Token=" + getCookie("Token");
data["cmd"] = this.cmd;
var ws = new WebSocket(url);
var isLogUpdate = data["cmd"] == "updateLog";
var responseReceived = false;
var requestFinished = false;
var timeoutMs = 12000;
var requestTimeout;
var finishRequest = function (state, responseSuccess) {
if (responseSuccess === void 0) { responseSuccess = false; }
if (requestFinished == true) {
return;
}
requestFinished = true;
SERVER_CONNECTION = false;
window.clearTimeout(requestTimeout);
if (responseSuccess == true) {
if (state == "online") {
WS_FAILURE_COUNT = 0;
}
}
else {
WS_FAILURE_COUNT++;
}
if (isLogUpdate == false) {
showElement("loading", false);
}
if (state != "") {
setConnectionState(state);
}
};
requestTimeout = window.setTimeout(function () {
console.log("Websocket request timed out.");
var timeoutState = "offline";
if (isLogUpdate == true && WS_FAILURE_COUNT < 2) {
timeoutState = "idle";
}
finishRequest(timeoutState, false);
try {
ws.close();
}
catch (err) {
console.log(err);
}
}, timeoutMs);
ws.onopen = function () {
WS_AVAILABLE = true;
if (data["cmd"] != "updateLog") {
@@ -37,18 +83,18 @@ var Server = /** @class */ (function () {
};
ws.onerror = function (e) {
console.log("No websocket connection to xTeVe could be established. Check your network configuration.");
SERVER_CONNECTION = false;
setConnectionState("offline");
var errorState = "offline";
if (isLogUpdate == true && WS_FAILURE_COUNT < 2) {
errorState = "idle";
}
finishRequest(errorState, false);
if (WS_AVAILABLE == false) {
alert("No websocket connection to xTeVe could be established. Check your network configuration.");
}
};
ws.onmessage = function (e) {
SERVER_CONNECTION = false;
showElement("loading", false);
if (data["cmd"] != "updateLog") {
setConnectionState("online");
}
responseReceived = true;
finishRequest("online", true);
console.log("RESPONSE:");
var response = JSON.parse(e.data);
console.log(response);
@@ -103,9 +149,20 @@ var Server = /** @class */ (function () {
}
createLayout();
};
ws.onclose = function () {
if (responseReceived == true) {
return;
}
var closeState = "offline";
if (isLogUpdate == true && WS_FAILURE_COUNT < 2) {
closeState = "idle";
}
finishRequest(closeState, false);
};
};
return Server;
}());
var WS_FAILURE_COUNT = 0;
function getCookie(name) {
var value = "; " + document.cookie;
var parts = value.split("; " + name + "=");

File diff suppressed because one or more lines are too long

View File

@@ -30,10 +30,60 @@ class Server {
break
}
var url = this.protocol + window.location.hostname + ":" + window.location.port + "/data/" + "?Token=" + getCookie("Token")
var wsHost:string = window.location.host
if (wsHost == undefined || wsHost.length < 1) {
wsHost = window.location.hostname
}
var url = this.protocol + wsHost + "/data/" + "?Token=" + getCookie("Token")
data["cmd"] = this.cmd
var ws = new WebSocket(url)
var isLogUpdate:boolean = data["cmd"] == "updateLog"
var responseReceived:boolean = false
var requestFinished:boolean = false
var timeoutMs:number = 12000
var requestTimeout:number
var finishRequest = function(state:string, responseSuccess:boolean = false):void {
if (requestFinished == true) {
return
}
requestFinished = true
SERVER_CONNECTION = false
window.clearTimeout(requestTimeout)
if (responseSuccess == true) {
if (state == "online") {
WS_FAILURE_COUNT = 0
}
} else {
WS_FAILURE_COUNT++
}
if (isLogUpdate == false) {
showElement("loading", false)
}
if (state != "") {
setConnectionState(state)
}
}
requestTimeout = window.setTimeout(function() {
console.log("Websocket request timed out.")
var timeoutState:string = "offline"
if (isLogUpdate == true && WS_FAILURE_COUNT < 2) {
timeoutState = "idle"
}
finishRequest(timeoutState, false)
try {
ws.close()
} catch (err) {
console.log(err)
}
}, timeoutMs)
ws.onopen = function() {
WS_AVAILABLE = true
@@ -54,8 +104,11 @@ class Server {
ws.onerror = function(e) {
console.log("No websocket connection to xTeVe could be established. Check your network configuration.")
SERVER_CONNECTION = false
setConnectionState("offline")
var errorState:string = "offline"
if (isLogUpdate == true && WS_FAILURE_COUNT < 2) {
errorState = "idle"
}
finishRequest(errorState, false)
if (WS_AVAILABLE == false) {
alert("No websocket connection to xTeVe could be established. Check your network configuration.")
@@ -65,12 +118,8 @@ class Server {
ws.onmessage = function (e) {
SERVER_CONNECTION = false
showElement("loading", false)
if (data["cmd"] != "updateLog") {
setConnectionState("online")
}
responseReceived = true
finishRequest("online", true)
console.log("RESPONSE:");
var response = JSON.parse(e.data);
@@ -144,11 +193,25 @@ class Server {
createLayout()
}
ws.onclose = function() {
if (responseReceived == true) {
return
}
var closeState:string = "offline"
if (isLogUpdate == true && WS_FAILURE_COUNT < 2) {
closeState = "idle"
}
finishRequest(closeState, false)
}
}
}
var WS_FAILURE_COUNT:number = 0
function getCookie(name) {
var value = "; " + document.cookie;
var parts = value.split("; " + name + "=");