feat(desktop): launch from the applications list (folio-style)

- launch-keynctr.sh: builds renderer/electron main if missing, exports
  KEYNCTR_ENABLE_GPU=1 (software rendering dies 'GPU process isn't
  usable' on this Hyprland box), execs bundled electron with
  --class=keynectr for WM_CLASS grouping.
- keynctr.desktop installed at ~/.local/share/applications/ (validated,
  icon = public/icon.png, categories Utility, StartupWMClass keynectr).
- requestSingleInstanceLock: second launch focuses the existing window
  (app.exit(0) in the doomed instance) instead of a duplicate shell
  fighting the vault.
Verified via gtk-launch: 'keynectr | Keynctr' window maps; second
gtk-launch keeps exactly 1 window.
This commit is contained in:
Avi 2026-09-30 09:35:25 -05:00
commit fac4ba3cde
2 changed files with 42 additions and 0 deletions

24
launch-keynctr.sh Executable file
View file

@ -0,0 +1,24 @@
#!/usr/bin/env bash
# Launch Keynctr desktop (Electron shell + Rust backend spawned on demand).
# Production mode: loads the built renderer (frontend/dist) — no Vite needed.
set -euo pipefail
APP_DIR="/home/avi/Projects/Keynctr/frontend"
cd "$APP_DIR"
# The Electron shell spawns target/release/keynectr; make sure it exists and
# is newer-checked lazily by the app itself. We only guarantee the renderer
# bundle is present, else build it (first run or after a clean checkout).
if [[ ! -f "$APP_DIR/dist/index.html" || ! -f "$APP_DIR/dist-electron/main.js" ]]; then
npm run build >/dev/null 2>&1 || npm run build
npm run electron:build >/dev/null 2>&1 || npm run electron:build
fi
# On this Hyprland machine native-Wayland rendering needs hardware GL:
# software rendering dies with "GPU process isn't usable" (verified
# 2026-09-30). Same setting the dev workflow uses.
export KEYNCTR_ENABLE_GPU=1
# --class pins WM_CLASS so the launcher icon groups with the window
# (StartupWMClass=keynectr in the .desktop file).
exec "$APP_DIR/node_modules/.bin/electron" --class=keynectr "$APP_DIR" "$@"