fix: Electron desktop app startup and add install script

- tryElectronApp() now finds the project directory via
  LAZY_UPDATE_MANAGER_DIR env, CWD, binary path, or $HOME
- Launches node_modules/.bin/electron directly instead of npm start
  (avoids recompiling the Go backend on every launch)
- Add install.sh with Electron fallback, desktop launcher, and
  prefer_electron config
- Desktop entry points to electron launcher for wofi support
- Update electron to v41.7.1
This commit is contained in:
2026-05-27 03:16:40 +02:00
parent 118e10561c
commit bdd51a201a
4 changed files with 305 additions and 15 deletions

View File

@@ -288,20 +288,64 @@ func defaultConfigPath() string {
} }
func tryElectronApp() error { func tryElectronApp() error {
// Try to find and launch the Electron app projectDir := electronProjectDir()
cmd := exec.Command("npm", "start") if projectDir == "" {
cmd.Stdout = nil return errors.New("LazyUpdateManager project directory not found set LAZY_UPDATE_MANAGER_DIR or run from the project folder")
cmd.Stderr = nil }
cmd.Stdin = nil
if err := cmd.Run(); err != nil { electronBin := filepath.Join(projectDir, "node_modules", ".bin", "electron")
// Try electron directly if _, err := os.Stat(electronBin); err != nil {
cmd = exec.Command("electron", ".") electronBin = "electron"
}
cmd := exec.Command(electronBin, projectDir)
cmd.Dir = projectDir
cmd.Stdout = nil cmd.Stdout = nil
cmd.Stderr = nil cmd.Stderr = nil
cmd.Stdin = nil cmd.Stdin = nil
return cmd.Run() return cmd.Run()
} }
return nil
func electronProjectDir() string {
if d := os.Getenv("LAZY_UPDATE_MANAGER_DIR"); d != "" {
if hasElectronMain(d) {
return d
}
}
if d, err := os.Getwd(); err == nil && hasElectronMain(d) {
return d
}
exe, err := os.Executable()
if err != nil {
return ""
}
exeDir := filepath.Dir(exe)
// binary in ~/Projekte/LazyUpdateManager/bin/
if p := filepath.Dir(exeDir); hasElectronMain(p) {
return p
}
// binary in ~/.local/bin/, project is at configured location
if p := filepath.Join(exeDir, "..", "Projekte", "LazyUpdateManager"); hasElectronMain(p) {
return p
}
// relative to $HOME
if home, err := os.UserHomeDir(); err == nil {
if p := filepath.Join(home, "Projekte", "LazyUpdateManager"); hasElectronMain(p) {
return p
}
}
return ""
}
func hasElectronMain(dir string) bool {
info, err := os.Stat(filepath.Join(dir, "electron", "main.cjs"))
return err == nil && !info.IsDir()
} }
func usage() { func usage() {

246
install.sh Executable file
View File

@@ -0,0 +1,246 @@
#!/usr/bin/env bash
set -euo pipefail
BINARY="lazy-update-manager"
PREFIX="${PREFIX:-$HOME/.local}"
PROJECT_DIR="$(cd "$(dirname "$0")" && pwd)"
VERSION="$(git describe --tags --always --dirty 2>/dev/null || echo dev)"
BUILD_TIME="$(date -u +'%Y-%m-%dT%H:%M:%SZ')"
RED='\033[0;31m'
GREEN='\033[0;32m'
CYAN='\033[0;36m'
NC='\033[0m'
info() { echo -e "${CYAN}::${NC} $*"; }
ok() { echo -e "${GREEN} ->${NC} $*"; }
error() { echo -e "${RED} ->${NC} $*" >&2; }
cleanup() {
if [ -n "${TMP_CONFIG:-}" ]; then
rm -f "$TMP_CONFIG"
fi
}
trap cleanup EXIT
check_deps() {
local missing=false
for cmd in go node npm; do
if ! command -v "$cmd" &>/dev/null; then
error "$cmd ist nicht installiert"
missing=true
fi
done
if [ "$missing" = true ]; then
error "Installiere die fehlenden Abhängigkeiten und versuche es erneut."
exit 1
fi
ok "Alle Abhängigkeiten vorhanden (go $(go version | grep -oP '\d+\.\d+' | head -1), node $(node -v), npm $(npm -v))"
}
build_backend() {
info "Baue Go-Backend (Version: $VERSION, Build: $BUILD_TIME)"
mkdir -p "$PROJECT_DIR/bin"
go build -buildvcs=false \
-ldflags "-X 'lazy-update-manager/internal/version.Version=$VERSION' -X 'lazy-update-manager/internal/version.BuildTime=$BUILD_TIME'" \
-o "$PROJECT_DIR/bin/$BINARY" "$PROJECT_DIR/cmd/lazy-update-manager"
ok "Backend gebaut: bin/$BINARY"
}
install_npm() {
info "Installiere npm-Abhängigkeiten (Electron)"
npm install --prefix "$PROJECT_DIR"
if [ ! -f "$PROJECT_DIR/node_modules/electron/path.txt" ]; then
info "Electron-Binary fehlt versuche manuelle Installation"
ELECTRON_CACHE="$HOME/.cache/electron"
ELECTRON_DIR="$PROJECT_DIR/node_modules/electron"
if [ -d "$ELECTRON_CACHE" ]; then
CACHE_DIR=$(ls -t "$ELECTRON_CACHE" | head -1)
ZIP_FILE=$(ls "$ELECTRON_CACHE/$CACHE_DIR"/*.zip 2>/dev/null | head -1)
if [ -n "$ZIP_FILE" ] && [ -f "$ZIP_FILE" ]; then
rm -rf "$ELECTRON_DIR/dist"
mkdir -p "$ELECTRON_DIR/dist"
unzip -q "$ZIP_FILE" -d "$ELECTRON_DIR/dist/"
printf 'electron' > "$ELECTRON_DIR/path.txt"
chmod +x "$ELECTRON_DIR/dist/electron"
ok "Electron-Binary manuell installiert (${ZIP_FILE##*/})"
fi
fi
if [ ! -f "$ELECTRON_DIR/path.txt" ]; then
error "Electron-Binary konnte nicht installiert werden"
error "Versuche: rm -rf node_modules && npm install"
exit 1
fi
fi
ok "npm-Abhängigkeiten installiert"
}
install_binary() {
info "Installiere Binary nach $PREFIX/bin"
mkdir -p "$PREFIX/bin"
command install -Dm755 "$PROJECT_DIR/bin/$BINARY" "$PREFIX/bin/$BINARY"
ok "Binary installiert: $PREFIX/bin/$BINARY"
}
install_electron_launcher() {
info "Installiere Electron-Launcher nach $PREFIX/bin"
mkdir -p "$PREFIX/bin"
cat > "$PREFIX/bin/lazy-update-manager-electron" <<'LAUNCHER'
#!/bin/sh
export LAZY_UPDATE_MANAGER_DIR="__PROJECT_DIR__"
cd "$LAZY_UPDATE_MANAGER_DIR" || exit 1
exec ./node_modules/.bin/electron .
LAUNCHER
sed -i "s|__PROJECT_DIR__|$PROJECT_DIR|g" "$PREFIX/bin/lazy-update-manager-electron"
chmod +x "$PREFIX/bin/lazy-update-manager-electron"
ok "Electron-Launcher installiert: $PREFIX/bin/lazy-update-manager-electron"
}
install_desktop_file() {
info "Installiere Desktop-Eintrag"
mkdir -p "$PREFIX/share/applications"
cat > "$PREFIX/share/applications/lazy-update-manager.desktop" <<EOF
[Desktop Entry]
Type=Application
Name=LazyUpdateManager
Comment=Arch and Hyprland update helper
Exec=$PREFIX/bin/lazy-update-manager-electron
Icon=system-software-update
Terminal=false
Categories=System;Utility;
EOF
ok "Desktop-Eintrag installiert: $PREFIX/share/applications/lazy-update-manager.desktop"
}
enable_electron_config() {
info "Setze PreferElectron=true in der Konfiguration"
mkdir -p "$HOME/.config/lazy-update-manager"
CONFIG_FILE="$HOME/.config/lazy-update-manager/config.json"
if [ -f "$CONFIG_FILE" ]; then
# Update prefer_electron in existing config
tmp="$(mktemp)"
python3 -c "
import json
with open('$CONFIG_FILE') as f:
cfg = json.load(f)
cfg['prefer_electron'] = True
with open('$tmp', 'w') as f:
json.dump(cfg, f, indent=2)
f.write('\n')
" 2>/dev/null || {
# fallback: jq or sed
if command -v jq &>/dev/null; then
jq '.prefer_electron = true' "$CONFIG_FILE" > "$tmp" && cp "$tmp" "$CONFIG_FILE"
else
info "Konnte Config nicht automatisch aktualisieren, setze prefer_electron manuell"
fi
}
if [ -f "$tmp" ]; then
cp "$tmp" "$CONFIG_FILE" && rm -f "$tmp"
fi
else
cat > "$CONFIG_FILE" <<EOF
{
"prefer_electron": true,
"check_aur": true,
"reminder_interval_hours": 168,
"terminal": "auto",
"language": "de",
"auto_refresh_minutes": 30,
"show_ignored": false,
"notifications_enabled": true,
"keep_terminal_open": true,
"confirm_selected_installs": true,
"ignored_packages": []
}
EOF
fi
ok "PreferElectron aktiviert 'lazy-update-manager gui' startet jetzt die Desktop-App"
}
install_systemd() {
info "Installiere systemd-User-Service und Timer"
mkdir -p "$HOME/.config/systemd/user"
command install -Dm644 "$PROJECT_DIR/systemd/lazy-update-manager.service" "$HOME/.config/systemd/user/lazy-update-manager.service"
command install -Dm644 "$PROJECT_DIR/systemd/lazy-update-manager.timer" "$HOME/.config/systemd/user/lazy-update-manager.timer"
ok "systemd-Dateien installiert"
if command -v systemctl &>/dev/null; then
info "Aktiviere Timer"
systemctl --user daemon-reload 2>/dev/null || true
systemctl --user enable --now lazy-update-manager.timer 2>/dev/null || true
ok "Timer aktiviert: systemctl --user status lazy-update-manager.timer"
else
info "systemctl nicht verfügbar. Manuell aktivieren:"
info " systemctl --user daemon-reload"
info " systemctl --user enable --now lazy-update-manager.timer"
fi
}
build_electron_dist() {
info "Baue Electron-Desktop-Pakete"
npm run --prefix "$PROJECT_DIR" dist
ok "Electron-Pakete gebaut: dist/"
}
run_install() {
echo -e "${CYAN}========================================${NC}"
echo -e "${CYAN} LazyUpdateManager Installer${NC}"
echo -e "${CYAN}========================================${NC}"
echo ""
check_deps
echo ""
install_npm
echo ""
build_backend
echo ""
install_binary
echo ""
install_electron_launcher
echo ""
install_desktop_file
echo ""
enable_electron_config
echo ""
install_systemd
echo ""
echo -e "${GREEN}========================================${NC}"
echo -e "${GREEN} Installation abgeschlossen!${NC}"
echo -e "${GREEN}========================================${NC}"
echo ""
echo "Desktop-App starten: $PREFIX/bin/lazy-update-manager-electron"
echo "Web-Oberfläche starten: $PREFIX/bin/$BINARY gui web"
echo "Updates prüfen: $PREFIX/bin/$BINARY check"
echo "Status anzeigen: $PREFIX/bin/$BINARY status"
echo ""
}
build_electron() {
check_deps
install_npm
build_backend
build_electron_dist
echo ""
echo -e "${GREEN}Electron-Pakete erstellt in: $PROJECT_DIR/dist/${NC}"
}
usage() {
cat <<EOF
Verwendung: $0 [option]
Optionen:
install (Standard) Installiere alles (Backend, npm, Binary, Desktop-Eintrag, systemd-Timer)
electron-dist Baue Electron-Desktop-Pakete (AppImage, Pacman)
help Diese Hilfe anzeigen
EOF
}
case "${1:-install}" in
install) run_install ;;
electron-dist) build_electron ;;
help|--help|-h) usage ;;
*) error "Unbekannte Option: $1"; usage; exit 1 ;;
esac

8
package-lock.json generated
View File

@@ -9,7 +9,7 @@
"version": "0.1.0", "version": "0.1.0",
"license": "MIT", "license": "MIT",
"devDependencies": { "devDependencies": {
"electron": "^41.5.0", "electron": "^41.7.1",
"electron-builder": "^26.0.0" "electron-builder": "^26.0.0"
} }
}, },
@@ -1747,9 +1747,9 @@
} }
}, },
"node_modules/electron": { "node_modules/electron": {
"version": "41.5.0", "version": "41.7.1",
"resolved": "https://registry.npmjs.org/electron/-/electron-41.5.0.tgz", "resolved": "https://registry.npmjs.org/electron/-/electron-41.7.1.tgz",
"integrity": "sha512-x9j9//PubUA4EjDtQbZhtk3prolandqCKgit0uCIqc1jb8FTskPbnJtxcDFB1aejczJcuERgjPixBUaMwoWyJg==", "integrity": "sha512-pdRvNNP99Qfvs1lyIxo/sfIGAwJP0CrJFNCE3goFKc7/fV+kjK3EPxx5Nt6sLTkzqTyeRYylpwPUfpeGojiyyw==",
"dev": true, "dev": true,
"hasInstallScript": true, "hasInstallScript": true,
"license": "MIT", "license": "MIT",

View File

@@ -18,7 +18,7 @@
"author": "", "author": "",
"license": "MIT", "license": "MIT",
"devDependencies": { "devDependencies": {
"electron": "^41.5.0", "electron": "^41.7.1",
"electron-builder": "^26.0.0" "electron-builder": "^26.0.0"
}, },
"build": { "build": {