Spaces:
Sleeping
Sleeping
| /** | |
| * SystemTray — installs a Tauri tray icon with Show/Hide/Quit menu and a | |
| * left-click handler that brings the main window forward. | |
| * | |
| * Listens for "single-instance" emitter events so a second launch refocuses the window. | |
| */ | |
| import { useEffect } from 'react'; | |
| import { useTranslation } from 'react-i18next'; | |
| import { TrayIcon } from '@tauri-apps/api/tray'; | |
| import { Menu, MenuItem } from '@tauri-apps/api/menu'; | |
| import { defaultWindowIcon } from '@tauri-apps/api/app'; | |
| import { getCurrentWindow } from '@tauri-apps/api/window'; | |
| import { listen } from '@tauri-apps/api/event'; | |
| const isTauri = () => typeof window !== 'undefined' && '__TAURI_INTERNALS__' in window; | |
| const TRAY_ID = 'hasarui-main-tray'; | |
| export function SystemTray() { | |
| const { t } = useTranslation(); | |
| useEffect(() => { | |
| if (!isTauri()) return; | |
| let tray: TrayIcon | null = null; | |
| let unlisten: (() => void) | null = null; | |
| (async () => { | |
| try { | |
| const win = getCurrentWindow(); | |
| // Refocus on second-instance launch. | |
| unlisten = await listen('single-instance', async () => { | |
| await win.show(); | |
| await win.unminimize(); | |
| await win.setFocus(); | |
| }); | |
| const menu = await Menu.new({ | |
| items: [ | |
| await MenuItem.new({ | |
| id: 'tray-show', | |
| text: t('tray.show'), | |
| action: async () => { | |
| await win.show(); | |
| await win.unminimize(); | |
| await win.setFocus(); | |
| }, | |
| }), | |
| await MenuItem.new({ | |
| id: 'tray-hide', | |
| text: t('tray.hide'), | |
| action: async () => { | |
| await win.hide(); | |
| }, | |
| }), | |
| await MenuItem.new({ | |
| id: 'tray-quit', | |
| text: t('tray.quit'), | |
| action: async () => { | |
| // Best-effort exit: try the app handle (most reliable across Tauri 2 versions), | |
| // then fall back to closing the main window. | |
| try { | |
| const { getAllWindows } = await import('@tauri-apps/api/window'); | |
| for (const w of await getAllWindows()) await w.close(); | |
| } catch { | |
| /* ignored */ | |
| } | |
| }, | |
| }), | |
| ], | |
| }); | |
| tray = await TrayIcon.new({ | |
| id: TRAY_ID, | |
| tooltip: 'Hasarİ', | |
| icon: (await defaultWindowIcon()) ?? undefined, | |
| menu, | |
| menuOnLeftClick: false, | |
| action: async (event) => { | |
| if (event.type === 'Click' && event.button === 'Left' && event.buttonState === 'Up') { | |
| await win.show(); | |
| await win.unminimize(); | |
| await win.setFocus(); | |
| } | |
| }, | |
| }); | |
| } catch (e) { | |
| // tray may already exist from a previous HMR mount — ignore | |
| console.warn('SystemTray install warning:', e); | |
| } | |
| })(); | |
| return () => { | |
| unlisten?.(); | |
| tray?.close().catch(() => undefined); | |
| }; | |
| }, [t]); | |
| return null; | |
| } | |
| export default SystemTray; | |