feat: add Electron desktop app wrapper
This commit is contained in:
8
Makefile
8
Makefile
@@ -1,11 +1,17 @@
|
||||
BINARY := lazy-update-manager
|
||||
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:
|
||||
go build -buildvcs=false -o bin/$(BINARY) ./cmd/lazy-update-manager
|
||||
|
||||
desktop:
|
||||
npm run start
|
||||
|
||||
desktop-dist:
|
||||
npm run dist
|
||||
|
||||
install: build
|
||||
install -Dm755 bin/$(BINARY) $(PREFIX)/bin/$(BINARY)
|
||||
install -Dm644 systemd/lazy-update-manager.desktop $(PREFIX)/share/applications/lazy-update-manager.desktop
|
||||
|
||||
22
README.md
22
README.md
@@ -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
|
||||
- Sends notifications with `notify-send`, with `hyprctl notify` as fallback
|
||||
- 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
|
||||
- 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`
|
||||
- Optional: `paru` or `yay` for AUR updates
|
||||
- Optional: `libnotify` for `notify-send`
|
||||
- Optional: Node.js and npm for the Electron desktop app
|
||||
|
||||
## Build
|
||||
|
||||
@@ -51,6 +53,26 @@ The GUI opens in your browser and lets you:
|
||||
- change the reminder interval
|
||||
- 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
|
||||
|
||||
```sh
|
||||
|
||||
127
electron/main.cjs
Normal file
127
electron/main.cjs
Normal 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
4026
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
41
package.json
Normal file
41
package.json
Normal 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"
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user