Files
SubMiner/src/main/runtime/tray-lifecycle.ts
T

85 lines
2.5 KiB
TypeScript

type TrayIconLike = {
isEmpty: () => boolean;
resize: (options: {
width: number;
height: number;
quality?: 'best' | 'better' | 'good';
}) => TrayIconLike;
setTemplateImage: (enabled: boolean) => void;
};
type TrayLike = {
setContextMenu: (menu: any) => void;
setToolTip: (tooltip: string) => void;
on: (event: 'click', handler: () => void) => void;
destroy: () => void;
};
export function createEnsureTrayHandler(deps: {
getTray: () => TrayLike | null;
setTray: (tray: TrayLike | null) => void;
buildTrayMenu: () => any;
resolveTrayIconPath: () => string | null;
createImageFromPath: (iconPath: string) => TrayIconLike;
createEmptyImage: () => TrayIconLike;
createTray: (icon: TrayIconLike) => TrayLike;
trayTooltip: string;
platform: string;
logWarn: (message: string) => void;
ensureOverlayVisibleFromTrayClick: () => void;
}) {
return (): void => {
const existingTray = deps.getTray();
if (existingTray) {
existingTray.setContextMenu(deps.buildTrayMenu());
return;
}
const iconPath = deps.resolveTrayIconPath();
let trayIcon = iconPath ? deps.createImageFromPath(iconPath) : deps.createEmptyImage();
if (trayIcon.isEmpty()) {
deps.logWarn('Tray icon asset not found; using empty icon placeholder.');
}
if (deps.platform === 'darwin' && !trayIcon.isEmpty()) {
trayIcon = trayIcon.resize({ width: 18, height: 18, quality: 'best' });
trayIcon.setTemplateImage(true);
}
if (deps.platform === 'linux' && !trayIcon.isEmpty()) {
trayIcon = trayIcon.resize({ width: 20, height: 20 });
}
let tray: TrayLike;
try {
tray = deps.createTray(trayIcon);
} catch (error) {
const reason = error instanceof Error ? error.message : String(error);
if (deps.platform === 'linux') {
deps.logWarn(
`Unable to create Linux tray icon. Ensure your desktop has a StatusNotifier/AppIndicator tray host. ${reason}`,
);
} else {
deps.logWarn(`Unable to create tray icon. ${reason}`);
}
return;
}
tray.setToolTip(deps.trayTooltip);
tray.setContextMenu(deps.buildTrayMenu());
tray.on('click', () => {
deps.ensureOverlayVisibleFromTrayClick();
});
deps.setTray(tray);
};
}
export function createDestroyTrayHandler(deps: {
getTray: () => TrayLike | null;
setTray: (tray: TrayLike | null) => void;
}) {
return (): void => {
const tray = deps.getTray();
if (!tray) return;
tray.destroy();
deps.setTray(null);
};
}