From 131199113daad0f377a4c40a9ada8fe2fa33b7cf Mon Sep 17 00:00:00 2001 From: everoddandeven Date: Tue, 1 Oct 2024 20:45:10 +0200 Subject: [PATCH] Daemon data service implementation --- app/main.ts | 15 +- app/preload.js | 9 + src/app/app.component.ts | 10 +- .../daemon/daemon-data.service.spec.ts | 16 + .../services/daemon/daemon-data.service.ts | 203 ++++++++++ .../core/services/daemon/daemon.service.ts | 39 +- src/app/core/services/index.ts | 1 + src/app/pages/detail/detail.component.html | 15 - src/app/pages/detail/detail.component.ts | 380 ++++++------------ src/app/pages/version/version.component.ts | 3 +- .../components/navbar/navbar.service.ts | 13 +- 11 files changed, 391 insertions(+), 313 deletions(-) create mode 100644 src/app/core/services/daemon/daemon-data.service.spec.ts create mode 100644 src/app/core/services/daemon/daemon-data.service.ts diff --git a/app/main.ts b/app/main.ts index 1b2d4b9..24499c9 100644 --- a/app/main.ts +++ b/app/main.ts @@ -113,11 +113,11 @@ function getMonerodVersion(monerodFilePath: string): void { const monerodProcess = spawn(getMonerodPath(), [ '--version' ]); monerodProcess.stdout.on('data', (data) => { - win?.webContents.send('on-monerod-version', `${data}`); + win?.webContents.send('monero-version', `${data}`); }) monerodProcess.stderr.on('data', (data) => { - win?.webContents.send('on-monerod-version-error', `${data}`); + win?.webContents.send('monero-version-error', `${data}`); }) } @@ -290,14 +290,6 @@ const verifyFileHash = (filePath: string): Promise => { }); }; -// Funzione per estrarre tar.bz2 -const extractTarBz2Old = (filePath: string, destination: string): Promise => { - return tar.x({ - file: filePath, - cwd: destination, - }); -}; - const extractTarBz2 = (filePath: string, destination: string): Promise => { return new Promise((resolve, reject) => { // Crea il file decomprimendo il .bz2 in uno .tar temporaneo @@ -354,11 +346,10 @@ try { startMoneroDaemon(configFilePath); }) - ipcMain.on('get-monerod-version', (event, configFilePath: string) => { + ipcMain.handle('get-monero-version', (event, configFilePath: string) => { getMonerodVersion(configFilePath); }); - // Gestione IPC ipcMain.handle('download-monero', async (event, downloadUrl: string, destination: string) => { try { diff --git a/app/preload.js b/app/preload.js index 1802e4c..49142ba 100644 --- a/app/preload.js +++ b/app/preload.js @@ -10,5 +10,14 @@ contextBridge.exposeInMainWorld('electronAPI', { }, onMoneroClose: (callback) => { ipcRenderer.on('monero-close', callback); + }, + getMoneroVersion: () => { + ipcRenderer.invoke('get-monero-version'); + }, + onMoneroVersion: (callback) => { + ipcRenderer.on('monero-version', callback); + }, + onMoneroVersionError: (callback) => { + ipcRenderer.on('monero-version-error', callback); } }); diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 173d4f9..e0b143c 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -3,6 +3,8 @@ import { ElectronService } from './core/services'; import { TranslateService } from '@ngx-translate/core'; 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'; @Component({ selector: 'app-root', @@ -13,10 +15,16 @@ export class AppComponent { public loading: boolean; public daemonRunning: boolean; + public get initializing(): boolean { + return this.daemonData.initializing; + } + constructor( private electronService: ElectronService, private translate: TranslateService, - private daemonService: DaemonService + private daemonService: DaemonService, + private daemonData: DaemonDataService, + private LogService: LogsService ) { this.translate.setDefaultLang('en'); console.log('APP_CONFIG', APP_CONFIG); diff --git a/src/app/core/services/daemon/daemon-data.service.spec.ts b/src/app/core/services/daemon/daemon-data.service.spec.ts new file mode 100644 index 0000000..d823cae --- /dev/null +++ b/src/app/core/services/daemon/daemon-data.service.spec.ts @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; + +import { DaemonDataService } from './daemon-data.service'; + +describe('DaemonDataService', () => { + let service: DaemonDataService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(DaemonDataService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); diff --git a/src/app/core/services/daemon/daemon-data.service.ts b/src/app/core/services/daemon/daemon-data.service.ts new file mode 100644 index 0000000..da6d1a8 --- /dev/null +++ b/src/app/core/services/daemon/daemon-data.service.ts @@ -0,0 +1,203 @@ +import { EventEmitter, Injectable } from '@angular/core'; +import { DaemonService } from './daemon.service'; +import { BlockCount, BlockHeader, DaemonInfo, SyncInfo } from '../../../../common'; + +@Injectable({ + providedIn: 'root' +}) +export class DaemonDataService { + + private refreshTimeoutMs: number = 5000; + private refreshInterval?: NodeJS.Timeout; + private _refreshing: boolean = false; + private _firstRefresh: boolean = true; + private _lastRefresh: number = Date.now(); + + private _daemonRunning: boolean = false; + private _daemonRestarting: boolean = false; + + private _daemonInfo?: DaemonInfo; + private _gettingDaemonInfo: boolean = false; + + private _syncInfo?: SyncInfo; + private _gettingSyncInfo: boolean = false; + + private _blockCount?: BlockCount; + private _gettingBlockCount: boolean = false; + + private _isBlockchainPruned: boolean = false; + private _gettingIsBlockchainPruned: boolean = false; + + private _lastBlockHeader?: BlockHeader; + private _gettingLastBlockHeader: boolean = false; + + public readonly syncStart: EventEmitter = new EventEmitter(); + public readonly syncEnd: EventEmitter = new EventEmitter(); + public readonly syncError: EventEmitter = new EventEmitter(); + + public readonly syncInfoRefreshStart: EventEmitter = new EventEmitter(); + public readonly syncInfoRefreshEnd: EventEmitter = new EventEmitter(); + + constructor(private daemonService: DaemonService) { + this.startLoop(); + + this.daemonService.onDaemonStatusChanged.subscribe((running: boolean) => { + if (running) { + this.startLoop(); + } + else { + this.stopLoop(); + } + }) + } + + public get initializing(): boolean { + return this._firstRefresh; + } + + public get running(): boolean { + return this._daemonRunning; + } + + public get starting(): boolean { + return this.daemonService.starting; + } + + public get stopping(): boolean { + return this.daemonService.stopping; + } + + public get restarting(): boolean { + return this._daemonRestarting; + } + + public get refreshing(): boolean { + return this._refreshing; + } + + public get info(): DaemonInfo | undefined { + return this._daemonInfo; + } + + public get gettingInfo(): boolean { + return this._gettingDaemonInfo; + } + + public get syncInfo(): SyncInfo | undefined { + return this._syncInfo; + } + + public get gettingSyncInfo(): boolean { + return this._gettingSyncInfo; + } + + public get blockCount(): BlockCount | undefined { + return this._blockCount; + } + + public get gettingBlockCount(): boolean { + return this._gettingBlockCount; + } + + public get isBlockchainPruned(): boolean { + return this._isBlockchainPruned; + } + + public get gettingIsBlockchainPruned(): boolean { + return this._gettingIsBlockchainPruned; + } + + public get lastBlockHeader(): BlockHeader | undefined { + return this._lastBlockHeader; + } + + public get gettingLastBlockHeader(): boolean { + return this._gettingLastBlockHeader; + } + + public setRefreshTimeout(ms: number = 5000): void { + this.refreshTimeoutMs = ms; + } + + private startLoop(): void { + if (this.refreshInterval != undefined) { + throw new Error("Loop already started"); + } + this._firstRefresh = true; + this.refreshInterval = setInterval(() => { + this.refresh(); + },this.refreshTimeoutMs); + } + + private stopLoop(): void { + if (this.refreshInterval == undefined) { + throw new Error("Loop already stopped"); + } + + clearInterval(this.refreshInterval); + + this.refreshInterval = undefined; + this._refreshing = false; + } + + private get tooEarlyForRefresh(): boolean { + return Date.now() - this._lastRefresh <= this.refreshTimeoutMs; + } + + private async refresh(): Promise { + if (this.refreshing || this.tooEarlyForRefresh) { + return; + } + + this._refreshing = true; + this.syncStart.emit(); + + try { + const firstRefresh = this._firstRefresh; + this._daemonRunning = await this.daemonService.isRunning(); + this._firstRefresh = false; + + this._gettingDaemonInfo = true; + this._daemonInfo = await this.daemonService.getInfo(); + this._gettingDaemonInfo = false; + + this._gettingSyncInfo = true; + this.syncInfoRefreshStart.emit(); + this._syncInfo = await this.daemonService.syncInfo(); + this._gettingSyncInfo = false; + this.syncInfoRefreshEnd.emit(); + + this._gettingBlockCount = true; + this._blockCount = await this.daemonService.getBlockCount(); + this._gettingBlockCount = false; + + this._gettingLastBlockHeader = true; + this._lastBlockHeader = await this.daemonService.getLastBlockHeader(true); + this._gettingLastBlockHeader = false; + + this._gettingIsBlockchainPruned = true; + if (firstRefresh) this._isBlockchainPruned = (await this.daemonService.pruneBlockchain(true)).pruned; + this._gettingIsBlockchainPruned = false; + + this._lastRefresh = Date.now(); + } catch(error) { + console.error(error); + this._gettingDaemonInfo = false; + this._gettingSyncInfo = false; + this._gettingBlockCount = false; + this._gettingLastBlockHeader = false; + this._gettingIsBlockchainPruned = false; + + this.syncError.emit(error); + + if (!await this.daemonService.isRunning()) { + this.stopLoop(); + } + } + + this.syncEnd.emit(); + this._firstRefresh = false; + this._refreshing = false; + } + +} diff --git a/src/app/core/services/daemon/daemon.service.ts b/src/app/core/services/daemon/daemon.service.ts index 8903bab..fd20461 100644 --- a/src/app/core/services/daemon/daemon.service.ts +++ b/src/app/core/services/daemon/daemon.service.ts @@ -256,13 +256,6 @@ export class DaemonService { return; } - /* - if (!this.electronService.isElectron) { - console.error("Could not start monero daemon: not electron app"); - return; - } - */ - this.starting = true; console.log("Starting daemon"); @@ -270,7 +263,7 @@ export class DaemonService { if (this.electronService.ipcRenderer) this.electronService.ipcRenderer.send('start-monerod', settings.toCommandOptions()); else { - const wdw = (window as any).electronAPI.startMonerod(settings.toCommandOptions()); + (window as any).electronAPI.startMonerod(settings.toCommandOptions()); } await this.delay(3000); @@ -546,17 +539,29 @@ export class DaemonService { } else if (dontUseRpc) { const monerodPath: string = ''; // TO DO get local monerod path + const wdw = (window as any); return new Promise((resolve, reject) => { - this.electronService.ipcRenderer.on('on-monerod-version', (event, version: string) => { - resolve(DaemonVersion.parse(version)); - }); - - this.electronService.ipcRenderer.on('on-monerod-version-error', (event, version: string) => { - reject(version); - }); - - this.electronService.ipcRenderer.send('get-monerod-version', monerodPath); + if (this.electronService.isElectron) { + this.electronService.ipcRenderer.on('on-monerod-version', (event, version: string) => { + resolve(DaemonVersion.parse(version)); + }); + + this.electronService.ipcRenderer.on('on-monerod-version-error', (event, version: string) => { + reject(version); + }); + + this.electronService.ipcRenderer.send('get-monerod-version', monerodPath); + } + else if (wdw.electronAPI && wdw.electronAPI.getMoneroVersion) { + wdw.electronAPI.onMoneroVersion((event: any, version: string) => { + resolve(DaemonVersion.parse(version)); + }) + wdw.electronAPI.onMoneroVersionError((event: any, error: string) => { + reject(error); + }); + wdw.electronAPI.getMoneroVersion(); + } }); } diff --git a/src/app/core/services/index.ts b/src/app/core/services/index.ts index 9cc4b54..dbd97dc 100644 --- a/src/app/core/services/index.ts +++ b/src/app/core/services/index.ts @@ -1,3 +1,4 @@ export * from './electron/electron.service'; export * from './daemon/daemon.service'; +export * from './daemon/daemon-data.service'; export { MoneroInstallerService } from './monero-installer/monero-installer.service'; diff --git a/src/app/pages/detail/detail.component.html b/src/app/pages/detail/detail.component.html index e798cd3..060f1e4 100644 --- a/src/app/pages/detail/detail.component.html +++ b/src/app/pages/detail/detail.component.html @@ -17,19 +17,6 @@
-
-
Daemon running
-
-
- - -
-
-
- @for(card of cards; track card.header) { @if(card.loading && !stoppingDaemon) {
diff --git a/src/app/pages/detail/detail.component.ts b/src/app/pages/detail/detail.component.ts index a452004..b35df30 100644 --- a/src/app/pages/detail/detail.component.ts +++ b/src/app/pages/detail/detail.component.ts @@ -1,81 +1,107 @@ -import { Component, OnInit, AfterViewInit, NgZone, OnDestroy } from '@angular/core'; -import { DaemonService } from '../../core/services/daemon/daemon.service'; -import { SyncInfo } from '../../../common/SyncInfo'; +import { Component, AfterViewInit, NgZone } from '@angular/core'; import { Peer } from '../../../common/Peer'; import { NavbarLink } from '../../shared/components/navbar/navbar.model'; import { NavbarService } from '../../shared/components/navbar/navbar.service'; -import { NavigationEnd, Router } from '@angular/router'; -import { DaemonInfo } from '../../../common/DaemonInfo'; - - -import { LogsService } from '../logs/logs.service'; -import { ElectronService } from '../../core/services'; +import { DaemonService, DaemonDataService } from '../../core/services'; @Component({ selector: 'app-detail', templateUrl: './detail.component.html', styleUrls: ['./detail.component.scss'] }) -export class DetailComponent implements OnInit, AfterViewInit, OnDestroy { +export class DetailComponent implements AfterViewInit { - public daemonRunning: boolean; - public startingDaemon: boolean; - public stoppingDaemon: boolean; - private syncInfo?: SyncInfo; - private daemonInfo?: DaemonInfo; - public readonly navbarLinks: NavbarLink[]; - - private syncStatus: string; - private height: number; - private targetHeight: number; - private nextNeededPruningSeed: number; - private overview: string; - private blockCount: number; - private version: string; - - private blockchainSize: string; - private diskUsage: string; - private networkType: string; - private connectionStatus: string; - private txCount: number; - private poolSize: number; - private nodeType: string; - private syncProgress: string; - - private isLoading: boolean; - - private loadInterval?: any; - - public get loading(): boolean { - return this.isLoading; + public get daemonRunning(): boolean { + return this.daemonData.running; } + public get startingDaemon(): boolean { + return this.daemonData.starting; + } + + public get stoppingDaemon(): boolean { + return this.daemonData.stopping; + } + + public readonly navbarLinks: NavbarLink[]; + + //private get syncStatus: string; + + //#region Sync Info + + private get height(): number { + return this.daemonData.syncInfo ? this.daemonData.syncInfo.height : 0; + } + + private get targetHeight(): number { + return this.daemonData.syncInfo ? this.daemonData.syncInfo.targetHeight : 0; + } + + private get nextNeededPruningSeed(): number { + return this.daemonData.syncInfo ? this.daemonData.syncInfo.nextNeededPruningSeed : 0; + } + + private get overview(): string { + return this.daemonData.syncInfo ? this.daemonData.syncInfo.overview : '[]'; + } + + //#endregion + + private get blockCount(): number { + return this.daemonData.blockCount ? this.daemonData.blockCount.count : 0; + } + + //#region Daemon Info + + private get version(): string { + return this.daemonData.info ? this.daemonData.info.version : 'Unknown'; + } + + private get blockchainSize(): number { + return this.daemonData.info ? parseFloat((this.daemonData.info.databaseSize / 1000 / 1000 / 1000).toFixed(2)) : 0; + } + + private get capacity(): number { + return this.daemonData.info ? this.daemonData.info.freeSpace + this.daemonData.info.databaseSize : 0; + } + + private get diskUsage(): number { + return this.daemonData.info ? parseFloat((this.daemonData.info.databaseSize * 100 / this.capacity).toFixed(2)) : 0; + } + + private get networkType(): string { + return this.daemonData.info ? this.daemonData.info.nettype : 'unknown'; + } + + private get connectionStatus(): string { + return this.daemonData.info ? this.daemonData.info.offline ? 'offline' : 'online' : 'offline'; + } + + private get txCount(): number { + return this.daemonData.info ? this.daemonData.info.txCount : 0; + } + + private get poolSize(): number { + return this.daemonData.info ? this.daemonData.info.txPoolSize : 0; + } + + private get nodeType(): string { + return this.daemonData.isBlockchainPruned ? 'pruned' : 'full'; + } + + private get syncProgress(): string { + return `${(this.height*100/this.targetHeight).toFixed(2)} %`; + } + + //#endregion + public cards: Card[]; - public firstLoading: boolean = true; constructor( - private router: Router,private daemonService: DaemonService, - private navbarService: NavbarService, private logsService: LogsService, - private ngZone: NgZone, private electronService: ElectronService) { - this.daemonRunning = false; - this.startingDaemon = false; - this.stoppingDaemon = false; - this.syncStatus = 'Not synced'; - this.height = 0; - this.targetHeight = 0; - this.nextNeededPruningSeed = 0; - this.overview = ''; - this.blockCount = 0; - this.version = ''; - this.diskUsage = '0 %'; - this.networkType = ''; - this.connectionStatus = 'offline'; - this.txCount = 0; - this.poolSize = 0; - this.nodeType = 'unknown'; - this.blockchainSize = '0 GB'; - this.syncProgress = '0 %'; - this.isLoading = false; + private daemonService: DaemonService, + private navbarService: NavbarService, + private daemonData: DaemonDataService, + private ngZone: NgZone) { this.navbarLinks = [ new NavbarLink('pills-home-tab', '#pills-home', 'pills-home', true, 'Overview', true), @@ -83,135 +109,40 @@ export class DetailComponent implements OnInit, AfterViewInit, OnDestroy { new NavbarLink('pills-spans-tab', '#pills-spans', 'pills-spans', false, 'Spans', true) ]; - this.cards = this.createLoadingCards(); + this.cards = this.createCards(); - this.router.events.subscribe((event) => { - if (event instanceof NavigationEnd) { - if (event.url != '/detail') return; - //this.onNavigationEnd(); + this.daemonData.syncInfoRefreshEnd.subscribe(() => { + const $table = $('#table'); + //$table.bootstrapTable({}); + $table.bootstrapTable('refreshOptions', { + classes: 'table table-bordered table-hover table-dark table-striped' + }); + if (this.getPeers().length == 0) $table.bootstrapTable('showLoading'); + else + { + $table.bootstrapTable('load', this.getPeers()); + $table.bootstrapTable('hideLoading'); } - }); - this.daemonService.onDaemonStatusChanged.subscribe((running: boolean) => { - this.ngZone.run(() => { - this.daemonRunning = running; - if (!running && this.stoppingDaemon) { - this.stoppingDaemon = false; - } - }) - }); + this.cards = this.createCards(); + }) } - ngOnInit(): void { - console.log('DetailComponent INIT'); - - } - ngAfterViewInit(): void { console.log('DetailComponent AFTER VIEW INIT'); this.navbarService.setLinks(this.navbarLinks); - setTimeout(() => { - this.ngZone.run(() => { - - const $table = $('#table'); - $table.bootstrapTable({}); - $table.bootstrapTable('refreshOptions', { - classes: 'table table-bordered table-hover table-dark table-striped' - }); - $table.bootstrapTable('showLoading'); - /* - $table.bootstrapTable('refreshOptions', { - classes: 'table table-bordered table-hover table-dark table-striped' - }); - */ - }); - }, 1000); - - - if (this.loadInterval != null) return; - this.ngZone.run(() => { - this.load().then(() => { - this.cards = this.createCards(); - }); - }); - - this.loadInterval = setInterval(() => { - /* + const $table = $('#table'); $table.bootstrapTable({}); + $table.bootstrapTable('refreshOptions', { classes: 'table table-bordered table-hover table-dark table-striped' }); - */ - if (this.stoppingDaemon) return; - this.ngZone.run(() => { + $table.bootstrapTable('showLoading'); - this.load().then(() => { - this.cards = this.createCards(); - }); - }, 5000); - }) - - - } - - ngOnDestroy(): void { - console.log("DetailComponent ON DESTROY"); - - if(this.loadInterval != null) { - clearInterval(this.loadInterval); - } - } - - public async startDaemon(): Promise { - if (this.daemonRunning) { - console.warn("Daemon already running"); - return; - } - - if (this.startingDaemon || this.stoppingDaemon) { - return; - } - - this.startingDaemon = true; - - setTimeout(async () => { - try { - await this.daemonService.startDaemon(); - this.daemonRunning = await this.daemonService.isRunning(); - } - catch(error) { - console.error(error); - this.daemonRunning = false; - } - - this.cards = this.createLoadingCards(); - - this.startingDaemon = false; - }, 500); - } - - public async stopDaemon(): Promise { - if (this.stoppingDaemon || this.startingDaemon || !this.daemonRunning) { - return; - } - - this.stoppingDaemon = true; - - try { - if (this.loadInterval) clearInterval(this.loadInterval); - - await this.daemonService.stopDaemon(); - - if(!this.electronService.isElectron) this.daemonRunning = false; - } - catch (error) { - console.error(error); - } - - if(!this.electronService.isElectron) this.stoppingDaemon = false; + }); } private createLoadingCards(): Card[] { @@ -224,8 +155,8 @@ export class DetailComponent implements OnInit, AfterViewInit, OnDestroy { new Card('Next needed pruning seed', `${this.nextNeededPruningSeed}`, true), new Card('Block count', `${this.blockCount}`, true), new Card('Monero version', this.version, true), - new Card('Blockchain size', this.blockchainSize, true), - new Card('Disk usage', this.diskUsage, true), + new Card('Blockchain size', `${this.blockchainSize} GB`, true), + new Card('Disk usage', `${this.diskUsage} %`, true), new Card('Transaction count', `${this.txCount}`, true), new Card('Pool size', `${this.poolSize}`, true) ]; @@ -235,7 +166,7 @@ export class DetailComponent implements OnInit, AfterViewInit, OnDestroy { if (!this.daemonRunning && !this.daemonService.starting) { return []; } - if (this.firstLoading || this.daemonService.starting) { + if (this.daemonData.initializing || this.daemonService.starting) { return this.createLoadingCards(); } return [ @@ -247,102 +178,19 @@ export class DetailComponent implements OnInit, AfterViewInit, OnDestroy { new Card('Next needed pruning seed', `${this.nextNeededPruningSeed}`), new Card('Block count', `${this.blockCount}`), new Card('Monero version', this.version), - new Card('Blockchain size', this.blockchainSize), - new Card('Disk usage', this.diskUsage), + new Card('Blockchain size', `${this.blockchainSize} GB`), + new Card('Disk usage', `${this.diskUsage} %`), new Card('Transaction count', `${this.txCount}`), new Card('Pool size', `${this.poolSize}`) ]; } - private async load(): Promise { - if (this.isLoading) { - return; - } - - try { - this.isLoading = true; - this.daemonRunning = await this.daemonService.isRunning(); - - if (!this.daemonRunning) { - this.navbarService.disableLinks(); - this.isLoading = false; - return; - } - - this.navbarService.enableLinks(); - - const $table = $('#table'); - $table.bootstrapTable({}); - $table.bootstrapTable('refreshOptions', { - classes: 'table table-bordered table-hover table-dark table-striped' - }); - if (this.getPeers().length == 0) $table.bootstrapTable('showLoading'); - - this.syncInfo = await this.daemonService.syncInfo(); - this.height = this.syncInfo.height; - this.targetHeight = this.syncInfo.targetHeight; - this.nextNeededPruningSeed = this.syncInfo.nextNeededPruningSeed; - - if (this.height > 0 && this.targetHeight == 0) { - this.targetHeight = this.height; - this.syncStatus = 'Daemon synced'; - } - else if (this.height > 0 && this.targetHeight > 0 && this.height == this.targetHeight) { - this.syncStatus = 'Daemon synced'; - } - - this.overview = this.syncInfo.overview; - - const blockCount = await this.daemonService.getBlockCount(); - - this.blockCount = blockCount.count; - - //const version = await this.daemonService.getVersion(); - - //this.version = `${version.version}`; - - this.daemonInfo = await this.daemonService.getInfo(); - - const capacity: number = this.daemonInfo.freeSpace + this.daemonInfo.databaseSize; - const diskUsage = parseInt(`${this.daemonInfo.databaseSize * 100 / capacity}`); - const blockchainSize = (this.daemonInfo.databaseSize / 1000 / 1000 / 1000).toFixed(2); - this.blockchainSize = `${blockchainSize} GB`; - this.diskUsage = `${diskUsage} %`; - this.networkType = this.daemonInfo.nettype; - this.connectionStatus = this.daemonInfo.offline ? 'offline' : 'online'; - this.txCount = this.daemonInfo.txCount; - this.poolSize = this.daemonInfo.txPoolSize; - this.version = this.daemonInfo.version; - this.syncProgress = `${(this.height*100/this.targetHeight).toFixed(2)} %`; - - const blockchainPruned = await this.isBlockchainPruned(); - //const blockchainPruned = false; - this.nodeType = blockchainPruned ? 'pruned' : 'full'; - $table.bootstrapTable('load', this.getPeers()); - $table.bootstrapTable('hideLoading'); - - } - catch(error) { - console.error(error); - } - - this.isLoading = false; - this.firstLoading = false; - - } - - public async isBlockchainPruned(): Promise { - const result = await this.daemonService.pruneBlockchain(true); - - return result.pruned; - } - public getPeers(): any[] { - if (!this.syncInfo) return []; + if (!this.daemonData.syncInfo) return []; const peers: any[] = []; - this.syncInfo.peers.forEach((peer: Peer) => peers.push({ + this.daemonData.syncInfo.peers.forEach((peer: Peer) => peers.push({ 'address': peer.info.address, 'peerId': peer.info.peerId, 'height': peer.info.height, diff --git a/src/app/pages/version/version.component.ts b/src/app/pages/version/version.component.ts index 461e61c..c861331 100644 --- a/src/app/pages/version/version.component.ts +++ b/src/app/pages/version/version.component.ts @@ -56,7 +56,8 @@ export class VersionComponent implements AfterViewInit { } public async load(): Promise { - const version = await this.daemonService.getVersion(this.electronService.isElectron); + const isElectron = this.electronService.isElectron || (window as any).electronAPI != null; + const version = await this.daemonService.getVersion(isElectron); const latestVersion = await this.daemonService.getLatestVersion(); this.currentVersion = version; diff --git a/src/app/shared/components/navbar/navbar.service.ts b/src/app/shared/components/navbar/navbar.service.ts index 6fd9bde..3977365 100644 --- a/src/app/shared/components/navbar/navbar.service.ts +++ b/src/app/shared/components/navbar/navbar.service.ts @@ -1,17 +1,25 @@ import { Injectable } from '@angular/core'; import { NavbarLink } from './navbar.model'; +import { DaemonService } from '../../../core/services'; @Injectable({ providedIn: 'root' }) export class NavbarService { private _navbarLinks: NavbarLink[] = []; + private daemonRunning: boolean = false; public get links(): NavbarLink[] { return this._navbarLinks; } - constructor() { } + constructor(private daemonService: DaemonService) { + this.daemonService.onDaemonStatusChanged.subscribe((running: boolean) => { + this.daemonRunning = running; + if (!running) this.disableLinks(); + if (running) this.enableLinks(); + }) + } public addLink(... navbarLinks: NavbarLink[]): void { navbarLinks.forEach((navLink: NavbarLink) => this._navbarLinks.push(navLink)); @@ -19,6 +27,9 @@ export class NavbarService { public setLinks(navbarLinks: NavbarLink[]): void { this._navbarLinks = navbarLinks; + + if (this.daemonRunning) this.enableLinks(); + else this.disableLinks(); } public removeLinks(): void {