Refactor: auto-update functionality with user prompts and download progress

This commit is contained in:
MasterAcnolo
2026-04-12 16:57:39 +02:00
parent 011e0a703a
commit 75fdf91fcd
6 changed files with 106 additions and 42 deletions

View File

@@ -1,47 +1,83 @@
const { autoUpdater } = require("electron-updater"); const { autoUpdater } = require("electron-updater");
const { app, Notification, shell} = require("electron"); const { dialog } = require("electron");
const { logger } = require("../server/logger"); const { logger } = require("../server/logger");
function AutoUpdater() { autoUpdater.autoDownload = false;
autoUpdater.autoInstallOnAppQuit = false;
autoUpdater.on("update-available", (info) => { function initAutoUpdater(mainWindow) {
logger.info(`New Version Available : ${info.version}`); autoUpdater.on("update-available", async (info) => {
new Notification({ logger.info(`Update available: ${info.version}`);
title: "Freedom Loader",
body: `New Version Available : ${info.version}. Application will restart` const { response } = await dialog.showMessageBox(mainWindow, {
}).show(); type: "info",
title: "Update Available",
message: `Version ${info.version} is available.`,
detail: "Would you like to download and install it now?",
buttons: ["Install Update", "Maybe Later"],
defaultId: 0,
cancelId: 1,
}); });
autoUpdater.on("update-downloaded", (info) => { if (response === 0) {
logger.info(`Update Downloaded : ${info.version}`); autoUpdater.downloadUpdate();
new Notification({ } else {
title: "Freedom Loader", mainWindow?.webContents.executeJavaScript(
body: `Update ${info.version} downloaded.` `window.showUpdateBadge && window.showUpdateBadge("${info.version}")`
}).on("click", () => );
shell.openExternal("https://github.com/MasterAcnolo/Freedom-Loader/releases/latest") }
).show(); });
setTimeout(() => { autoUpdater.on("download-progress", (progress) => {
autoUpdater.quitAndInstall(); logger.info(`Download progress: ${Math.round(progress.percent)}%`);
}, 5000); mainWindow?.webContents.send("update-progress", {
percent: Math.round(progress.percent),
speed: progress.bytesPerSecond,
});
});
autoUpdater.on("update-downloaded", async (info) => {
logger.info(`Update downloaded: ${info.version}`);
const { response } = await dialog.showMessageBox(mainWindow, {
type: "info",
title: "Update Ready",
message: `Version ${info.version} has been downloaded.`,
detail: "The application will restart to apply the update.",
buttons: ["Restart & Install", "Later"],
defaultId: 0,
cancelId: 1,
});
if (response === 0) autoUpdater.quitAndInstall();
}); });
autoUpdater.on("error", (err) => { autoUpdater.on("error", (err) => {
logger.error("Auto Update Error :", err.message); logger.error("Auto update error:", err.message);
new Notification({ dialog.showErrorBox("Update Error", err.message);
title: "Freedom Loader - Update Error",
body: err.message
}).show();
}); });
app.whenReady().then(async () => { checkForUpdates();
}
async function checkForUpdates() {
try { try {
await autoUpdater.checkForUpdates(); await autoUpdater.checkForUpdates();
logger.info("Update check completed");
} catch (err) { } catch (err) {
logger.error("Error during update check :", err.message); logger.error("Update check failed:", err.message);
} }
});
} }
module.exports = { AutoUpdater }; async function downloadUpdate() {
try {
await autoUpdater.downloadUpdate();
} catch (err) {
logger.error("Download failed:", err.message);
}
}
function installUpdate() {
autoUpdater.quitAndInstall();
}
module.exports = { initAutoUpdater, downloadUpdate, installUpdate };

View File

@@ -1,10 +1,11 @@
const { BrowserWindow } = require("electron"); const { BrowserWindow, app } = require("electron");
const path = require("path"); const path = require("path");
let splashWindow = null; let splashWindow = null;
function createSplashWindow() { function createSplashWindow() {
splashWindow = new BrowserWindow({
const splashOptions = {
width: 400, width: 400,
height: 300, height: 300,
frame: false, frame: false,
@@ -16,9 +17,29 @@ function createSplashWindow() {
nodeIntegration: false, nodeIntegration: false,
contextIsolation: true, contextIsolation: true,
}, },
}); };
splashWindow.loadFile(path.join(__dirname, "../public/splash.html")); splashWindow = new BrowserWindow(splashOptions);
const splashPath = path.join(__dirname, "../public/splash.html");
splashWindow.loadFile(splashPath);
// Inject banner path for both dev and packaged app
splashWindow.webContents.on('did-finish-load', () => {
let bannerPath;
// Check if app is packaged
if (app.isPackaged) {
bannerPath = path.join(process.resourcesPath, 'banner.png');
} else {
// In dev, use build folder
bannerPath = path.join(__dirname, '../build/banner.png');
}
splashWindow.webContents.executeJavaScript(`
document.querySelector('img[alt="Freedom Loader"]').src = 'file:///${bannerPath.replace(/\\/g, '/')}';
`);
});
} }
function closeSplashWindow() { function closeSplashWindow() {

View File

@@ -12,7 +12,7 @@ async function createMainWindow() {
return mainWindow; return mainWindow;
} }
mainWindow = new BrowserWindow({ const windowOptions = {
title: `Freedom Loader ${config.version}`, title: `Freedom Loader ${config.version}`,
width: 750, width: 750,
height: 800, height: 800,
@@ -26,7 +26,9 @@ async function createMainWindow() {
contextIsolation: true, contextIsolation: true,
preload: path.join(__dirname, "../preload.js"), preload: path.join(__dirname, "../preload.js"),
}, },
}); };
mainWindow = new BrowserWindow(windowOptions);
try { try {
await mainWindow.loadURL(`http://localhost:${config.applicationPort}`); await mainWindow.loadURL(`http://localhost:${config.applicationPort}`);

View File

@@ -13,7 +13,7 @@ const { createSplashWindow, closeSplashWindow, setSplashProgress } = require("./
const path = require("path"); const path = require("path");
const { logger, logSessionStart, logSessionEnd } = require("./server/logger"); const { logger, logSessionStart, logSessionEnd } = require("./server/logger");
const { AutoUpdater } = require("./app/autoUpdater"); const { initAutoUpdater } = require("./app/autoUpdater");
const { startRPC, stopRPC } = require("./app/discordRPC"); const { startRPC, stopRPC } = require("./app/discordRPC");
const { configFeatures } = require("./config"); const { configFeatures } = require("./config");
@@ -25,6 +25,7 @@ const { updateYtDlp } = require("./app/ytDlpUpdater");
const { createMainWindow, getMainWindow } = require("./app/windowManager"); const { createMainWindow, getMainWindow } = require("./app/windowManager");
const { registerIpcHandlers } = require("./app/ipcHandlers"); const { registerIpcHandlers } = require("./app/ipcHandlers");
app.setName("Freedom Loader");
app.setAppUserModelId("com.masteracnolo.freedomloader"); app.setAppUserModelId("com.masteracnolo.freedomloader");
app.disableHardwareAcceleration(); app.disableHardwareAcceleration();
@@ -72,7 +73,7 @@ app.whenReady().then(async () => {
getMainWindow().show(); getMainWindow().show();
if (configFeatures.discordRPC) startRPC(); if (configFeatures.discordRPC) startRPC();
if (configFeatures.autoUpdate) AutoUpdater(getMainWindow()); if (configFeatures.autoUpdate) initAutoUpdater(getMainWindow());
} catch (err) { } catch (err) {
logger.error("Boot error:", err); logger.error("Boot error:", err);

View File

@@ -62,6 +62,10 @@
"from": "build/banner.bmp", "from": "build/banner.bmp",
"to": "banner.bmp" "to": "banner.bmp"
}, },
{
"from": "build/banner.png",
"to": "banner.png"
},
{ {
"from": "build/error.png", "from": "build/error.png",
"to": "error.png" "to": "error.png"

View File

@@ -53,7 +53,7 @@
<body> <body>
<div class="splash-container"> <div class="splash-container">
<img src="../build/banner.png" alt="Freedom Loader" style="width: 90%;"> <img src="./banner.png" alt="Freedom Loader" style="width: 90%;">
<div class="progress-wrapper"> <div class="progress-wrapper">
<div class="progress-track"> <div class="progress-track">
<div class="progress-bar" id="progress-bar"></div> <div class="progress-bar" id="progress-bar"></div>