diff --git a/src/app/shared/components/navbar/navbar.service.ts b/src/app/shared/components/navbar/navbar.service.ts
index f3ea568..e062c50 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, NgZone } from '@angular/core';
+import { EventEmitter, Injectable, NgZone } from '@angular/core';
import { NavbarLink } from './navbar.model';
import { DaemonService } from '../../../core/services';
@@ -13,6 +13,10 @@ export class NavbarService {
return this._navbarLinks;
}
+ public get onDaemonStatusChanged(): EventEmitter {
+ return this.daemonService.onDaemonStatusChanged;
+ }
+
constructor(private daemonService: DaemonService, private zone: NgZone) {
this.daemonService.onDaemonStatusChanged.subscribe((running: boolean) => {
this.daemonRunning = running;
diff --git a/src/common/DaemonSettings.ts b/src/common/DaemonSettings.ts
index 369ee0e..4a1df50 100644
--- a/src/common/DaemonSettings.ts
+++ b/src/common/DaemonSettings.ts
@@ -1,3 +1,5 @@
+import { DaemonSettingsDuplicateExclusiveNodeError, DaemonSettingsDuplicatePriorityNodeError, DaemonSettingsInvalidNetworkError, DaemonSettingsInvalidValueError, DaemonSettingsUnknownKeyError } from "./error";
+
export class DaemonSettings {
public monerodPath: string = '';
@@ -45,7 +47,7 @@ export class DaemonSettings {
public keepFakeChain: boolean = false;
public fixedDifficulty: number = 0;
- public enforceDnsCheckpoint: boolean = false;
+ public enforceDnsCheckpointing: boolean = false;
public prepBlocksThreads: number = 0;
public fastBlockSync: boolean = false;
public showTimeStats: boolean = false;
@@ -70,7 +72,7 @@ export class DaemonSettings {
public extraMessagesFile: string = '';
public startMining: string = '';
- public miningThreds: number = 0;
+ public miningThreads: number = 0;
public bgMiningEnable: boolean = false;
public bgMiningIgnoreBattery: boolean = false;
@@ -90,8 +92,10 @@ export class DaemonSettings {
public p2pExternalPort: number = 0;
public allowLocalIp: boolean = false;
public addPeer: string = '';
- public addPriorityNode: string = '';
- public addExclusiveNode: string = '';
+ //public addPriorityNode: string = '';
+ //public addExclusiveNode: string = '';
+ public exclusiveNodes: string[] = [];
+ public priorityNodes: string[] = [];
public seedNode: string = '';
public txProxy: string = '';
@@ -104,7 +108,7 @@ export class DaemonSettings {
public enableDnsBlocklist: boolean = false;
public noIgd: boolean = false;
- public igd: 'disable' | 'enabled' | 'delayed' = 'delayed';
+ public igd: 'disabled' | 'enabled' | 'delayed' = 'delayed';
public outPeers: number = -1;
public inPeers: number = -1;
public tosFlag: number = -1;
@@ -146,6 +150,60 @@ export class DaemonSettings {
public rpcPaymentAllowFreeLoopback: boolean = false;
public disableRpcBan: boolean = false;
+ public get banListArray(): string[] {
+ return this.banList.split('\n');
+ }
+
+ public get hasExclusiveNodes(): boolean {
+ return this.exclusiveNodes.length > 0;
+ }
+
+ public get hasPriorityNodes(): boolean {
+ return this.priorityNodes.length > 0;
+ }
+
+ public addExclusiveNode(node: string): void {
+ if (this.exclusiveNodes.includes(node)) {
+ throw new DaemonSettingsDuplicateExclusiveNodeError(node);
+ }
+
+ this.exclusiveNodes.push(node);
+ }
+
+ public removeExclusiveNode(node: string): void {
+ this.exclusiveNodes = this.exclusiveNodes.filter((n) => n !== node);
+ }
+
+ public addPriorityNode(node: string): void {
+ if (this.priorityNodes.includes(node)) {
+ throw new DaemonSettingsDuplicatePriorityNodeError(node);
+ }
+
+ this.priorityNodes.push(node);
+ }
+
+ public removePriorityNode(node: string): void {
+ this.priorityNodes = this.priorityNodes.filter((n) => n !== node);
+ }
+
+ public assertValid(): void {
+ if (this.upgradeAutomatically && this.downloadUpgradePath == '') {
+ throw new Error('You must set a download path for monerod updates when enabling automatic upgrade');
+ }
+
+ if (this.monerodPath != '' && this.downloadUpgradePath != '') {
+ const separator: '\\' | '/' = this.monerodPath.includes('\\') ? '\\' : '/';
+ const monerodDirComponents = this.monerodPath.split(separator);
+
+ monerodDirComponents.pop();
+
+ if (monerodDirComponents.join(separator) == this.downloadUpgradePath || this.monerodPath == this.downloadUpgradePath) {
+ throw new Error("You must choose a download path other than the monerod path")
+ }
+
+ }
+ }
+
public equals(settings: DaemonSettings): boolean {
//return this.toCommandOptions().join('') == settings.toCommandOptions().join('');
return this.deepEqual(this, settings);
@@ -172,15 +230,40 @@ export class DaemonSettings {
// Se una chiave di obj1 non esiste in obj2, non sono uguali
if (!keys2.includes(key)) return false;
+ if (key == 'exclusiveNodes' && obj1 instanceof DaemonSettings && obj2 instanceof DaemonSettings) {
+ if (obj1.exclusiveNodes.length !== obj2.exclusiveNodes.length) return false;
+ else {
+ for(const en of obj1.exclusiveNodes) {
+ if (!obj2.exclusiveNodes.includes(en)) return false;
+ }
+ }
+ }
+ else if (key == 'priorityNodes' && obj1 instanceof DaemonSettings && obj2 instanceof DaemonSettings) {
+ if (obj1.priorityNodes.length !== obj2.priorityNodes.length) return false;
+ else {
+ for(const en of obj1.priorityNodes) {
+ if (!obj2.priorityNodes.includes(en)) return false;
+ }
+ }
+ }
+ else if (!this.deepEqual(obj1[key], obj2[key])) return false;
+
// Se il valore della proprietà non è uguale, effettua un confronto ricorsivo
- if (!this.deepEqual(obj1[key], obj2[key])) return false;
}
return true;
}
public clone(): DaemonSettings {
- return Object.assign(new DaemonSettings(), this);
+ const result = Object.assign(new DaemonSettings(), this);
+
+ result.exclusiveNodes = [];
+ result.priorityNodes = [];
+
+ this.exclusiveNodes.forEach((en) => result.addExclusiveNode(en));
+ this.priorityNodes.forEach((pn) => result.addPriorityNode(pn));
+
+ return result;
}
public static parse(data: any): DaemonSettings {
@@ -225,12 +308,21 @@ export class DaemonSettings {
const boolValue = value === '1'; // Interpret 1 as true, 0 as false
switch (key) {
+ case 'ban-list': settings.banList = value; break;
case 'data-dir': settings.dataDir = value; break;
case 'log-file': settings.logFile = value; break;
case 'log-level': settings.logLevel = parseInt(value, 10); break;
case 'max-log-files': settings.maxLogFileSize = parseInt(value, 10); break;
case 'max-log-file-size': settings.maxLogFileSize = parseInt(value, 10); break;
case 'no-igd': settings.noIgd = boolValue; break;
+ case `igd`: {
+ if (value === 'enabled' || value === 'disabled' || value === 'delayed') {
+ settings.igd = value; break;
+ }
+ else {
+ throw new DaemonSettingsInvalidValueError(key, value);
+ }
+ }
case 'enable-dns-blocklist': settings.enableDnsBlocklist = boolValue; break;
case 'testnet': settings.testnet = boolValue; break;
case 'mainnet': settings.mainnet = boolValue; break;
@@ -244,14 +336,15 @@ export class DaemonSettings {
case 'p2p-bind-ip': settings.p2pBindIp = value; break;
case 'p2p-bind-ipv6-address': settings.p2pBindIpv6Address = value; break;
case 'p2p-bind-port': settings.p2pBindPort = parseInt(value, 10); break;
+ case 'p2p-bind-port-ipv6': settings.p2pBindPortIpv6 = parseInt(value, 10); break;
case 'p2p-use-ipv6': settings.p2pUseIpv6 = boolValue; break;
+ case 'p2p-ignore-ipv4': settings.p2pIgnoreIpv4 = boolValue; break;
+ case 'p2p-external-port': settings.p2pExternalPort = parseInt(value, 10); break;
case 'add-peer': settings.addPeer = value; break;
- case 'add-priority-node': settings.addPriorityNode = value; break;
+ case 'add-priority-node': settings.addPriorityNode(value); break;
case 'bootstrap-daemon-address': settings.bootstrapDaemonAddress = value; break;
case 'bootstrap-daemon-login': settings.bootstrapDaemonLogin = value; break;
case 'bootstrap-daemon-proxy': settings.bootstrapDaemonProxy = value; break;
- case 'rpc-bind-ip': settings.rpcBindIp = value; break;
- case 'rpc-bind-port': settings.rpcBindPort = parseInt(value, 10); break;
case 'confirm-external-bind': settings.confirmExternalBind = boolValue; break;
case 'disable-dns-checkpoints': settings.disableDnsCheckpoints = boolValue; break;
case 'sync-pruned-blocks': settings.syncPrunedBlocks = boolValue; break;
@@ -271,6 +364,8 @@ export class DaemonSettings {
case 'tos-flag': settings.tosFlag = parseInt(value, 10); break;
case 'max-connections-per-ip': settings.maxConnectionsPerIp = parseInt(value, 10); break;
case 'disable-rpc-ban': settings.disableRpcBan = boolValue; break;
+ case 'rpc-bind-ip': settings.rpcBindIp = value; break;
+ case 'rpc-bind-port': settings.rpcBindPort = parseInt(value, 10); break;
case 'rpc-access-control-origins': settings.rpcAccessControlOrigins = value; break;
case 'rpc-ssl': settings.rpcSsl = value as 'autodetect' | 'enabled' | 'disabled'; break;
case 'rpc-ssl-private-key': settings.rpcSslPrivateKey = value; break;
@@ -282,12 +377,13 @@ export class DaemonSettings {
case 'rpc-payment-allow-free-loopback': settings.rpcPaymentAllowFreeLoopback = boolValue; break;
case 'rpc-payment-difficulty': settings.rpcPaymentDifficuly = parseInt(value, 10); break;
case 'rpc-payment-credits': settings.rpcPaymentCredits = parseInt(value, 10); break;
+ case 'rpc-payment-address': settings.rpcPaymentAddress = value; break;
+ case 'restricted-rpc': settings.restrictedRpc = boolValue; break;
case 'extra-messages-file': settings.extraMessagesFile = value; break;
case 'seed-node': settings.seedNode = value; break;
case 'zmq-rpc-bind-ip': settings.zmqRpcBindIp = value; break;
case 'zmq-rpc-bind-port': settings.zmqRpcBindPort = parseInt(value, 10); break;
case 'zmq-pub': settings.zmqPub = value; break;
- case 'rpc-payment-address': settings.rpcPaymentAddress = value; break;
case 'no-zmq': settings.noZmq = boolValue; break;
case 'fixed-difficulty': settings.fixedDifficulty = parseInt(value, 10); break;
case 'prep-blocks-threads': settings.prepBlocksThreads = parseInt(value, 10); break;
@@ -296,27 +392,28 @@ export class DaemonSettings {
case 'show-time-stats': settings.showTimeStats = boolValue; break;
case 'block-sync-size': settings.blockSyncSize = parseInt(value, 10); break;
case 'block-rate-notify': settings.blockRateNotify = value; break;
+ case 'block-download-max-size': settings.blockDownloadMaxSize = parseInt(value, 10); break;
case 'reorg-notify': settings.reorgNotify = value; break;
case 'prune-blockchain': settings.pruneBlockchain = boolValue; break;
case 'keep-alt-blocks': settings.keepAltBlocks = boolValue; break;
- case 'keep-fake-chain': settings.keepFakeChain = boolValue; break;
- case 'add-exclusive-node': settings.addExclusiveNode = value; break;
+ case 'keep-fakechain': settings.keepFakeChain = boolValue; break;
+ case 'add-exclusive-node': settings.addExclusiveNode(value); break;
case 'no-sync': settings.noSync = boolValue; break;
case 'start-mining': settings.startMining = value; break;
- case 'mining-threads': settings.miningThreds = parseInt(value, 10); break;
+ case 'mining-threads': settings.miningThreads = parseInt(value, 10); break;
case 'bg-mining-enable': settings.bgMiningEnable = boolValue; break;
case 'bg-mining-ignore-battery': settings.bgMiningIgnoreBattery = boolValue; break;
case 'bg-mining-idle-threshold': settings.bgMiningIdleThreshold = parseInt(value, 10); break;
+ case 'bg-mining-min-idle-interval': settings.bgMiningMinIdleInterval = parseInt(value, 10); break;
case 'bg-mining-miner-target': settings.bgMiningMinerTarget = parseInt(value, 10); break;
case 'hide-my-port': settings.hideMyPort = boolValue; break;
- case 'enforce-dns-checkpoint': settings.enforceDnsCheckpoint = boolValue; break;
+ case 'enforce-dns-checkpointing': settings.enforceDnsCheckpointing = boolValue; break;
case 'test-drop-download': settings.testDropDownload = boolValue; break;
case 'test-drop-download-height': settings.testDropDownloadHeight = parseInt(value, 10); break;
case 'test-dbg-lock-sleep': settings.testDbgLockSleep = parseInt(value, 10); break;
case 'in-peers': settings.inPeers = parseInt(value, 10); break;
case 'out-peers': settings.outPeers = parseInt(value, 10); break;
-
- default: throw new Error(`Invalid setting: ${key}`);
+ default: throw new DaemonSettingsUnknownKeyError(key);
}
});
@@ -342,7 +439,7 @@ export class DaemonSettings {
if (this.testnet) options.push(`--testnet`);
else if (this.stagenet) options.push(`--stagenet`);
else if (!this.mainnet) {
- throw new Error("Invalid daemon settings");
+ throw new DaemonSettingsInvalidNetworkError();
}
if (this.logFile != '') options.push('--log-file', this.logFile);
@@ -360,11 +457,11 @@ export class DaemonSettings {
if (!this.noZmq && this.zmqPub != '') options.push(`--zmq-pub`, this.zmqPub);
if (this.testDropDownload) options.push(`--test-drop-download`);
if (this.testDropDownload && this.testDropDownloadHeight) options.push(`--test-drop-download-height`);
- if (this.testDbgLockSleep) options.push(`--tet-dbg-lock-sleep`, `${this.testDbgLockSleep}`);
+ if (this.testDbgLockSleep) options.push(`--test-dbg-lock-sleep`, `${this.testDbgLockSleep}`);
if (this.regtest) options.push(`--regtest`);
if (this.keepFakeChain) options.push(`--keep-fakechain`);
if (this.fixedDifficulty) options.push(`--fixed-difficulty`, `${this.fixedDifficulty}`);
- if (this.enforceDnsCheckpoint) options.push(`--enforce-dns-checkpoint`);
+ if (this.enforceDnsCheckpointing) options.push(`--enforce-dns-checkpointing`);
if (this.prepBlocksThreads) options.push(`--prep-blocks-threads`, `${this.prepBlocksThreads}`);
if (!this.noSync && this.fastBlockSync) options.push(`--fast-block-sync`, `1`);
if (this.showTimeStats) options.push(`--show-time-stats`);
@@ -383,11 +480,11 @@ export class DaemonSettings {
if (this.keepAltBlocks) options.push(`--keep-alt-blocks`);
if (this.extraMessagesFile != '') options.push(`--extra-messages-file`, this.extraMessagesFile);
if (this.startMining != '') options.push(`--start-mining`, this.startMining);
- if (this.miningThreds) options.push(`--mining-threads`, `${this.miningThreds}`);
+ if (this.miningThreads) options.push(`--mining-threads`, `${this.miningThreads}`);
if (this.bgMiningEnable) options.push(`--bg-mining-enable`);
if (this.bgMiningIgnoreBattery) options.push(`--bg-mining-ignore-battery`);
if (this.bgMiningIdleThreshold) options.push(`--bg-mining-idle-threshold`, `${this.bgMiningIdleThreshold}`);
- if (this.bgMiningMinIdleInterval) options.push(`--bg-mining-idle-interval`, `${this.bgMiningMinIdleInterval}`);
+ if (this.bgMiningMinIdleInterval) options.push(`--bg-mining-min-idle-interval`, `${this.bgMiningMinIdleInterval}`);
if (this.bgMiningMinerTarget) options.push(`--bg-mining-miner-target`, `${this.bgMiningMinerTarget}`);
if (!this.noSync && this.dbSyncMode != '') options.push(`--db-sync-mode`, `${this.dbSyncMode}`);
if (this.dbSalvage) options.push(`--db-salvage`);
@@ -400,8 +497,8 @@ export class DaemonSettings {
if (this.p2pExternalPort > 0) options.push(`--p2p-external-port`, `${this.p2pExternalPort}`);
if (this.allowLocalIp) options.push(`--allow-local-ip`);
if (this.addPeer != '') options.push('--add-peer', this.addPeer);
- if (this.addPriorityNode != '') options.push(`--add-priority-node`, this.addPriorityNode);
- if (this.addExclusiveNode != '') options.push(`--add-exlcusive-node`, this.addExclusiveNode);
+ if (this.hasPriorityNodes) this.priorityNodes.forEach((node) => options.push(`--add-priority-node`, node));
+ if (this.hasExclusiveNodes) this.exclusiveNodes.forEach((node) => options.push(`--add-exlcusive-node`, node));
if (this.seedNode != '') options.push(`--seed-node`, this.seedNode);
if (this.txProxy != '') options.push(`--tx-proxy`, this.txProxy);
if (this.anonymousInbound != '') options.push(`--anonymous-inbound`, this.anonymousInbound);
@@ -410,6 +507,7 @@ export class DaemonSettings {
if (this.noSync) options.push(`--no-sync`);
if (this.enableDnsBlocklist) options.push(`--enable-dns-blocklist`);
if (this.noIgd) options.push(`--no-igd`);
+ if (!this.noIgd && this.igd) options.push(`--igd`, this.igd);
if (this.outPeers >= 0) options.push(`--out-peers`, `${this.outPeers}`);
if (this.inPeers >= 0) options.push(`--in-peers`, `${this.inPeers}`);
if (this.tosFlag >= 0) options.push(`--tos-flag`, `${this.tosFlag}`);
diff --git a/src/common/error/DaemonSettingsDuplicateExclusiveNodeError.ts b/src/common/error/DaemonSettingsDuplicateExclusiveNodeError.ts
new file mode 100644
index 0000000..6dd69cb
--- /dev/null
+++ b/src/common/error/DaemonSettingsDuplicateExclusiveNodeError.ts
@@ -0,0 +1,8 @@
+import { DaemonSettingsDuplicateNodeError } from "./DaemonSettingsDuplicateNodeError";
+
+export class DaemonSettingsDuplicateExclusiveNodeError extends DaemonSettingsDuplicateNodeError {
+
+ constructor(node: string) {
+ super(node, "exclusive");
+ }
+}
\ No newline at end of file
diff --git a/src/common/error/DaemonSettingsDuplicateNodeError.ts b/src/common/error/DaemonSettingsDuplicateNodeError.ts
new file mode 100644
index 0000000..efc1051
--- /dev/null
+++ b/src/common/error/DaemonSettingsDuplicateNodeError.ts
@@ -0,0 +1,13 @@
+import { DaemonSettingsError } from "./DaemonSettingsError";
+
+export abstract class DaemonSettingsDuplicateNodeError extends DaemonSettingsError {
+ public node: string;
+ public type: string;
+
+ constructor(node: string, type: string) {
+ super(`${type} node ${node} already added`);
+
+ this.node = node;
+ this.type = type;
+ }
+}
\ No newline at end of file
diff --git a/src/common/error/DaemonSettingsDuplicatePriorityNodeError.ts b/src/common/error/DaemonSettingsDuplicatePriorityNodeError.ts
new file mode 100644
index 0000000..8c6a89d
--- /dev/null
+++ b/src/common/error/DaemonSettingsDuplicatePriorityNodeError.ts
@@ -0,0 +1,8 @@
+import { DaemonSettingsDuplicateNodeError } from "./DaemonSettingsDuplicateNodeError";
+
+export class DaemonSettingsDuplicatePriorityNodeError extends DaemonSettingsDuplicateNodeError {
+
+ constructor(node: string) {
+ super(node, "priority");
+ }
+}
\ No newline at end of file
diff --git a/src/common/error/DaemonSettingsError.ts b/src/common/error/DaemonSettingsError.ts
new file mode 100644
index 0000000..91c16b6
--- /dev/null
+++ b/src/common/error/DaemonSettingsError.ts
@@ -0,0 +1,3 @@
+export class DaemonSettingsError extends Error {
+
+}
\ No newline at end of file
diff --git a/src/common/error/DaemonSettingsInvalidNetworkError.ts b/src/common/error/DaemonSettingsInvalidNetworkError.ts
new file mode 100644
index 0000000..d173b79
--- /dev/null
+++ b/src/common/error/DaemonSettingsInvalidNetworkError.ts
@@ -0,0 +1,8 @@
+import { DaemonSettingsError } from "./DaemonSettingsError";
+
+export class DaemonSettingsInvalidNetworkError extends DaemonSettingsError {
+
+ constructor() {
+ super("Invalid daemon network settings");
+ }
+}
\ No newline at end of file
diff --git a/src/common/error/DaemonSettingsInvalidValueError.ts b/src/common/error/DaemonSettingsInvalidValueError.ts
new file mode 100644
index 0000000..b40f541
--- /dev/null
+++ b/src/common/error/DaemonSettingsInvalidValueError.ts
@@ -0,0 +1,13 @@
+import { DaemonSettingsError } from "./DaemonSettingsError"
+
+export class DaemonSettingsInvalidValueError extends DaemonSettingsError {
+ public key: string;
+ public value: string;
+
+ constructor(key: string, value: string) {
+ super(`Invalid value ${value} for daemon setting ${key}`);
+
+ this.key = key;
+ this.value = value;
+ }
+}
\ No newline at end of file
diff --git a/src/common/error/DaemonSettingsUnknownKeyError.ts b/src/common/error/DaemonSettingsUnknownKeyError.ts
new file mode 100644
index 0000000..5a5326c
--- /dev/null
+++ b/src/common/error/DaemonSettingsUnknownKeyError.ts
@@ -0,0 +1,11 @@
+import { DaemonSettingsError } from "./DaemonSettingsError"
+
+export class DaemonSettingsUnknownKeyError extends DaemonSettingsError {
+ public key: string;
+
+ constructor(key: string) {
+ super(`Unknown daemon setting ${key}`);
+
+ this.key = key;
+ }
+}
\ No newline at end of file
diff --git a/src/common/error/index.ts b/src/common/error/index.ts
index 1b16e8a..64ce507 100644
--- a/src/common/error/index.ts
+++ b/src/common/error/index.ts
@@ -1,3 +1,10 @@
export { RpcError } from "./RpcError";
export { CoreIsBusyError } from "./CoreIsBusyError";
+export { DaemonSettingsError } from "./DaemonSettingsError";
+export { DaemonSettingsInvalidNetworkError } from "./DaemonSettingsInvalidNetworkError";
+export { DaemonSettingsInvalidValueError } from "./DaemonSettingsInvalidValueError";
+export { DaemonSettingsUnknownKeyError } from "./DaemonSettingsUnknownKeyError";
+export { DaemonSettingsDuplicateNodeError } from "./DaemonSettingsDuplicateNodeError";
+export { DaemonSettingsDuplicateExclusiveNodeError } from "./DaemonSettingsDuplicateExclusiveNodeError";
+export { DaemonSettingsDuplicatePriorityNodeError } from "./DaemonSettingsDuplicatePriorityNodeError";
export { MethodNotFoundError } from "./MethodNotFoundError";
diff --git a/src/polyfills.ts b/src/polyfills.ts
index c3ddc57..770a39e 100644
--- a/src/polyfills.ts
+++ b/src/polyfills.ts
@@ -87,6 +87,7 @@ declare global {
onDownloadProgress: (callback: (event: any, progress: { progress: number, status: string }) => void) => void;
checkValidMonerodPath: (path: string) => void;
onCheckValidMonerodPath: (callback: (event: any, valid: boolean) => void) => void;
+ unregisterOnCheckValidMonerodPath: () => void;
unsubscribeOnMonerodStarted: () => void;
onMoneroClose: (callback: (event: any, code: number) => void) => void;
onMoneroStdout: (callbak: (event: any, out: string) => void) => void;
@@ -120,9 +121,9 @@ declare global {
showNotification: (options: NotificationConstructorOptions) => void;
quit: () => void;
- isAppImage: () => void;
- onIsAppImage: (callback: (event: any, value: boolean) => void) => void;
- unregisterOnIsAppImage: () => void;
+ isPortable: () => void;
+ onIsPortable: (callback: (event: any, value: boolean) => void) => void;
+ unregisterIsPortable: () => void;
isAutoLaunchEnabled: () => void;
onIsAutoLaunchEnabled: (callback: (event: any, enabled: boolean) => void) => void;
@@ -161,6 +162,14 @@ declare global {
unregisterOnIsOnBatteryPower: () => void;
onBattery: (callback: (event: any) => void) => void;
onAc: (callback: (event: any) => void) => void;
+
+ downloadFile: (url: string, destination: string) => void;
+ onDownloadFileProgress: (callback: (event: any, info: { progress: number, status: string }) => void) => void;
+ onDownloadFileError: (callback: (event: any, error: string) => void) => void;
+ onDownloadFileComplete: (callback: (event: any, fileName: string) => void) => void;
+ unregisterOnDownloadFile: () => void;
+
+ showErrorBox: (title: string, content: string) => void;
};
}
}
\ No newline at end of file
diff --git a/src/styles.scss b/src/styles.scss
index fbf7912..4526ac5 100644
--- a/src/styles.scss
+++ b/src/styles.scss
@@ -9,6 +9,11 @@ $primary: #ff5733;
height: 1rem;
}
+.tab-grow {
+ overflow: hidden;
+ overflow-y: auto;
+}
+
/*
* Sidebar
*/