diff --git a/app/main.ts b/app/main.ts index 988d37d..7cdc284 100644 --- a/app/main.ts +++ b/app/main.ts @@ -90,27 +90,62 @@ const args = process.argv.slice(1), // #region Window -const onStartStopDaemon: () => void = () => { - console.log("onStartStopDaemon()"); +function updateTrayMenu(): void { + tray.setContextMenu(trayMenu); +} -}; +function setTrayItemEnabled(id: string, enabled: boolean): void { + const item = trayMenu.getMenuItemById(id); + + if (!item) { + throw new Error(`Item not found: ${id}`); + } + + item.enabled = enabled; + + updateTrayMenu(); +} function createTrayMenuTemplate(): MenuItemConstructorOptions[] { return [ { - id: "startStopDaemon", + id: "startDaemon", label: "Start", - toolTip: "Start monero daemon", - click: onStartStopDaemon + toolTip: "Start Daemon", + click: () => { + win?.webContents.send('on-tray-start-daemon'); + } + }, + { + id: "stopDaemon", + label: "Stop", + toolTip: "Stop Daemon", + click: () => { + win?.webContents.send('on-tray-stop-daemon'); + } + }, + { + id: "startSync", + label: "Start Sync", + toolTip: "Start Daemon Sync", + click: () => { + win?.webContents.send('on-tray-start-sync'); + } + }, + { + id: "stopSync", + label: "Stop Sync", + toolTip: "Stop Daemon Sync", + click: () => { + win?.webContents.send('on-tray-stop-sync'); + } }, { id: "quitDaemon", label: "Quit", - toolTip: "Quit monero daemon", + toolTip: "Quit Daemon", click: () => { - isQuitting = true; - app.quit(); - console.log("Quit monero daemon"); + win?.webContents.send('on-tray-quit-daemon'); } } ] @@ -948,6 +983,14 @@ try { // #endregion + ipcMain.handle('set-tray-item-enabled', (event: IpcMainInvokeEvent, id: string, enabled: boolean) => { + setTrayItemEnabled(id, enabled); + }); + + ipcMain.handle('set-tray-tool-tip', (event: IpcMainInvokeEvent, toolTip: string) => { + tray.setToolTip(toolTip); + }); + ipcMain.handle('is-app-image', (event: IpcMainInvokeEvent) => { const isAppImage: boolean = !!process.env.APPIMAGE; diff --git a/app/preload.js b/app/preload.js index 1ee7050..a470ca5 100644 --- a/app/preload.js +++ b/app/preload.js @@ -2,6 +2,27 @@ const { contextBridge, ipcRenderer } = require('electron'); contextBridge.exposeInMainWorld('electronAPI', { + onTrayStartDaemon: (callback) => { + ipcRenderer.on('on-tray-start-daemon', callback); + }, + onTrayStopDaemon: (callback) => { + ipcRenderer.on('on-tray-stop-daemon', callback); + }, + onTrayQuitDaemon: (callback) => { + ipcRenderer.on('on-tray-quit-daemon', callback); + }, + onTrayStartSync: (callback) => { + ipcRenderer.on('on-tray-start-sync', callback); + }, + onTrayStopSync: (callback) => { + ipcRenderer.on('on-tray-stop-sync', callback); + }, + setTrayItemEnabled: (id, enabled) => { + ipcRenderer.invoke('set-tray-item-enabled', id, enabled); + }, + setTrayToolTip: (toolTip) => { + ipcRenderer.invoke('set-tray-tool-tip', toolTip); + }, startMonerod: (args) => { ipcRenderer.invoke('start-monerod', args); }, @@ -50,7 +71,6 @@ contextBridge.exposeInMainWorld('electronAPI', { unregisterOnMoneroVersionError: () => { ipcRenderer.removeAllListeners('unregister-on-monero-version-error'); }, - downloadMonerod: (downloadUrl, destination) => { ipcRenderer.invoke('download-monerod', downloadUrl, destination); }, diff --git a/src/app/app.component.ts b/src/app/app.component.ts index e99e997..ac30c14 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -4,6 +4,7 @@ import { APP_CONFIG } from '../environments/environment'; import { DaemonService } from './core/services/daemon/daemon.service'; import { DaemonDataService } from './core/services/daemon/daemon-data.service'; import { LogsService } from './pages/logs/logs.service'; +import { DaemonTrayService } from './core/services/daemon/daemon-tray.service'; @Component({ selector: 'app-root', @@ -22,7 +23,8 @@ export class AppComponent { private electronService: ElectronService, private daemonService: DaemonService, private daemonData: DaemonDataService, - private LogService: LogsService + private LogService: LogsService, + private trayService: DaemonTrayService ) { console.log('APP_CONFIG', APP_CONFIG); diff --git a/src/app/core/services/daemon/daemon-tray.service.spec.ts b/src/app/core/services/daemon/daemon-tray.service.spec.ts new file mode 100644 index 0000000..bc91b5a --- /dev/null +++ b/src/app/core/services/daemon/daemon-tray.service.spec.ts @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; + +import { DaemonTrayService } from './daemon-tray.service'; + +describe('DaemonTrayService', () => { + let service: DaemonTrayService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(DaemonTrayService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); diff --git a/src/app/core/services/daemon/daemon-tray.service.ts b/src/app/core/services/daemon/daemon-tray.service.ts new file mode 100644 index 0000000..15ecc55 --- /dev/null +++ b/src/app/core/services/daemon/daemon-tray.service.ts @@ -0,0 +1,121 @@ +import { Injectable } from '@angular/core'; +import { DaemonService } from './daemon.service'; + +@Injectable({ + providedIn: 'root' +}) +export class DaemonTrayService { + + constructor(private daemonService: DaemonService) { + this.registerIpcEvents(); + this.daemonService.isRunning() + .then((running: boolean) => this.loadTrayItems(running)) + .catch((error: any) => { + console.error(error); + this.loadTrayItems(false); + }); + } + + private registerIpcEvents(): void { + window.electronAPI.onTrayStopDaemon((event: any) => { + console.debug(event); + this.disableAllItems(); + this.daemonService.isRunning().then((running: boolean) => { + if (!running) { + console.warn("Daemon already stopped"); + return; + } + + this.daemonService.stopDaemon().then(() => { + window.electronAPI.setTrayItemEnabled('stopDaemon', false); + window.electronAPI.setTrayItemEnabled('startDaemon', true); + window.electronAPI.setTrayItemEnabled('startSync', false); + window.electronAPI.setTrayItemEnabled('stopSync', false); + }).catch((error: any) => console.error(error)); + + }).catch((error: any) => console.error(error)); + }); + + window.electronAPI.onTrayStartDaemon((event: any) => { + console.debug(event); + this.disableAllItems(); + this.daemonService.isRunning().then((running: boolean) => { + if (running) { + console.warn("Daemon already started"); + return; + } + + this.daemonService.startDaemon().then(() => { + window.electronAPI.setTrayItemEnabled('stopDaemon', true); + window.electronAPI.setTrayItemEnabled('startDaemon', false); + window.electronAPI.setTrayItemEnabled('startSync', this.daemonService.settings.noSync); + window.electronAPI.setTrayItemEnabled('stopSync', !this.daemonService.settings.noSync); + }).catch((error: any) => console.error(error)); + + }).catch((error: any) => console.error(error)); + }); + + window.electronAPI.onTrayQuitDaemon((event: any) => { + console.debug(event); + this.disableAllItems(); + + this.daemonService.quit().then(() => this.disableAllItems()).catch((error: any) => console.error(error)); + }); + + window.electronAPI.onTrayStartSync((event: any) => { + console.debug(event); + if (!this.daemonService.settings.noSync) { + console.warn("Sync already enabled"); + return; + } + + this.disableAllItems(); + + this.daemonService.enableSync().then(() => { + window.electronAPI.setTrayItemEnabled('startSync', false); + window.electronAPI.setTrayItemEnabled('stopSync', true); + }).catch((error: any) => console.error(error)); + }); + + window.electronAPI.onTrayStopSync((event: any) => { + console.debug(event); + if (this.daemonService.settings.noSync) { + console.warn("Sync already disabled"); + return; + } + + this.disableAllItems(); + + this.daemonService.disableSync().then(() => { + window.electronAPI.setTrayItemEnabled('startSync', true); + window.electronAPI.setTrayItemEnabled('stopSync', false); + }).catch((error: any) => console.error(error)); + }); + + this.daemonService.onDaemonStatusChanged.subscribe((running: boolean) => { + this.loadTrayItems(running); + }); + } + + public disableAllItems(): void { + window.electronAPI.setTrayItemEnabled('stopDaemon', false); + window.electronAPI.setTrayItemEnabled('startDaemon', false); + window.electronAPI.setTrayItemEnabled('startSync', false); + window.electronAPI.setTrayItemEnabled('stopSync', false); + } + + public loadTrayItems(running: boolean): void { + if (!running) { + window.electronAPI.setTrayItemEnabled('stopDaemon', false); + window.electronAPI.setTrayItemEnabled('startDaemon', true); + window.electronAPI.setTrayItemEnabled('startSync', false); + window.electronAPI.setTrayItemEnabled('stopSync', false); + } + else { + window.electronAPI.setTrayItemEnabled('stopDaemon', true); + window.electronAPI.setTrayItemEnabled('startDaemon', false); + window.electronAPI.setTrayItemEnabled('startSync', this.daemonService.settings.noSync); + window.electronAPI.setTrayItemEnabled('stopSync', !this.daemonService.settings.noSync); + } + } +} diff --git a/src/app/core/services/daemon/daemon.service.ts b/src/app/core/services/daemon/daemon.service.ts index 523e486..2b45871 100644 --- a/src/app/core/services/daemon/daemon.service.ts +++ b/src/app/core/services/daemon/daemon.service.ts @@ -143,6 +143,7 @@ export class DaemonService { console.debug(code); this.onClose(); }); + } public async disableSync(): Promise { diff --git a/src/polyfills.ts b/src/polyfills.ts index 58510f2..18f1e81 100644 --- a/src/polyfills.ts +++ b/src/polyfills.ts @@ -144,6 +144,14 @@ declare global { isAutoLaunched: () => void; onIsAutoLaunched: (callback: (event: any, isAutoLaunched: boolean) => void) => void; unregisterOnIsAutoLaunched: () => void; + + onTrayStartDaemon: (callback: (event: any) => void) => void; + onTrayStopDaemon: (callback: (event: any) => void) => void; + onTrayStartSync: (callback: (event: any) => void) => void; + onTrayStopSync: (callback: (event: any) => void) => void; + onTrayQuitDaemon: (callback: (event: any) => void) => void; + setTrayItemEnabled: (id: string, enabled: boolean) => void; + setTrayToolTip: (toolTip: string) => void; }; } } \ No newline at end of file