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:
parent
d792a72dc2
commit
fac4ba3cde
2 changed files with 42 additions and 0 deletions
|
|
@ -1002,6 +1002,24 @@ if (process.platform === 'linux') {
|
||||||
app.setDesktopName('keynectr.desktop');
|
app.setDesktopName('keynectr.desktop');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Launched from the applications list a second time? Focus the existing
|
||||||
|
// window instead of starting a duplicate app (two Electron shells would
|
||||||
|
// each spawn their own backend and fight over the vault file).
|
||||||
|
const gotInstanceLock = app.requestSingleInstanceLock();
|
||||||
|
if (!gotInstanceLock) {
|
||||||
|
// Hard exit: app.quit() is async and would let the rest of this module
|
||||||
|
// (whenReady → backend spawn) run in the doomed second instance.
|
||||||
|
app.exit(0);
|
||||||
|
} else {
|
||||||
|
app.on('second-instance', () => {
|
||||||
|
const [window] = BrowserWindow.getAllWindows();
|
||||||
|
if (window) {
|
||||||
|
if (window.isMinimized()) window.restore();
|
||||||
|
window.focus();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
app.whenReady().then(() => {
|
app.whenReady().then(() => {
|
||||||
protocol.handle('app', (request) => {
|
protocol.handle('app', (request) => {
|
||||||
const { pathname } = new URL(request.url);
|
const { pathname } = new URL(request.url);
|
||||||
|
|
|
||||||
24
launch-keynctr.sh
Executable file
24
launch-keynctr.sh
Executable 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" "$@"
|
||||||
Loading…
Add table
Add a link
Reference in a new issue