aboutsummaryrefslogtreecommitdiff
path: root/src/app
diff options
context:
space:
mode:
author0neGal <mail@0negal.com>2024-12-20 20:23:20 +0100
committerGitHub <noreply@github.com>2024-12-20 20:23:20 +0100
commit98fa01696b123b8d602b20534f866debdb64df52 (patch)
tree9e4d4ac04b01010b4c2faa71543440114308be86 /src/app
parentfab59ba8b8b1c567ee158b9681c5b373fb7303e4 (diff)
parent00d04db553eb53abb48f0b4e3649a6912fdc10df (diff)
downloadViper-98fa01696b123b8d602b20534f866debdb64df52.tar.gz
Viper-98fa01696b123b8d602b20534f866debdb64df52.zip
Merge pull request #246 from Jan200101/PR/onLine-event
feat: handle no internet better
Diffstat (limited to 'src/app')
-rw-r--r--src/app/css/theming.css2
-rw-r--r--src/app/icons/offline.pngbin0 -> 2707 bytes
-rw-r--r--src/app/index.html9
-rw-r--r--src/app/js/browser.js15
-rw-r--r--src/app/js/mods.js2
-rw-r--r--src/app/js/request.js110
-rw-r--r--src/app/js/set_buttons.js12
-rw-r--r--src/app/js/update.js10
-rw-r--r--src/app/main.css8
9 files changed, 147 insertions, 21 deletions
diff --git a/src/app/css/theming.css b/src/app/css/theming.css
index c0b6497..efba26a 100644
--- a/src/app/css/theming.css
+++ b/src/app/css/theming.css
@@ -37,7 +37,7 @@ a {
transition: filter 0.2s ease-in !important;
}
-a.disabled:not("[onclick='kill('game')']") {
+a.disabled:not([onclick="kill('game')"]) {
opacity: 0.5;
pointer-events: none;
}
diff --git a/src/app/icons/offline.png b/src/app/icons/offline.png
new file mode 100644
index 0000000..a9d2f1f
--- /dev/null
+++ b/src/app/icons/offline.png
Binary files differ
diff --git a/src/app/index.html b/src/app/index.html
index 98c59d4..5421a3f 100644
--- a/src/app/index.html
+++ b/src/app/index.html
@@ -14,6 +14,9 @@
<div id="toasts"></div>
<div id="winbtns">
+ <div class="hidden" id="offline" tooltip="%%tooltip.offline%%" tooltip-position="horizontal">
+ <img src="icons/offline.png">
+ </div>
<div id="settings" tooltip="%%tooltip.settings%%" tooltip-position="horizontal" onclick="settings.popup.toggle()">
<img src="icons/settings.png">
</div>
@@ -35,7 +38,7 @@
<div id="overlay" onclick="popups.set_all(false)"></div>
<div class="popup" id="options">
<div class="misc">
- <input class="search default-selection" placeholder="%%gui.search%%">
+ <input class="search default-selection requires-internet" placeholder="%%gui.search%%">
<button id="apply" onclick="settings.popup.apply();settings.popup.toggle(false)">
<img src="icons/apply.png">
%%gui.settings.save%%
@@ -338,7 +341,7 @@
<button id="playNsBtn" class="playBtn" onclick="launch('northstar')">%%gui.launch%%</button>
<div class="inline">
<div id="nsversion"></div>
- <a id="update" href="#" onclick="update.ns()" class="disable-when-installing">(%%gui.update.check%%)</a>
+ <a id="update" href="#" onclick="update.ns()" class="disable-when-installing requires-internet">(%%gui.update.check%%)</a>
<div id="serverstatus" class="checking"></div>
</div>
</div>
@@ -360,7 +363,7 @@
<img src="icons/downloads.png">
%%gui.mods.install%%
</button>
- <button id="findmod" class="bg-blue2" onclick="browser.toggle(true)">
+ <button id="findmod" class="requires-internet bg-blue2" onclick="browser.toggle(true)">
<img src="icons/search.png">
%%gui.mods.find%%
</button>
diff --git a/src/app/js/browser.js b/src/app/js/browser.js
index 88e8017..f306da8 100644
--- a/src/app/js/browser.js
+++ b/src/app/js/browser.js
@@ -107,7 +107,15 @@ var browser = {
browser.filters.toggle(false);
}
},
- install: (package_obj, clear_queue = false) => {
+ install: async (package_obj, clear_queue = false) => {
+ let can_connect = await request.check_with_toasts(
+ "Thunderstore", "https://thunderstore.io"
+ )
+
+ if (! can_connect) {
+ return;
+ }
+
return mods.install_from_url(
package_obj.download || package_obj.versions[0].download_url,
package_obj.dependencies || package_obj.versions[0].dependencies,
@@ -489,11 +497,11 @@ browser.mod_el = (properties) => {
<div class="text">
<div class="title">${properties.title}</div>
<div class="description">${properties.description}</div>
- <button class="install bg-blue" onclick=''>
+ <button class="install bg-blue requires-internet" onclick=''>
<img src="icons/${installicon}.png">
<span>${installstr}</span>
</button>
- <button class="info" onclick="browser.preview.set('${properties.url}')">
+ <button class="info requires-internet" onclick="browser.preview.set('${properties.url}')">
<img src="icons/open.png">
<span>${lang('gui.browser.view')}</span>
</button>
@@ -563,7 +571,6 @@ ipcRenderer.on("legacy-duped-mod", (_, modname) => {
})
ipcRenderer.on("no-internet", () => {
- set_buttons(true);
toasts.show({
timeout: 10000,
scheme: "error",
diff --git a/src/app/js/mods.js b/src/app/js/mods.js
index 755aad1..9eb528b 100644
--- a/src/app/js/mods.js
+++ b/src/app/js/mods.js
@@ -74,7 +74,7 @@ mods.load = (mods_obj) => {
<div class="title">${mod_details.name}</div>
<div class="description">${mod_details.description}</div>
<button class="switch on orange"></button>
- <button class="update bg-blue">
+ <button class="update bg-blue requires-internet">
<img src="icons/downloads.png">
<span>${lang("gui.browser.update")}</span>
</button>
diff --git a/src/app/js/request.js b/src/app/js/request.js
index 29b8883..81e10b1 100644
--- a/src/app/js/request.js
+++ b/src/app/js/request.js
@@ -1,18 +1,118 @@
+const lang = require("../../lang");
+const toasts = require("./toasts");
+const launcher = require("./launcher");
+const set_buttons = require("./set_buttons");
const ipcRenderer = require("electron").ipcRenderer;
-// show a toast message if no Internet connection has been detected.
-if (! navigator.onLine) {
- ipcRenderer.send("no-internet");
-}
-
// invokes `requests.get()` from `src/modules/requests.js` through the
// main process, and returns the output
let request = async (...args) => {
return await ipcRenderer.invoke("request", ...args);
}
+// invokes `requests.check()` from `src/modules/requests.js` through the
+// main process, and returns the output
+request.check = async (...args) => {
+ return await ipcRenderer.invoke("request-check", ...args);
+}
+
request.delete_cache = () => {
ipcRenderer.send("delete-request-cache");
}
+// does `request.check(...args)` and shows toast if the check failed,
+// using `name` inside the toast message
+request.check_with_toasts = async (name, ...args) => {
+ // perform check
+ let can_connect = (
+ await request.check(...args)
+ ).succeeded.length;
+
+ // show toast, as the check failed
+ if (! can_connect) {
+ toasts.show({
+ timeout: 10000,
+ scheme: "error",
+ title: lang("gui.toast.title.failed_to_connect"),
+ description: lang("gui.toast.desc.failed_to_connect").replaceAll("%s", name)
+ })
+ }
+
+ return can_connect;
+}
+
+// keeps track of whether we've already sent a toast since we last went
+// offline, to prevent multiple toasts
+let sent_error_toast = false;
+
+// shows or hides offline icon, and shows toast depending on `is_online`
+let state_action = async (is_online) => {
+ if (is_online) {
+ // hide offline icon
+ sent_error_toast = false;
+ offline.classList.add("hidden");
+
+ // re-enable buttons that require internet
+ set_buttons(
+ true, false,
+ document.querySelectorAll(".requires-internet")
+ )
+
+ await launcher.check_servers();
+ serverstatus.style.opacity = "1.0";
+ } else {
+ // show toast
+ if (! sent_error_toast) {
+ sent_error_toast = true;
+ ipcRenderer.send("no-internet");
+ }
+
+ // show offline icon
+ offline.classList.remove("hidden");
+
+ // disable buttons that require internet
+ set_buttons(
+ false, false,
+ document.querySelectorAll(".requires-internet")
+ )
+
+ serverstatus.style.opacity = "0.0";
+
+ // close mod browser
+ try {
+ require("./browser").toggle(false);
+ } catch(err) {}
+ }
+}
+
+setTimeout(() => state_action(navigator.onLine), 100);
+window.addEventListener("online", () => state_action(navigator.onLine));
+window.addEventListener("offline", () => state_action(navigator.onLine));
+
+// checks a list of endpoints/domains we need to be functioning for a
+// lot of the WAN functionality
+let check_endpoints = async () => {
+ // if we're not online according to the navigator, it's highly
+ // unlikely the endpoints will succeed
+ if (! navigator.onLine) {
+ return state_action(false);
+ }
+
+ // check endpoints
+ let status = await request.check([
+ "https://github.com",
+ "https://northstar.tf",
+ "https://thunderstore.io"
+ ])
+
+ // handle result of check
+ state_action(!! status.succeeded.length);
+}
+
+// check endpoints on startup
+setTimeout(check_endpoints, 100);
+
+// check endpoints every 30 seconds
+setInterval(check_endpoints, 30000);
+
module.exports = request;
diff --git a/src/app/js/set_buttons.js b/src/app/js/set_buttons.js
index 9cb9d3e..4a0e1b2 100644
--- a/src/app/js/set_buttons.js
+++ b/src/app/js/set_buttons.js
@@ -6,22 +6,24 @@ ipcRenderer.on("set-buttons", (_, state) => {
// disables or enables certain buttons when for example
// updating/installing Northstar.
-module.exports = (state, enable_gamepath_btns) => {
- playNsBtn.disabled = ! state;
+module.exports = (state, enable_gamepath_btns, elements) => {
+ if (! elements) {
+ playNsBtn.disabled = ! state;
+ }
let disable_array = (array) => {
for (let i = 0; i < array.length; i++) {
array[i].disabled = ! state;
if (state) {
- array[i].classList.remove("disabled")
+ array[i].classList.remove("disabled");
} else {
- array[i].classList.add("disabled")
+ array[i].classList.add("disabled");
}
}
}
- disable_array(document.querySelectorAll([
+ disable_array(elements || document.querySelectorAll([
"#modsdiv .el button",
".disable-when-installing",
".playBtnContainer .playBtn",
diff --git a/src/app/js/update.js b/src/app/js/update.js
index d03db02..3732f89 100644
--- a/src/app/js/update.js
+++ b/src/app/js/update.js
@@ -125,7 +125,15 @@ let update = {
// updates Northstar, `force_update` forcefully updates Northstar,
// causing it to update, even if its already up-to-date
- ns: (force_update) => {
+ ns: async (force_update) => {
+ let can_connect = await request.check_with_toasts(
+ "GitHub", "https://github.com"
+ )
+
+ if (! can_connect) {
+ return;
+ }
+
update.ns.last_checked = new Date().getTime();
ipcRenderer.send("update-northstar", force_update);
update.ns.should_install = false;
diff --git a/src/app/main.css b/src/app/main.css
index 9ade423..b6b0ac7 100644
--- a/src/app/main.css
+++ b/src/app/main.css
@@ -59,8 +59,14 @@ button:active {filter: brightness(90%)}
margin-right: calc(var(--padding) / 2);
}
+#winbtns div.hidden {
+ width: 0px;
+ opacity: 0.0;
+ margin-right: 0px;
+ pointer-events: none;
+}
+
#winbtns div img {
- width: 100%;
height: 100%;
transition: transform 0.25s ease-in-out;
}