Upgrade monerod implementation

This commit is contained in:
everoddandeven 2024-10-09 20:53:38 +02:00
parent d066b7cdaa
commit f9d878906f
10 changed files with 327 additions and 176 deletions

View file

@ -1,4 +1,4 @@
import {app, BrowserWindow, ipcMain, screen} from 'electron';
import {app, BrowserWindow, ipcMain, screen, dialog } from 'electron';
import { ChildProcess, ChildProcessWithoutNullStreams, exec, spawn } from 'child_process';
import * as path from 'path';
import * as fs from 'fs';
@ -35,9 +35,10 @@ function createWindow(): BrowserWindow {
nodeIntegration: false,
allowRunningInsecureContent: (serve),
contextIsolation: true,
devTools: true
devTools: true,
},
icon: path.join(__dirname, 'assets/icons/favicon.ico')
autoHideMenuBar: true,
icon: path.join(__dirname, '../src/assets/icons/favicon.ico')
});
win.webContents.openDevTools();
@ -72,45 +73,6 @@ function createWindow(): BrowserWindow {
return win;
}
function execMoneroDaemon(configFilePath: string): ChildProcess {
const monerodPath = path.resolve(__dirname, 'path/to/monerod'); // Percorso del binario di monerod
//const command = `"${monerodPath}" --config-file "${configFilePath}"`;
const command = `/home/sidney/Documenti/monero-x86_64-linux-gnu-v0.18.3.4/monerod --testnet --fast-block-sync 1 --prune-blockchain --sync-pruned-blocks --confirm-external-bind --max-concurrency 1 --log-level 1 --rpc-access-control-origins=*`;
const monerodProcess = exec(command, (error, stdout, stderr) => {
if (error) {
console.error(`Errore durante l'avvio di monerod: ${error.message}`);
return;
}
if (stderr) {
console.error(`stderr: ${stderr}`);
return;
}
console.log(`stdout: ${stdout}`);
});
// Gestisci l'output in tempo reale
if (monerodProcess.stdout == null) {
throw new Error("No stdout for monero process")
}
if (monerodProcess.stderr == null) {
throw new Error("No stderr for monero process");
}
monerodProcess.stdout.on('data', (data) => {
console.log(`monerod stdout: ${data}`);
});
monerodProcess.stderr.on('data', (data) => {
console.error(`monerod stderr: ${data}`);
});
return monerodProcess;
}
function getMonerodVersion(monerodFilePath: string): void {
const monerodProcess = spawn(getMonerodPath(), [ '--version' ]);
@ -160,36 +122,6 @@ function startMoneroDaemon(commandOptions: string[]): ChildProcessWithoutNullStr
return monerodProcess;
}
// Funzione per il download
const downloadFileOld = (url: string, destination: string, onProgress: (progress: number) => void): Promise<void> => {
return new Promise((resolve, reject) => {
const file = fs.createWriteStream(destination);
https.get(url, (response) => {
if (response.statusCode === 200) {
const totalBytes = parseInt(response.headers['content-length'] || '0', 10);
let downloadedBytes = 0;
response.on('data', (chunk) => {
downloadedBytes += chunk.length;
const progress = (downloadedBytes / totalBytes) * 100;
onProgress(progress); // Notifica il progresso
});
response.pipe(file);
file.on('finish', () => {
file.close(() => resolve());
});
} else {
reject(new Error(`Failed to download: ${response.statusCode}`));
}
}).on('error', (err) => {
fs.unlink(destination, () => reject(err));
});
});
};
const downloadFile = (url: string, destinationDir: string, onProgress: (progress: number) => void): Promise<string> => {
return new Promise((resolve, reject) => {
const request = (url: string) => {
@ -246,8 +178,6 @@ const downloadFile = (url: string, destinationDir: string, onProgress: (progress
});
};
// Funzione per scaricare e verificare l'hash
const downloadAndVerifyHash = async (hashUrl: string, fileName: string, filePath: string): Promise<boolean> => {
//const hashFilePath = path.join(app.getPath('temp'), 'monero_hashes.txt');
@ -366,28 +296,39 @@ try {
const hashUrl = 'https://www.getmonero.org/downloads/hashes.txt';
// Inizializza il progresso
event.sender.send('download-progress', { progress: 0, status: 'Starting download...' });
event.sender.send('download-progress', { progress: 0, status: 'Starting download' });
// Scarica il file Monero
const fileName = await downloadFile(downloadUrl, destination, (progress) => {
event.sender.send('download-progress', { progress, status: 'Downloading...' });
event.sender.send('download-progress', { progress, status: 'Downloading' });
});
// Scarica e verifica l'hash
event.sender.send('download-progress', { progress: 100, status: 'Verifying hash...' });
event.sender.send('download-progress', { progress: 100, status: 'Verifying hash' });
await downloadAndVerifyHash(hashUrl, fileName, destination);
// Estrai il file
event.sender.send('download-progress', { progress: 100, status: 'Extracting...' });
await extractTarBz2(`${destination}${fileName}`, destination);
const fPath = `${destination}/${fileName}`;
event.sender.send('download-progress', { progress: 100, status: 'Extracting' });
await extractTarBz2(fPath, destination);
event.sender.send('download-progress', { progress: 100, status: 'Download and extraction completed successfully.' });
event.sender.send('download-progress', { progress: 100, status: 'Download and extraction completed successfully' });
event.sender.send('download-progress', { progress: 200, status: fPath.replace('.tar.bz2', '') });
} catch (error) {
event.sender.send('download-progress', { progress: 0, status: `Error: ${error}` });
throw new Error(`Error: ${error}`);
//throw new Error(`Error: ${error}`);
}
});
ipcMain.handle('select-folder', async (event) => {
const result = await dialog.showOpenDialog({
properties: ['openDirectory'], // Specifica che vogliamo solo cartelle
});
const path = result.canceled ? null : result.filePaths[0];
win?.webContents.send('selected-folder', path ? `${path}` : '');
});
} catch (e) {
// Catch Error

View file

@ -25,5 +25,11 @@ contextBridge.exposeInMainWorld('electronAPI', {
},
onDownloadProgress: (callback) => {
ipcRenderer.on('download-progress', callback);
},
selectFolder: () => {
ipcRenderer.invoke('select-folder')
},
onSelectedFolder: (callback) => {
ipcRenderer.on('selected-folder', callback);
}
});

View file

@ -1,36 +1,59 @@
import { Injectable } from '@angular/core';
import { ElectronService } from '../electron/electron.service';
import { Injectable, NgZone } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class MoneroInstallerService {
constructor(private electronService: ElectronService) {}
private _upgrading: boolean = false;
private _progress: { progress: number, status: string } = { progress: 0, status: 'Starting upgrade' }
public downloadMonero(downloadUrl: string, destination: string): Promise<void> {
return new Promise((resolve, reject) => {
if (this.electronService.isElectron) {
this.electronService.ipcRenderer.invoke('download-monero', downloadUrl, destination)
.then(() => resolve())
.catch((error) => reject(error));
public get upgrading(): boolean {
return this._upgrading;
}
this.electronService.ipcRenderer.on('download-progress', (event, { progress, status }) => {
console.log(`Progress: ${progress}% - ${status}`);
// Qui puoi aggiornare lo stato di progresso nel tuo componente
});
}
else {
public get progress(): { progress: number, status: string } {
return this._progress;
}
constructor(private ngZone: NgZone) {}
public async downloadMonero(downloadUrl: string, destination: string): Promise<string> {
this._upgrading = true;
try {
const result = await new Promise<string>((resolve, reject) => {
const wdw = (window as any);
if (wdw.electronAPI && wdw.electronAPI.onDownloadProgress && wdw.electronAPI.downloadMonerod) {
wdw.electronAPI.onDownloadProgress((event: any, progress: any) => {
console.log(`Download progress: ${progress}`);
});
wdw.electronAPI.onDownloadProgress((event: any, progress: { progress: number, status: string }) => {
//console.log(`${progress.progress.toFixed(2)} % ${progress.status}`);
this.ngZone.run(() => {
this._progress = progress;
});
if (progress.status.includes('Error')) {
reject(progress.status);
}
if (progress.progress == 200) {
resolve(progress.status);
}
});
wdw.electronAPI.downloadMonerod(downloadUrl, destination);
}
}
});
this._upgrading = false;
return result;
}
catch (error) {
console.error(error);
this._upgrading = false;
throw error;
}
});
}
}

View file

@ -14,7 +14,20 @@
</div>
<div *ngIf="!loading" class="tab-content" id="pills-settings-tabContent">
<div *ngIf="savingChangesError != ''" class="alert alert-danger d-flex align-items-center justify-content-center text-center" role="alert">
<h4><i class="bi bi-exclamation-triangle m-2"></i></h4>&nbsp;&nbsp;
<div>
{{savingChangesError}}
</div>
</div>
<div *ngIf="savingChangesSuccess" class="alert alert-success d-flex align-items-center justify-content-center text-center" role="alert">
<h4><i class="bi bi-check-circle m-2"></i></h4>&nbsp;&nbsp;
<div>
Successfully saved settings
</div>
</div>
<div class="tab-pane fade show active" id="pills-general" role="tabpanel" aria-labelledby="pills-general-tab" tabindex="0">
<div class="row g-5 p-2">
<div class="col-md-7 col-lg-10">
@ -32,6 +45,23 @@
<small class="text-body-secondary">Path to monerod executable</small>
</div>
<div class="form-check form-switch col-md-6">
<label for="upgrade-automatically" class="form-check-label">Upgrade Automatically</label>
<input class="form-control form-check-input" type="checkbox" role="switch" id="upgrade-automatically" [checked]="currentSettings.upgradeAutomatically" [(ngModel)]="currentSettings.upgradeAutomatically" [ngModelOptions]="{standalone: true}">
<br>
<small class="text-body-secondary">Upgrade monerod automatically when a new version is available</small>
</div>
<div class="col-md-12">
<label for="upgrade-download-path" class="form-label">Download path</label>
<div class="input-group mb-3">
<input id="upgrade-download-path=" type="text" class="form-control form-control-sm" placeholder="" aria-label="Monerod path" aria-describedby="basic-addon2" [value]="currentSettings.downloadUpgradePath" readonly>
<span class="input-group-text" id="basic-addon2"><button type="button" class="btn btn-secondary btn-sm" (click)="chooseMoneroDownloadPath()">Choose folder</button></span>
</div>
<input type="file" class="form-control d-none" id="general-download-monerod-path" webkitdirectory multiple>
<small class="text-body-secondary">Folder where to save updates</small>
</div>
</div>
</div>

View file

@ -1,4 +1,4 @@
import { AfterViewInit, Component } from '@angular/core';
import { AfterViewInit, Component, NgZone } from '@angular/core';
import { NavbarLink } from '../../shared/components/navbar/navbar.model';
import { DaemonSettings } from '../../../common/DaemonSettings';
import { DaemonService } from '../../core/services/daemon/daemon.service';
@ -16,13 +16,15 @@ export class SettingsComponent implements AfterViewInit {
public currentSettings: DaemonSettings;
public savingChanges: boolean = false;
public savingChangesError = ``;
public savingChangesSuccess: boolean = false;
public rpcLoginUser: string;
public rpcLoginPassword: string;
public loading: boolean;
public networkType: 'mainnet' | 'testnet' | 'stagenet' = 'mainnet';
constructor(private daemonService: DaemonService) {
constructor(private daemonService: DaemonService, private ngZone: NgZone) {
this.loading = true;
this.navbarLinks = [
@ -141,6 +143,15 @@ export class SettingsComponent implements AfterViewInit {
}
}
public onMonerodDownloadPathChange(): void {
if (document) {
const element = <HTMLInputElement>document.getElementById('general-download-monerod-path');
if (element.files) {
this.currentSettings.downloadUpgradePath = element.files[0].path;
}
}
}
public async OnSave(): Promise<void> {
if (!this.modified) {
return;
@ -149,12 +160,21 @@ export class SettingsComponent implements AfterViewInit {
this.savingChanges = true;
try {
if (this.currentSettings.upgradeAutomatically && this.currentSettings.downloadUpgradePath == '') {
throw new Error('You must set a download path for monerod updates when enabling automatic upgrade');
}
await this.daemonService.saveSettings(this.currentSettings);
this.originalSettings = this.currentSettings.clone();
this.savingChangesError = ``;
this.savingChangesSuccess = true;
}
catch(error) {
console.error(error);
this.savingChangesError = `${error}`;
this.savingChangesSuccess = false;
}
this.savingChanges = false;
@ -168,6 +188,33 @@ export class SettingsComponent implements AfterViewInit {
}
input.click();
}
public chooseMoneroDownloadPath(): void {
/*
const input = document.getElementById('general-download-monerod-path');
if (!input) {
return;
}
input.click();
*/
const wdw = (window as any);
if (wdw.electronAPI && wdw.electronAPI.selectFolder && wdw.electronAPI.onSelectedFolder) {
wdw.electronAPI.onSelectedFolder((event: any, folder: string) => {
if (folder == '') {
return;
}
this.ngZone.run(() => {
this.currentSettings.downloadUpgradePath = folder;
})
});
wdw.electronAPI.selectFolder();
}
}
public chooseXmrigFile(): void {

View file

@ -2,44 +2,65 @@
<h1 class="h2">Version</h1>
<div class="btn-toolbar mb-2 mb-md-0">
<ul class="nav nav-pills m-3" id="pills-tab" role="tablist">
<!--
@for(navbarLink of navbarLinks; track navbarLink.name) {
@for(navbarLink of links; track navbarLink.name) {
<li class="nav-item mr-2" role="presentation">
<button [class]="navbarLink.selected ? 'nav-link active btn-sm' : 'nav-link btn-sm'" [id]="navbarLink.id" data-bs-toggle="pill" [attr.data-bs-target]="navbarLink.target" type="button" role="tab" [attr.aria-controls]="navbarLink.controls" [attr.aria-selected]="navbarLink.selected" [disabled]="navbarLink.disabled">{{navbarLink.name}}</button>
</li>
} -->
}
</ul>
</div>
</div>
<div class="row d-flex justify-content-center">
@for(card of cards; track card.header) {
@if(card.loading) {
<div class="card text-bg-dark m-3 text-center" style="max-width: 18rem;" aria-hidden="true">
<div class="card-header"><strong>{{card.header}}</strong></div>
<div class="card-body">
<p class="card-text placeholder-glow">
<span class="placeholder col-7"></span>
<span class="placeholder col-4"></span>
<span class="placeholder col-4"></span>
<span class="placeholder col-6"></span>
<span class="placeholder col-8"></span>
</p>
</div>
<div class="tab-content" id="pills-tabContent">
<div class="tab-pane fade show active" id="pills-monero" role="tabpanel" aria-labelledby="pills-monero-tab" tabindex="0">
<div *ngIf="upgradeError != ''" class="alert alert-danger d-flex align-items-center justify-content-center text-center" role="alert">
<h4><i class="bi bi-exclamation-triangle m-2"></i></h4>&nbsp;&nbsp;
<div>
{{upgradeError}}
</div>
}
@else {
<div class="card text-bg-dark m-3 text-center" style="max-width: 18rem;">
<div class="card-header"><strong>{{card.header}}</strong></div>
<div class="card-body">
<h5 class="card-title">{{card.content}}</h5>
</div>
</div>
<div *ngIf="upgradeSuccess" class="alert alert-success d-flex align-items-center justify-content-center text-center" role="alert">
<h4><i class="bi bi-check-circle m-2"></i></h4>&nbsp;&nbsp;
<div>
Successfully upgraded monerod
</div>
}
}
</div>
<div class="row d-flex justify-content-center">
@for(card of cards; track card.header) {
@if(card.loading) {
<div class="card text-bg-dark m-3 text-center" style="max-width: 18rem;" aria-hidden="true">
<div class="card-header"><strong>{{card.header}}</strong></div>
<div class="card-body">
<p class="card-text placeholder-glow">
<span class="placeholder col-7"></span>
<span class="placeholder col-4"></span>
<span class="placeholder col-4"></span>
<span class="placeholder col-6"></span>
<span class="placeholder col-8"></span>
</p>
</div>
</div>
}
@else {
<div class="card text-bg-dark m-3 text-center" style="max-width: 18rem;">
<div class="card-header"><strong>{{card.header}}</strong></div>
<div class="card-body">
<h5 class="card-title">{{card.content}}</h5>
</div>
</div>
}
}
</div>
<hr class="my-4">
<button *ngIf="!upgrading" class="w-100 btn btn-primary btn-lg" type="submit" (click)="upgrade()" [disabled]="buttonDisabled">{{ buttonTitle }}</button>
<button *ngIf="upgrading" class="w-100 btn btn-primary btn-lg" type="button" disabled>
<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span>
Upgrading monerod
</button>
</div>
</div>
<hr class="my-4">
<button class="w-100 btn btn-primary btn-lg" type="submit" (click)="upgrade()">Upgrade</button>

View file

@ -4,7 +4,7 @@ import { NavbarLink } from '../../shared/components/navbar/navbar.model';
import { DaemonService } from '../../core/services/daemon/daemon.service';
import { SimpleBootstrapCard } from '../../shared/utils';
import { DaemonVersion } from '../../../common/DaemonVersion';
import { ElectronService, MoneroInstallerService } from '../../core/services';
import { DaemonDataService, ElectronService, MoneroInstallerService } from '../../core/services';
@Component({
selector: 'app-version',
@ -12,16 +12,49 @@ import { ElectronService, MoneroInstallerService } from '../../core/services';
styleUrl: './version.component.scss'
})
export class VersionComponent implements AfterViewInit {
private readonly links: NavbarLink[];
public readonly links: NavbarLink[];
public cards: SimpleBootstrapCard[];
public currentVersion?: DaemonVersion;
public latestVersion?: DaemonVersion;
public downloadPath: string = '/home/sidney/monerod/';
constructor(private navbarService: NavbarService, private daemonService: DaemonService, private electronService: ElectronService, private moneroInstaller: MoneroInstallerService) {
public get buttonDisabled(): boolean {
const title = this.buttonTitle;
if (title == 'Install') {
return false;
}
const configured = this.daemonService.settings.monerodPath != '';
const updateAvailable = this.daemonData.info ? this.daemonData.info.updateAvailable : false;
if (title == 'Upgrade' && configured && updateAvailable) {
return false;
}
return true;
}
public get buttonTitle(): string {
const updateAvailable = this.daemonData.info ? this.daemonData.info.updateAvailable : false;
if (updateAvailable) {
return 'Upgrade';
}
const notConfigured = this.daemonService.settings.monerodPath == '';
if (notConfigured) {
return 'Install';
}
return 'Upgrade';
}
constructor(private daemonData: DaemonDataService, private daemonService: DaemonService, private electronService: ElectronService, private moneroInstaller: MoneroInstallerService) {
this.links = [
new NavbarLink('pills-overview-tab', '#pills-overview', 'pills-overview', true, 'Overview')
new NavbarLink('pills-monero-tab', '#pills-monero', 'pills-monero', true, 'Monero')
];
this.cards = this.createCards();
}
@ -43,16 +76,16 @@ export class VersionComponent implements AfterViewInit {
}
public ngAfterViewInit(): void {
this.navbarService.setLinks(this.links);
this.load()
.then(() => {
this.cards = this.createCards();
})
.catch((error: any) => {
this.currentVersion = undefined;
this.latestVersion = undefined
this.cards = this.createErrorCards();
});
this.upgrading = this.moneroInstaller.upgrading;
this.load()
.then(() => {
this.cards = this.createCards();
})
.catch((error: any) => {
this.currentVersion = undefined;
this.latestVersion = undefined
this.cards = this.createErrorCards();
});
}
public async load(): Promise<void> {
@ -64,21 +97,46 @@ export class VersionComponent implements AfterViewInit {
this.latestVersion = latestVersion;
}
public upgrading: boolean = false;
public upgradeSuccess: boolean = false;
public upgradeError: string = '';
public downloadProgress: number = 100;
public downloadStatus : string = '';
public async upgrade(): Promise<void> {
const downloadUrl = 'https://downloads.getmonero.org/cli/linux64'; // Cambia in base al sistema
const destination = '/home/sidney/'; // Aggiorna con il percorso desiderato
if (this.upgrading) {
console.warn("Already upgrading");
return;
}
this.moneroInstaller.downloadMonero(downloadUrl, destination)
.then(() => {
console.log('Download completato con successo.');
})
.catch((error) => {
console.error('Errore:', error);
});
this.upgrading = true;
try {
const settings = await this.daemonService.getSettings();
if (settings.upgradeAutomatically) {
throw new Error('Monero Daemon will upgrade automatically');
}
if (settings.downloadUpgradePath == '') {
throw new Error("Download path not configured");
}
const downloadUrl = 'https://downloads.getmonero.org/cli/linux64'; // Cambia in base al sistema
const destination = settings.downloadUpgradePath; // Aggiorna con il percorso desiderato
const moneroFolder = await this.moneroInstaller.downloadMonero(downloadUrl, destination);
settings.monerodPath = `${moneroFolder}/monerod`;
await this.daemonService.saveSettings(settings);
this.upgradeError = '';
this.upgradeSuccess = true;
}
catch(error) {
console.error(error);
this.upgradeSuccess = false;
this.upgradeError = `${error}`;
}
this.upgrading = false;
}
}

View file

@ -1,17 +1,19 @@
<div *ngIf="!daemonRunning || stoppingDaemon || restartingDaemon" class="h-100 p-5 text-bg-dark rounded-3 m-4 text-center">
<h2 *ngIf="!daemonRunning && !startingDaemon && !stoppingDaemon && !restartingDaemon && daemonConfigured"><i class="bi bi-exclamation-diamond m-4"></i> Daemon not running</h2>
<h2 *ngIf="!daemonRunning && !startingDaemon && !stoppingDaemon && !restartingDaemon && !daemonConfigured"><i class="bi bi-exclamation-diamond m-4"></i> Daemon not configured</h2>
<h2 *ngIf="restartingDaemon"><i class="bi bi-arrow-clockwise m-4"></i> Daemon restarting</h2>
<h2 *ngIf="stoppingDaemon"><i class="bi bi-stop-fill m-4"></i> Daemon is stopping</h2>
<h2 *ngIf="!daemonRunning && !startingDaemon && !stoppingDaemon && !restartingDaemon && !upgrading && daemonConfigured"><i class="bi bi-exclamation-diamond m-4"></i> Daemon not running</h2>
<h2 *ngIf="!daemonRunning && !startingDaemon && !stoppingDaemon && !restartingDaemon && !upgrading && !daemonConfigured"><i class="bi bi-exclamation-diamond m-4"></i> Daemon not configured or installed</h2>
<h2 *ngIf="restartingDaemon && !upgrading"><i class="bi bi-arrow-clockwise m-4"></i> Daemon restarting</h2>
<h2 *ngIf="stoppingDaemon && !upgrading"><i class="bi bi-stop-fill m-4"></i> Daemon is stopping</h2>
<h2 *ngIf="upgrading"><i class="bi bi-cloud-download m-4"></i> Daemon is upgrading</h2>
<p *ngIf="!daemonRunning && !startingDaemon && !stoppingDaemon && !restartingDaemon && daemonConfigured">Start monero daemon</p>
<p *ngIf="!startingDaemon && !startingDaemon && !stoppingDaemon && !restartingDaemon && !daemonConfigured">Configure monero daemon</p>
<p *ngIf="!daemonRunning && !startingDaemon && !stoppingDaemon && !restartingDaemon && daemonConfigured && !upgrading">Start monero daemon</p>
<p *ngIf="!startingDaemon && !startingDaemon && !stoppingDaemon && !restartingDaemon && !daemonConfigured && !upgrading">Configure or install monero daemon</p>
<h2 *ngIf="startingDaemon"><i class="bi bi-play-fill m-4"></i> Daemon is starting</h2>
<p *ngIf="startingDaemon">Starting monero daemon</p>
<p *ngIf="restartingDaemon">Restarting monero daemon</p>
<p *ngIf="upgrading">Upgrading monero daemon to latest version</p>
<button *ngIf="!startingDaemon && !stoppingDaemon && !restartingDaemon && daemonConfigured" class="btn btn-outline-light" type="button" (click)="startDaemon()"><i class="bi bi-play-fill"></i> Start</button>
<button *ngIf="!startingDaemon && !stoppingDaemon && !restartingDaemon && !upgrading && daemonConfigured" class="btn btn-outline-light" type="button" (click)="startDaemon()"><i class="bi bi-play-fill"></i> Start</button>
<button *ngIf="startingDaemon" class="btn btn-outline-light" type="button" disabled>
<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span>
Starting monerod
@ -26,7 +28,13 @@
<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span>
Stopping monerod
</button>
<button *ngIf="upgrading" class="btn btn-outline-light" type="button" disabled>
<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span>
{{ progressStatus }}
</button>
&nbsp;
<button *ngIf="!startingDaemon && !stoppingDaemon && !restartingDaemon" routerLink="/settings" class="btn btn-outline-light" type="button"><i class="bi bi-gear"></i> Configure</button>
</div>
<button *ngIf="!startingDaemon && !stoppingDaemon && !restartingDaemon && !upgrading" routerLink="/settings" class="btn btn-outline-light" type="button"><i class="bi bi-gear"></i> Configure</button>
<button *ngIf="!startingDaemon && !stoppingDaemon && !restartingDaemon && !upgrading" routerLink="/version" class="btn btn-outline-light" type="button"><i class="bi bi-arrow-down-circle"></i> Install</button>
</div>

View file

@ -1,6 +1,6 @@
import { Component, Input, NgZone } from '@angular/core';
import { DaemonService } from '../../../core/services/daemon/daemon.service';
import { DaemonDataService } from '../../../core/services';
import { DaemonDataService, MoneroInstallerService } from '../../../core/services';
@Component({
selector: 'app-daemon-not-running',
@ -9,25 +9,39 @@ import { DaemonDataService } from '../../../core/services';
})
export class DaemonNotRunningComponent {
public get upgrading(): boolean {
return this.installer.upgrading;
}
public get daemonRunning(): boolean {
return this.daemonData.running && !this.startingDaemon && !this.stoppingDaemon && !this.restartingDaemon;
return this.daemonData.running && !this.startingDaemon && !this.stoppingDaemon && !this.restartingDaemon && !this.upgrading;
}
public daemonConfigured: boolean = true;
public get startingDaemon(): boolean {
return this.daemonService.starting && !this.restartingDaemon;
return this.daemonService.starting && !this.restartingDaemon && !this.stoppingDaemon && !this.upgrading;
}
public get stoppingDaemon(): boolean{
return this.daemonData.stopping && !this.restartingDaemon;
return this.daemonData.stopping && !this.restartingDaemon && !this.startingDaemon && !this.upgrading;
}
public get restartingDaemon(): boolean {
return this.daemonService.restarting;
return this.daemonService.restarting && ! this.upgrading;
}
constructor(private daemonData: DaemonDataService, private daemonService: DaemonService, private ngZone: NgZone) {
public get progressStatus(): string {
const progress = this.installer.progress;
if (progress.status == 'Downloading') {
return `${progress.status} ${progress.progress.toFixed(2)} %`;
}
return progress.status;
}
constructor(private installer: MoneroInstallerService, private daemonData: DaemonDataService, private daemonService: DaemonService, private ngZone: NgZone) {
this.daemonService.getSettings().then((settings) => {
this.daemonConfigured = settings.monerodPath != '';
})

View file

@ -6,6 +6,9 @@ export class DaemonSettings {
public syncPeriodFrom: any = '00:00';
public syncPeriodTo: any = '00:00';
public upgradeAutomatically: boolean = false;
public downloadUpgradePath: string = '';
public logFile: string = '';
public logLevel: number = 0;
public maxLogFileSize: number = 104850000;