# HiveOps Browser — System Info Footer Status Bar ## Context The HiveOps Browser (Electron 28) currently loads `https://incident.bcos.cloud` directly in the main `BrowserWindow`. The user wants a persistent footer status bar — native to the browser chrome like a menu/status bar — showing: logged-in user, memory usage, CPU usage, and service health. This replaces the fragile approach of having the Svelte frontend call `electronAPI.getUserProfile()`. ## Architecture Change **Current**: `BrowserWindow` → `loadURL('https://incident.bcos.cloud')` (fills full window) **New**: `BrowserWindow` (no content) → - `WebContentsView` (top, full width, `height - 32px`) → `loadURL('https://incident.bcos.cloud')` - `WebContentsView` (bottom, full width, `32px`) → `loadFile('src/renderer/statusbar.html')` Electron 28's `WebContentsView` API is used (replaces deprecated `BrowserView`). --- ## Files to Modify / Create ### 1. `src/main/preload.js` — Add 2 new IPC bindings ```javascript getSystemInfo: () => ipcRenderer.invoke('get-system-info'), getServiceStatus: () => ipcRenderer.invoke('get-service-status'), ``` ### 2. `src/main/main.js` — Major changes - Import `WebContentsView` from electron - Create `incidentView` (WebContentsView with preload) and `statusbarView` (WebContentsView with preload) - Replace `mainWindow.loadURL(allowedUrl)` with: - `mainWindow.contentView.addChildView(incidentView)` → `incidentView.webContents.loadURL(allowedUrl)` - `mainWindow.contentView.addChildView(statusbarView)` → `statusbarView.webContents.loadFile('statusbar.html')` - Migrate all `mainWindow.webContents.*` event listeners to `incidentView.webContents.*`: - `did-finish-load`, `dom-ready`, `console-message`, `did-fail-load`, `page-title-updated`, `will-navigate` - Move session header injection to `incidentView.webContents.session.webRequest.onBeforeSendHeaders` - Add `mainWindow.on('resize', updateBounds)` to keep views sized correctly - Add `updateBounds()` helper: sets incidentView to `{x:0, y:0, w, h-32}` and statusbarView to `{x:0, y:h-32, w, h:32}` - Add new IPC handlers: - `get-system-info` → uses Node `os` module: `{ memory: {used, total, percent}, cpu: {load}, user: authManager.getUserInfo() }` - `get-service-status` → pings health endpoints with `net.request()`, returns array of `{name, status: 'up'|'down'|'checking'}` ### 3. `src/renderer/statusbar.html` — New file Compact 32px dark status bar with 3 sections: ``` [ 👤 John Doe ADMIN ] ──── [ RAM 52% ████░░ 4.2/8GB ] [ CPU 23% ] ──── [ ● Auth ● Incident ● Config ] ──── [ v2.0.40 ] ``` - Dark background `#0f0f1a` with subtle top border `rgba(255,255,255,0.08)` - White/muted text, monospace for metrics - Service dots: green `●` = up, red `●` = down, yellow `●` = checking - Uses `window.electronAPI.getSystemInfo()` + `getServiceStatus()` on load and every 5s - Memory: inline bar visualization - No external dependencies (pure HTML/CSS/JS) ### Service Health Endpoints (defaults, from known architecture) ```javascript const SERVICE_ENDPOINTS = [ { name: 'Auth', url: `${authServerUrl}/actuator/health` }, { name: 'Incident', url: `${allowedUrl}/actuator/health` }, { name: 'Config', url: `${apiBaseUrl.replace('/api/v1','')}/actuator/health` }, ]; ``` These use the existing config values. Timeout: 3s. Returns up/down per service. --- ## Key Technical Details ### WebContentsView bounds management ```javascript function updateBounds() { const STATUS_BAR_H = 32; const [w, h] = mainWindow.getContentSize(); incidentView.setBounds({ x: 0, y: 0, width: w, height: h - STATUS_BAR_H }); statusbarView.setBounds({ x: 0, y: h - STATUS_BAR_H, width: w, height: STATUS_BAR_H }); } mainWindow.on('resize', updateBounds); ``` ### Header injection moves to incidentView's session ```javascript incidentView.webContents.session.webRequest.onBeforeSendHeaders(...) ``` ### System info IPC handler ```javascript const os = require('os'); ipcMain.handle('get-system-info', () => { const total = os.totalmem(); const free = os.freemem(); const used = total - free; const [load1] = os.loadavg(); // Linux/Mac; 0 on Windows return { memory: { used, total, percent: Math.round((used / total) * 100) }, cpu: { load: Math.min(100, Math.round(load1 * 100 / os.cpus().length)) }, user: authManager.getUserInfo(), version: app.getVersion(), }; }); ``` ### Service status uses electron net module ```javascript const { net } = require('electron'); // HEAD request with 3s timeout per service ``` --- ## Cleanup - Remove `getUserProfile` call from `hiveops-incident/frontend/src/App.svelte` (the sidebar-user block) since user info is now shown in the browser's own status bar. --- ## Build & Verify 1. `cd /source/hiveops-src/hiveops-browser && npm start` — dev test 2. Confirm status bar appears at bottom of window 3. Confirm incident app fills remaining space and works normally 4. Confirm user name/role shows (must be logged in) 5. Confirm memory/CPU metrics update every 5s 6. Confirm service dots show correct status 7. `npm run build:linux` — build production package 8. Test with `dist/linux-unpacked/hiveops-browser --no-sandbox`