feat(desktop-client): surface account health issues in tray and app icons
Periodically polls runtime snapshot for accounts in expired/revoked/challenge_required states and reflects the count via tray badge, macOS dock badge, and Windows overlay icon so users see authentication problems without opening the app. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -11,6 +11,12 @@ import type {
|
||||
import type { DesktopAccountInfo, DesktopRuntimeSessionSyncRequest } from "@geo/shared-types";
|
||||
|
||||
import { initAccountHealth } from "./account-health";
|
||||
import {
|
||||
applyDesktopHealthIndicatorFromSnapshot,
|
||||
createDesktopHealthIcon,
|
||||
startDesktopHealthIndicator,
|
||||
syncDesktopHealthIndicator,
|
||||
} from "./app-issue-indicator";
|
||||
import { bindPublishAccount, openPublishAccountConsole } from "./account-binder";
|
||||
import { installObservedGlobalFetch, registerObservedRequestRendererTarget } from "./network-observer";
|
||||
import { initProcessMetricsSampler } from "./process-metrics";
|
||||
@@ -142,6 +148,12 @@ function currentMainWindow(): ElectronBrowserWindow | null {
|
||||
return mainWindow;
|
||||
}
|
||||
|
||||
function captureRuntimeSnapshot() {
|
||||
const snapshot = createRuntimeSnapshot();
|
||||
applyDesktopHealthIndicatorFromSnapshot(snapshot, currentMainWindow());
|
||||
return snapshot;
|
||||
}
|
||||
|
||||
async function ensureMainWindow(): Promise<ElectronBrowserWindow> {
|
||||
const existing = currentMainWindow();
|
||||
if (existing) {
|
||||
@@ -201,6 +213,7 @@ async function createMainWindow(): Promise<ElectronBrowserWindow> {
|
||||
height: initial.height,
|
||||
show: false,
|
||||
title: "GEO Rankly Desktop",
|
||||
icon: createDesktopHealthIcon("normal"),
|
||||
titleBarStyle: "hiddenInset",
|
||||
trafficLightPosition: { x: 12, y: 14 },
|
||||
backgroundColor: nativeTheme.shouldUseDarkColors ? "#15191a" : "#eaf2ff",
|
||||
@@ -287,7 +300,7 @@ function registerBridgeHandlers(): void {
|
||||
os: process.platform,
|
||||
cpu_arch: process.arch,
|
||||
}));
|
||||
ipcMain.handle("desktop:runtime-snapshot", () => createRuntimeSnapshot());
|
||||
ipcMain.handle("desktop:runtime-snapshot", () => captureRuntimeSnapshot());
|
||||
safeHandle("desktop:bind-publish-account", async (_event, platformId: string) => {
|
||||
const account = (await bindPublishAccount(platformId)) as DesktopAccountInfo;
|
||||
noteRuntimeAccountBound(account);
|
||||
@@ -369,6 +382,7 @@ app.whenReady().then(async () => {
|
||||
startHotViewReaper();
|
||||
startHiddenPlaywrightReaper();
|
||||
onRuntimeInvalidated((event) => {
|
||||
syncDesktopHealthIndicator(currentMainWindow());
|
||||
if (!mainRendererContents || mainRendererContents.isDestroyed()) {
|
||||
return;
|
||||
}
|
||||
@@ -378,6 +392,7 @@ app.whenReady().then(async () => {
|
||||
initTray(() => {
|
||||
revealMainWindowSafely("tray");
|
||||
});
|
||||
startDesktopHealthIndicator(() => currentMainWindow());
|
||||
}).catch((error) => {
|
||||
console.error("[desktop-main] app.whenReady failed", error);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user