Spaces:
Runtime error
Runtime error
File size: 3,051 Bytes
077865a | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 | import path from 'node:path';
import { fileURLToPath } from 'node:url';
import { BrowserWindow, type Tray } from 'electron';
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const WIDTH = 316;
const HEIGHT = 348;
let popover: BrowserWindow | null = null;
// A Control-Center-style glass panel anchored under the tray icon.
// Real macOS material: frameless window with SYSTEM rounded corners +
// NSVisualEffectView vibrancy + native shadow. No `transparent: true` —
// that path composites the window itself and defeats the vibrancy blur;
// instead the page background stays transparent and the material shows
// through. Created once, then shown/hidden; hides on blur like a menu.
function createPopover(): BrowserWindow {
const win = new BrowserWindow({
width: WIDTH,
height: HEIGHT,
show: false,
frame: false,
roundedCorners: true, // native macOS corner mask + matching shadow
resizable: false,
movable: false,
minimizable: false,
maximizable: false,
fullscreenable: false,
skipTaskbar: true,
alwaysOnTop: true,
...(process.platform === 'darwin'
? {
// 'popover' follows the app appearance, which main.ts pins via
// nativeTheme.themeSource to the DASHBOARD's theme choice — so the
// glass flips dark/light together with the dashboard. The dark
// variant is deepened toward black by the panel's CSS tint.
vibrancy: 'popover' as const,
visualEffectState: 'active' as const,
backgroundColor: '#00000000',
}
: {
// Windows 11 acrylic; older Windows falls back to the solid CSS bg.
backgroundMaterial: 'acrylic' as const,
}),
webPreferences: {
preload: path.join(__dirname, 'preload-popover.cjs'),
contextIsolation: true,
sandbox: false,
nodeIntegration: false,
},
});
// Show over fullscreen apps, like every menu bar utility.
win.setVisibleOnAllWorkspaces(true, { visibleOnFullScreen: true });
win.loadFile(path.join(__dirname, '../renderer/popover.html')).then(() => {
if (process.platform !== 'darwin') {
win.webContents.executeJavaScript("document.body.classList.add('no-vibrancy')");
}
});
win.on('blur', () => win.hide());
win.on('closed', () => {
popover = null;
});
return win;
}
export function getPopoverWindow(): BrowserWindow | null {
return popover;
}
export function togglePopover(tray: Tray): void {
if (!popover || popover.isDestroyed()) popover = createPopover();
if (popover.isVisible()) {
popover.hide();
return;
}
const b = tray.getBounds();
// Centered under the icon; tray bounds are in screen coordinates.
const x = Math.round(b.x + b.width / 2 - WIDTH / 2);
const y = process.platform === 'darwin'
? Math.round(b.y + b.height + 6)
: Math.round(b.y - HEIGHT - 6); // Windows tray sits at the bottom
popover.setPosition(x, y, false);
popover.webContents.send('freeapi:refresh');
popover.show();
popover.focus();
}
|