From f6e0e4dd0966ef79cb19bfcc1770f8a66d0dbec8 Mon Sep 17 00:00:00 2001 From: byGalax Date: Sat, 16 May 2026 19:04:03 +0200 Subject: [PATCH] feat(P3.T3): app:hostname IPC for device-name default --- apps/desktop/electron/ipc-types.ts | 5 +++++ apps/desktop/electron/main.ts | 2 ++ apps/desktop/electron/modules/app-hostname.ts | 21 +++++++++++++++++++ apps/desktop/electron/preload-types.d.ts | 7 +++++++ apps/desktop/electron/preload.ts | 3 +++ 5 files changed, 38 insertions(+) create mode 100644 apps/desktop/electron/modules/app-hostname.ts diff --git a/apps/desktop/electron/ipc-types.ts b/apps/desktop/electron/ipc-types.ts index 98527ad..77e982a 100644 --- a/apps/desktop/electron/ipc-types.ts +++ b/apps/desktop/electron/ipc-types.ts @@ -114,6 +114,11 @@ export const CHANNELS = { // timeout, whichever comes first). /** Main → renderer: about to quit. Renderer wipes, then resolves. */ APP_WIPE_BEFORE_QUIT: 'app:wipe-before-quit', + + // OS hostname — returns the machine hostname via Node's `os.hostname()`. + // Used by AuthContext on first launch to populate the `devices` row with + // a human-readable default device name. Returns null on failure. + APP_HOSTNAME: 'app:hostname', } as const; // ---- Screen sources ------------------------------------------------------ diff --git a/apps/desktop/electron/main.ts b/apps/desktop/electron/main.ts index cc450ac..d5311a5 100644 --- a/apps/desktop/electron/main.ts +++ b/apps/desktop/electron/main.ts @@ -12,6 +12,7 @@ import { fileURLToPath } from 'node:url'; import { CHANNELS } from './ipc-types'; import { register as registerAudioLoopback } from './modules/audio-loopback'; +import { register as registerAppHostname } from './modules/app-hostname'; import { register as registerAutostart } from './modules/autostart'; import { register as registerFsScoped } from './modules/fs-scoped'; import { register as registerNotifications } from './modules/notifications'; @@ -254,6 +255,7 @@ if (!gotLock) { registerFsScoped(); registerSql(); registerAutostart(); + registerAppHostname(); // Window-dependent registrars — only call once mainWindow exists so // event emitters have somewhere to send. diff --git a/apps/desktop/electron/modules/app-hostname.ts b/apps/desktop/electron/modules/app-hostname.ts new file mode 100644 index 0000000..9cebdb4 --- /dev/null +++ b/apps/desktop/electron/modules/app-hostname.ts @@ -0,0 +1,21 @@ +// app:hostname adapter — returns the OS hostname via Node's `os.hostname()`. +// The renderer has no Node access (contextIsolation is ON), so it must ask +// main for this value. Used by AuthContext on first launch to populate the +// `devices` row with a human-readable default device name. + +import os from 'node:os'; + +import { ipcMain } from 'electron'; + +import { CHANNELS } from '../ipc-types'; + +export function register(): void { + ipcMain.handle(CHANNELS.APP_HOSTNAME, (): string | null => { + try { + const h = os.hostname(); + return typeof h === 'string' && h.length > 0 ? h : null; + } catch { + return null; + } + }); +} diff --git a/apps/desktop/electron/preload-types.d.ts b/apps/desktop/electron/preload-types.d.ts index ee02da7..7d8e647 100644 --- a/apps/desktop/electron/preload-types.d.ts +++ b/apps/desktop/electron/preload-types.d.ts @@ -99,6 +99,13 @@ export interface ElectronAPI { /** Subscribe to the main-process pre-quit notification. Used by the * "Cache beim Schließen leeren" Settings toggle. */ onWipeBeforeQuit: (cb: () => Promise) => () => void; + + /** Returns the OS hostname (via Node's `os.hostname()`). Used by + * AuthContext on first launch to populate the `devices` row with a + * human-readable default device name. Optional: always feature-check + * via `typeof window.electronAPI?.getHostname === 'function'` because + * the web build has no preload bridge. */ + getHostname?: () => Promise; } declare global { diff --git a/apps/desktop/electron/preload.ts b/apps/desktop/electron/preload.ts index 5855d02..a3fb1c7 100644 --- a/apps/desktop/electron/preload.ts +++ b/apps/desktop/electron/preload.ts @@ -160,6 +160,9 @@ const api = { setFullscreen: (enabled: boolean): Promise => ipcRenderer.invoke(CHANNELS.WINDOW_SET_FULLSCREEN, enabled), + // OS hostname ------------------------------------------------------------ + getHostname: (): Promise => ipcRenderer.invoke(CHANNELS.APP_HOSTNAME), + // Wipe-on-close ---------------------------------------------------------- // Subscribe to the main-process pre-quit notification. The renderer's // callback does the actual wipe (memoryWipe.ts) and resolves; we ack