feat: add system tray with quick actions and minimize-to-tray

System tray:
- Always-visible tray icon with context menu
- Quick Scratchpad action from tray (triggers session creation
  via IPC bridge to renderer)
- Running session count in tray tooltip and menu
- Click tray icon to show/focus window
- Quit option in tray menu

Minimize to tray:
- New 'Minimize to tray on close' toggle in Settings > Appearance
- When enabled, closing the window hides to tray instead of
  quitting (configurable per-user, default off)
- macOS: hides dock icon when minimized to tray
- Proper force-quit handling (Cmd+Q on macOS, tray Quit)

Full IPC contract chain:
- minimizeToTray setting in WorkspaceSettings
- setMinimizeToTray channel + ElectronApi method
- Preload bridge, service handler, IPC registration
- Preserved through workspace normalization

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
David Kaya
2026-03-29 18:10:38 +02:00
co-authored by Copilot
parent 8813f9e90a
commit a670817870
10 changed files with 246 additions and 4 deletions
+35 -1
View File
@@ -42,6 +42,8 @@ interface SettingsPanelProps {
onSetTheme: (theme: AppearanceTheme) => void;
notificationsEnabled: boolean;
onSetNotificationsEnabled: (enabled: boolean) => void;
minimizeToTray: boolean;
onSetMinimizeToTray: (enabled: boolean) => void;
onOpenAppDataFolder: () => void;
onResetLocalWorkspace: () => Promise<void>;
onResolveUserDiscoveredTooling?: (serverIds: string[], resolution: 'accept' | 'dismiss') => void;
@@ -122,6 +124,8 @@ export function SettingsPanel({
onSetTheme,
notificationsEnabled,
onSetNotificationsEnabled,
minimizeToTray,
onSetMinimizeToTray,
onOpenAppDataFolder,
onResetLocalWorkspace,
onResolveUserDiscoveredTooling,
@@ -265,6 +269,8 @@ export function SettingsPanel({
onSetTheme={onSetTheme}
notificationsEnabled={notificationsEnabled}
onSetNotificationsEnabled={onSetNotificationsEnabled}
minimizeToTray={minimizeToTray}
onSetMinimizeToTray={onSetMinimizeToTray}
/>
)}
{activeSection === 'connection' && (
@@ -327,12 +333,16 @@ function AppearanceSection({
onSetTheme,
notificationsEnabled,
onSetNotificationsEnabled,
minimizeToTray,
onSetMinimizeToTray,
}: {
theme: AppearanceTheme;
onSetTheme: (theme: AppearanceTheme) => void;
notificationsEnabled: boolean;
onSetNotificationsEnabled: (enabled: boolean) => void;
}) {
minimizeToTray: boolean;
onSetMinimizeToTray: (enabled: boolean) => void;
}){
return (
<div>
<div className="mb-1">
@@ -397,6 +407,30 @@ function AppearanceSection({
</div>
<ToggleSwitch enabled={notificationsEnabled} />
</button>
{/* System Tray */}
<div className="mt-8 mb-1">
<h3 className="font-display text-[13px] font-semibold text-[var(--color-text-primary)]">System Tray</h3>
<p className="mt-0.5 text-[12px] text-[var(--color-text-muted)]">
Control how Aryx behaves when you close the window
</p>
</div>
<button
className="mt-4 flex w-full items-center justify-between rounded-lg border border-[var(--color-border)] px-4 py-3 text-left transition hover:bg-[var(--color-surface-3)]/40"
onClick={() => onSetMinimizeToTray(!minimizeToTray)}
type="button"
>
<div>
<span className="text-[13px] font-medium text-[var(--color-text-primary)]">
Minimize to tray on close
</span>
<p className="text-[12px] text-[var(--color-text-muted)]">
Keep Aryx running in the system tray when you close the window instead of quitting
</p>
</div>
<ToggleSwitch enabled={minimizeToTray} />
</button>
</div>
);
}