feat: add Electron desktop app wrapper

This commit is contained in:
2026-05-03 22:48:17 +02:00
parent 653ff6d298
commit a22d2e16ea
5 changed files with 4223 additions and 1 deletions

View File

@@ -1,11 +1,17 @@
BINARY := lazy-update-manager BINARY := lazy-update-manager
PREFIX ?= $(HOME)/.local PREFIX ?= $(HOME)/.local
.PHONY: build install install-user-service enable-user-service test fmt clean .PHONY: build desktop desktop-dist install install-user-service enable-user-service test fmt clean
build: build:
go build -buildvcs=false -o bin/$(BINARY) ./cmd/lazy-update-manager go build -buildvcs=false -o bin/$(BINARY) ./cmd/lazy-update-manager
desktop:
npm run start
desktop-dist:
npm run dist
install: build install: build
install -Dm755 bin/$(BINARY) $(PREFIX)/bin/$(BINARY) install -Dm755 bin/$(BINARY) $(PREFIX)/bin/$(BINARY)
install -Dm644 systemd/lazy-update-manager.desktop $(PREFIX)/share/applications/lazy-update-manager.desktop install -Dm644 systemd/lazy-update-manager.desktop $(PREFIX)/share/applications/lazy-update-manager.desktop

View File

@@ -8,6 +8,7 @@ LazyUpdateManager is a small update helper for Arch Linux and Hyprland. It check
- Checks AUR updates with `paru -Qua` or `yay -Qua` when either helper is installed - Checks AUR updates with `paru -Qua` or `yay -Qua` when either helper is installed
- Sends notifications with `notify-send`, with `hyprctl notify` as fallback - Sends notifications with `notify-send`, with `hyprctl notify` as fallback
- Provides a graphical browser UI for checking and installing updates - Provides a graphical browser UI for checking and installing updates
- Provides an Electron desktop app wrapper for the GUI
- Includes a systemd user timer that checks every two hours and reminds weekly - Includes a systemd user timer that checks every two hours and reminds weekly
- Provides an interactive `update` command - Provides an interactive `update` command
@@ -18,6 +19,7 @@ LazyUpdateManager is a small update helper for Arch Linux and Hyprland. It check
- `pacman-contrib` recommended for `checkupdates` - `pacman-contrib` recommended for `checkupdates`
- Optional: `paru` or `yay` for AUR updates - Optional: `paru` or `yay` for AUR updates
- Optional: `libnotify` for `notify-send` - Optional: `libnotify` for `notify-send`
- Optional: Node.js and npm for the Electron desktop app
## Build ## Build
@@ -51,6 +53,26 @@ The GUI opens in your browser and lets you:
- change the reminder interval - change the reminder interval
- choose the terminal used for installing updates - choose the terminal used for installing updates
## Desktop App
Install the Electron dependencies once:
```sh
npm install
```
Start the desktop app:
```sh
make desktop
```
Build desktop packages:
```sh
make desktop-dist
```
## Install ## Install
```sh ```sh

127
electron/main.cjs Normal file
View File

@@ -0,0 +1,127 @@
const { app, BrowserWindow, dialog, shell } = require("electron");
const { spawn } = require("node:child_process");
const fs = require("node:fs");
const path = require("node:path");
const readline = require("node:readline");
let mainWindow = null;
let backendProcess = null;
app.disableHardwareAcceleration();
app.commandLine.appendSwitch("ozone-platform-hint", "auto");
function backendBinary() {
const candidates = [
path.join(process.resourcesPath || "", "bin", "lazy-update-manager"),
path.join(app.getAppPath(), "bin", "lazy-update-manager"),
path.join(app.getAppPath(), "..", "bin", "lazy-update-manager"),
];
for (const candidate of candidates) {
if (candidate && fs.existsSync(candidate)) {
return candidate;
}
}
return "lazy-update-manager";
}
function startBackend() {
return new Promise((resolve, reject) => {
const binary = backendBinary();
backendProcess = spawn(binary, ["gui", "-no-open"], {
stdio: ["ignore", "pipe", "pipe"],
env: process.env,
});
let stderr = "";
const rl = readline.createInterface({ input: backendProcess.stdout });
const timeout = setTimeout(() => {
reject(new Error("Backend did not report a GUI URL."));
}, 8000);
rl.on("line", (line) => {
const match = line.match(/LazyUpdateManager GUI:\s+(http:\/\/127\.0\.0\.1:\d+)/);
if (!match) {
return;
}
clearTimeout(timeout);
resolve(match[1]);
});
backendProcess.stderr.on("data", (chunk) => {
stderr += chunk.toString();
});
backendProcess.on("error", (error) => {
clearTimeout(timeout);
reject(error);
});
backendProcess.on("exit", (code) => {
if (mainWindow) {
return;
}
clearTimeout(timeout);
reject(new Error(stderr || `Backend exited with code ${code}`));
});
});
}
async function createWindow() {
const url = await startBackend();
mainWindow = new BrowserWindow({
width: 1180,
height: 760,
minWidth: 860,
minHeight: 560,
title: "LazyUpdateManager",
backgroundColor: "#101114",
autoHideMenuBar: true,
webPreferences: {
contextIsolation: true,
nodeIntegration: false,
sandbox: true,
},
});
mainWindow.webContents.setWindowOpenHandler(({ url: targetURL }) => {
shell.openExternal(targetURL);
return { action: "deny" };
});
await mainWindow.loadURL(url);
}
function stopBackend() {
if (!backendProcess || backendProcess.killed) {
return;
}
backendProcess.kill("SIGTERM");
backendProcess = null;
}
app.whenReady().then(async () => {
try {
await createWindow();
} catch (error) {
await dialog.showMessageBox({
type: "error",
title: "LazyUpdateManager",
message: "Die Desktop-App konnte nicht gestartet werden.",
detail: error.message,
});
app.quit();
}
});
app.on("window-all-closed", () => {
stopBackend();
app.quit();
});
app.on("before-quit", stopBackend);

4026
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

41
package.json Normal file
View File

@@ -0,0 +1,41 @@
{
"name": "lazy-update-manager",
"version": "0.1.0",
"description": "Desktop update helper for Arch Linux and Hyprland.",
"main": "electron/main.cjs",
"type": "commonjs",
"scripts": {
"start": "npm run build:backend && electron .",
"build:backend": "go build -buildvcs=false -o bin/lazy-update-manager ./cmd/lazy-update-manager",
"dist": "npm run build:backend && electron-builder --linux AppImage,pacman,dir"
},
"keywords": [
"arch",
"hyprland",
"updates",
"electron"
],
"author": "",
"license": "MIT",
"devDependencies": {
"electron": "^41.5.0",
"electron-builder": "^26.0.0"
},
"build": {
"appId": "dev.lazyupdatemanager.app",
"productName": "LazyUpdateManager",
"files": [
"electron/**/*"
],
"extraResources": [
{
"from": "bin/lazy-update-manager",
"to": "bin/lazy-update-manager"
}
],
"linux": {
"category": "System",
"icon": "system-software-update"
}
}
}