diff --git a/main.js b/main.js
index 390d5e0..5df3082 100644
--- a/main.js
+++ b/main.js
@@ -11,6 +11,7 @@ import { path7za } from "7zip-bin";
import node7z from "node-7z";
const { extractFull } = node7z;
import packageJson from "./package.json" with { type: "json" };
+import semverGt from "semver/functions/gt.js";
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
@@ -79,6 +80,9 @@ async function createWindow() {
mainWindow.once("ready-to-show", () => {
mainWindow.show();
+ if (!isDev) {
+ verifyUpdate();
+ }
});
}
@@ -115,6 +119,51 @@ app.on("open-url", (event, url) => {
handleNxmUrl(url);
});
+async function verifyUpdate() {
+ const GITHUB_URL = "https://api.github.com/repos/Gabi-Zar/Silk-Fly-Launcher/releases";
+
+ const res = await fetch(GITHUB_URL, {
+ headers: {
+ "User-Agent": userAgent,
+ Accept: "application/vnd.github+json",
+ },
+ });
+
+ if (!res.ok) {
+ if (res.status == 403) {
+ mainWindow.webContents.send("showToast", "Github has blocked the application. Please try again later.", "error");
+ }
+ throw new Error(`GitHub API error: ${res.status}`);
+ }
+
+ const releases = await res.json();
+ const prerelease = releases.find((r) => r.prerelease);
+ const release = releases.find((r) => !r.prerelease && !r.draft);
+
+ let prereleaseVersion;
+ let releaseVersion;
+ let latestVersion;
+
+ if (prerelease) {
+ prereleaseVersion = prerelease.tag_name.replace(/^v/, "");
+ latestVersion = prereleaseVersion;
+ }
+ if (release) {
+ releaseVersion = release.tag_name.replace(/^v/, "");
+ latestVersion = releaseVersion;
+ }
+
+ if (prereleaseVersion && releaseVersion) {
+ latestVersion = semverGt(prereleaseVersion, releaseVersion) ? prereleaseVersion : releaseVersion;
+ }
+ if (latestVersion != VERSION) {
+ mainWindow.webContents.send(
+ "showBanner",
+ `Update v${latestVersion} is available on GitHub! Your current version is ${VERSION}.`,
+ );
+ }
+}
+
//////////////////////////////////////////////////////
///////////////// SAVING AND LOADING /////////////////
ipcMain.handle("save-path", (event, path) => {
diff --git a/package-lock.json b/package-lock.json
index f502a14..0e72d76 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "silkflylauncher",
- "version": "1.0.0",
+ "version": "1.0.0-dev",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "silkflylauncher",
- "version": "1.0.0",
+ "version": "1.0.0-dev",
"license": "GPL-3.0",
"dependencies": {
"@nexusmods/nexus-api": "^1.1.5",
@@ -14,7 +14,8 @@
"electron-store": "^11.0.2",
"graphql": "^16.12.0",
"graphql-request": "^7.4.0",
- "node-7z": "^3.0.0"
+ "node-7z": "^3.0.0",
+ "semver": "^7.7.4"
},
"devDependencies": {
"@electron-forge/cli": "^7.11.1",
diff --git a/package.json b/package.json
index 4708ce8..136024f 100644
--- a/package.json
+++ b/package.json
@@ -30,7 +30,8 @@
"electron-store": "^11.0.2",
"graphql": "^16.12.0",
"graphql-request": "^7.4.0",
- "node-7z": "^3.0.0"
+ "node-7z": "^3.0.0",
+ "semver": "^7.7.4"
},
"AES-key-nexus-api": "__AES_KEY__"
}
diff --git a/preload.js b/preload.js
index 07c4402..7c39da3 100644
--- a/preload.js
+++ b/preload.js
@@ -34,6 +34,11 @@ contextBridge.exposeInMainWorld("electronAPI", {
callback(message, type, duration);
});
},
+ onShowBanner: (callback) => {
+ ipcRenderer.on("showBanner", (event, message) => {
+ callback(message);
+ });
+ },
});
contextBridge.exposeInMainWorld("bepinex", {
diff --git a/renderer/index.html b/renderer/index.html
index 48ef77c..b87c2e6 100644
--- a/renderer/index.html
+++ b/renderer/index.html
@@ -58,6 +58,10 @@
+
Silk Fly Launcher
diff --git a/renderer/renderer.js b/renderer/renderer.js
index 6b18b36..40c809d 100644
--- a/renderer/renderer.js
+++ b/renderer/renderer.js
@@ -739,6 +739,23 @@ function showToast(message, type = "info", duration = 3000) {
electronAPI.onShowToast(showToast);
+function showBanner(message) {
+ const bannerDiv = document.getElementById("banner-div");
+ const bannerText = document.getElementById("banner-text");
+
+ console.log(bannerDiv);
+
+ bannerText.innerHTML = message;
+ bannerDiv.classList.add("show");
+}
+
+electronAPI.onShowBanner(showBanner);
+
+function hideBanner() {
+ const bannerDiv = document.getElementById("banner-div");
+ bannerDiv.classList.remove("show");
+}
+
function changeModsPage(offsetChange) {
if (oldPage == "mods-installed") {
if (offsetChange == "min") {
diff --git a/renderer/style.css b/renderer/style.css
index 2ef1607..685943d 100644
--- a/renderer/style.css
+++ b/renderer/style.css
@@ -447,3 +447,19 @@ body {
.long-text {
overflow-wrap: anywhere;
}
+
+.banner-div {
+ display: none;
+ align-items: center;
+ justify-content: space-between;
+ border: 1px solid var(--secondary-color);
+ background: var(--primary-color);
+ margin-bottom: 20px;
+ height: 64px;
+ border-radius: 12px;
+ padding: 10px;
+}
+
+.banner-div.show {
+ display: flex;
+}