directlx-claude-config/plans/iridescent-coalescing-charm.md

5.1 KiB

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: BrowserWindowloadURL('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

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)

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

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

incidentView.webContents.session.webRequest.onBeforeSendHeaders(...)

System info IPC handler

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

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