diff --git a/src/app/core/services/daemon/daemon.service.ts b/src/app/core/services/daemon/daemon.service.ts index d588953..27855b3 100644 --- a/src/app/core/services/daemon/daemon.service.ts +++ b/src/app/core/services/daemon/daemon.service.ts @@ -990,10 +990,18 @@ export class DaemonService { this.stopping = false; if (!this.restarting) { - window.electronAPI.showNotification({ - title: 'Daemon stopped', - body: 'Successfully stopped monero daemon' - }); + if (!this.quitting) { + window.electronAPI.showNotification({ + title: 'Daemon stopped', + body: 'Successfully stopped monero daemon' + }); + } + else { + window.electronAPI.showNotification({ + title: 'Daemon quitted', + body: 'Successfully quit monero daemon' + }); + } } return; diff --git a/src/app/core/services/electron/electron.service.ts b/src/app/core/services/electron/electron.service.ts index 78ad8fa..e88dca3 100644 --- a/src/app/core/services/electron/electron.service.ts +++ b/src/app/core/services/electron/electron.service.ts @@ -16,6 +16,7 @@ export class ElectronService { private _isAppImage?: boolean; private _isAutoLaunched?: boolean; + private _online: boolean = false; constructor() { // Conditional imports @@ -50,6 +51,14 @@ export class ElectronService { // ipcRenderer.invoke can serve many common use cases. // https://www.electronjs.org/docs/latest/api/ipc-renderer#ipcrendererinvokechannel-args } + + this._online = navigator.onLine; + window.addEventListener('online', () => this._online = true); + window.addEventListener('offline', () => this._online = false); + } + + public get online(): boolean { + return this._online; } get isElectron(): boolean { diff --git a/src/app/pages/base-page/base-page.component.ts b/src/app/pages/base-page/base-page.component.ts index 09d061b..32bb679 100644 --- a/src/app/pages/base-page/base-page.component.ts +++ b/src/app/pages/base-page/base-page.component.ts @@ -11,7 +11,7 @@ export abstract class BasePageComponent implements AfterContentInit, OnDestroy { private _links: NavbarLink[] = []; public get links(): NavbarLink[] { - return this._links; + return this.navbarService.links; } protected subscriptions: Subscription[] = []; diff --git a/src/app/pages/detail/detail.component.ts b/src/app/pages/detail/detail.component.ts index 3d066bb..14cc5a7 100644 --- a/src/app/pages/detail/detail.component.ts +++ b/src/app/pages/detail/detail.component.ts @@ -179,12 +179,18 @@ export class DetailComponent extends BasePageComponent implements AfterViewInit }); }); + const daemonStatusSub = this.daemonService.onDaemonStatusChanged.subscribe((running: boolean) => { + if (!running) { + this.destroyTables(); + } + }); + const syncInfoRefreshEndSub: Subscription = this.daemonData.syncInfoRefreshEnd.subscribe(() => { this.cards = this.createCards(); this.loadTables(); }); - this.subscriptions.push(syncStartSub, syncInfoRefreshEndSub); + this.subscriptions.push(syncStartSub, syncInfoRefreshEndSub, daemonStatusSub); } public ngAfterViewInit(): void { diff --git a/src/app/shared/components/navbar/navbar.service.ts b/src/app/shared/components/navbar/navbar.service.ts index e640e00..f3ea568 100644 --- a/src/app/shared/components/navbar/navbar.service.ts +++ b/src/app/shared/components/navbar/navbar.service.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@angular/core'; +import { Injectable, NgZone } from '@angular/core'; import { NavbarLink } from './navbar.model'; import { DaemonService } from '../../../core/services'; @@ -13,31 +13,49 @@ export class NavbarService { return this._navbarLinks; } - constructor(private daemonService: DaemonService) { + constructor(private daemonService: DaemonService, private zone: NgZone) { this.daemonService.onDaemonStatusChanged.subscribe((running: boolean) => { this.daemonRunning = running; - if (!running) this.disableLinks(); - if (running) this.enableLinks(); + this.refreshLinks(); }); this.daemonService.isRunning().then((running: boolean) => { this.daemonRunning = running; - if (!running) this.disableLinks(); - if (running) this.enableLinks(); }).catch((error: any) => { console.error(error); - this.disableLinks(); + }).finally(() => { + this.refreshLinks(); + }); + } + + private refreshLinks(): void { + if (this._navbarLinks.length == 0) { + return; + } + + const links = this._navbarLinks; + this.zone.run(() => { + setTimeout(() => { + this.setLinks([]); + }, 0); + setTimeout(() => { + this.setLinks(links); + }, 0); }) - } + } public addLink(... navbarLinks: NavbarLink[]): void { navbarLinks.forEach((navLink: NavbarLink) => this._navbarLinks.push(navLink)); } + private get enabled(): boolean { + return this.daemonRunning && !this.daemonService.stopping && !this.daemonService.starting && !this.daemonService.restarting; + } + public setLinks(navbarLinks: NavbarLink[]): void { this._navbarLinks = navbarLinks; - if (this.daemonRunning) this.enableLinks(); + if (this.enabled) this.enableLinks(); else this.disableLinks(); }