From fe0667919e440e72c57adbf27a51c7f172d4f911 Mon Sep 17 00:00:00 2001 From: leukipp Date: Wed, 27 Aug 2025 18:30:15 +0200 Subject: [PATCH] feat: check online status #62 --- js/integration.js | 14 ++++++------ js/webview.js | 55 +++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 55 insertions(+), 14 deletions(-) diff --git a/js/integration.js b/js/integration.js index d26cb89..3641af1 100644 --- a/js/integration.js +++ b/js/integration.js @@ -445,7 +445,7 @@ const initPageNumber = () => { if (topic === config.command_topic) { const number = parseInt(message, 10); console.log("Set Page Number:", number); - WEBVIEW.viewActive = number; + WEBVIEW.viewActive = number || 1; WEBVIEW.events.emit("updateView"); } }) @@ -457,7 +457,7 @@ const initPageNumber = () => { * Updates the page number via the mqtt connection. */ const updatePageNumber = () => { - const pageNumber = WEBVIEW.viewActive; + const pageNumber = WEBVIEW.viewActive || 1; publishState("page_number", pageNumber); }; @@ -484,7 +484,7 @@ const initPageZoom = () => { if (topic === config.command_topic) { const zoom = parseInt(message, 10); console.log("Set Page Zoom:", zoom); - WEBVIEW.views[WEBVIEW.viewActive].webContents.setZoomFactor(zoom / 100.0); + WEBVIEW.views[WEBVIEW.viewActive || 1].webContents.setZoomFactor(zoom / 100.0); WEBVIEW.events.emit("updateView"); } }) @@ -496,7 +496,7 @@ const initPageZoom = () => { * Updates the page zoom via the mqtt connection. */ const updatePageZoom = () => { - const pageZoom = Math.round(WEBVIEW.views[WEBVIEW.viewActive].webContents.getZoomFactor() * 100.0); + const pageZoom = Math.round(WEBVIEW.views[WEBVIEW.viewActive || 1].webContents.getZoomFactor() * 100.0); publishState("page_zoom", pageZoom); }; @@ -520,7 +520,7 @@ const initPageUrl = () => { if (topic === config.command_topic) { const url = message.toString(); console.log("Set Page Url:", url); - WEBVIEW.views[WEBVIEW.viewActive].webContents.loadURL(url); + WEBVIEW.views[WEBVIEW.viewActive || 1].webContents.loadURL(url); } }) .subscribe(config.command_topic); @@ -531,8 +531,8 @@ const initPageUrl = () => { * Updates the page url via the mqtt connection. */ const updatePageUrl = () => { - const defaultUrl = WEBVIEW.viewUrls[WEBVIEW.viewActive]; - const currentUrl = WEBVIEW.views[WEBVIEW.viewActive].webContents.getURL(); + const defaultUrl = WEBVIEW.viewUrls[WEBVIEW.viewActive || 1]; + const currentUrl = WEBVIEW.views[WEBVIEW.viewActive || 1].webContents.getURL(); const pageUrl = !currentUrl || currentUrl.startsWith("data:") ? defaultUrl : currentUrl; publishState("page_url", pageUrl); }; diff --git a/js/webview.js b/js/webview.js index ef8c8e9..c117f6f 100644 --- a/js/webview.js +++ b/js/webview.js @@ -1,4 +1,5 @@ const path = require("path"); +const axios = require("axios"); const hardware = require("./hardware"); const integration = require("./integration"); const { app, screen, nativeTheme, ipcMain, session, BaseWindow, WebContentsView } = require("electron"); @@ -74,8 +75,10 @@ const init = async () => { view.setVisible(i === 0); view.setBackgroundColor("#FFFFFFFF"); WEBVIEW.window.contentView.addChildView(view); - view.webContents.loadURL(url); WEBVIEW.views.push(view); + onlineStatus(url).then(() => { + view.webContents.loadURL(url); + }); }); // Init global widget @@ -146,6 +149,9 @@ const update = async () => { * Updates the active view. */ const updateView = () => { + if (!WEBVIEW.viewActive) { + return; + } const title = `TouchKio - ${new URL(WEBVIEW.viewUrls[WEBVIEW.viewActive]).host}`; console.log(`Update View: ${title} (${WEBVIEW.viewActive})`); WEBVIEW.window.setTitle(title); @@ -192,7 +198,7 @@ const updateNavigation = () => { WEBVIEW.navigation.webContents.send("input-text", { id: "url", text: currentUrl.startsWith("data:") ? "" : currentUrl, - placeholder: defaultUrl, + placeholder: defaultUrl.startsWith("data:") ? "" : defaultUrl, }); // Disable history buttons @@ -540,7 +546,8 @@ const navigationEvents = () => { * Register dom events and handler. */ const domEvents = () => { - WEBVIEW.views.forEach((view) => { + const ready = []; + WEBVIEW.views.forEach((view, i) => { // Enable webview touch emulation view.webContents.debugger.attach("1.1"); view.webContents.debugger.sendCommand("Emulation.setEmitTouchEventsForMouse", { @@ -556,14 +563,15 @@ const domEvents = () => { // Update webview layout view.webContents.on("dom-ready", () => { - view.webContents.setZoomFactor(WEBVIEW.viewZoom); view.webContents.insertCSS("::-webkit-scrollbar { display: none; }"); + view.webContents.setZoomFactor(WEBVIEW.viewZoom); + WEBVIEW.initialized = true; + ready.push(i); }); // Webview fully loaded view.webContents.on("did-finish-load", () => { - WEBVIEW.initialized = true; - if (WEBVIEW.viewActive === 0) { + if (WEBVIEW.viewActive === 0 && ready.length === WEBVIEW.views.length) { nextView(); } if (ARGS.app_debug === "true") { @@ -576,7 +584,7 @@ const domEvents = () => { // Webview not loaded view.webContents.on("did-fail-load", (e, code, text, url, mainframe) => { if (mainframe) { - if (WEBVIEW.viewActive === 0) { + if (WEBVIEW.viewActive === 0 && ready.length === WEBVIEW.views.length) { nextView(); } view.webContents.loadURL(errorHtml(code, text, url)); @@ -615,6 +623,39 @@ const appEvents = () => { }); }; +/** + * Checks for network connectivity by requesting a known url. + * + * @param {string} url - Url to request. + * @param {number} interval - Interval between requests in milliseconds. + * @param {number} timeout - Maximum time to repeat requests in milliseconds. + * @returns {Promise} Resolves true if online, false on timeout. + */ +const onlineStatus = (url, interval = 1000, timeout = 60000) => { + return new Promise((resolve) => { + const start = Date.now(); + const check = async () => { + const elapsed = Date.now() - start; + try { + if (!url.startsWith("data:")) { + await axios.get(url, { timeout: 10000 }); + } + resolve(true); + } catch (error) { + if (elapsed >= interval) { + console.warn(`Checking Connection: ${url}`, error.message); + } + if (elapsed >= timeout) { + resolve(false); + } else { + setTimeout(check, interval); + } + } + }; + check(); + }); +}; + /** * Generates a html template for a spinning loader. *