From 218bb492689c89851e203bb3d978db249a018c59 Mon Sep 17 00:00:00 2001 From: argenius Date: Tue, 11 Feb 2025 19:03:39 +0100 Subject: [PATCH] I2pdProcess partial implementation --- app/main.ts | 9 ++++- app/preload.js | 15 ++++++++ app/process/I2pdProcess.ts | 8 ++++ app/process/index.ts | 3 +- .../core/services/daemon/daemon.service.ts | 14 +++++++ .../pages/settings/settings.component.html | 36 +++++++++++++++++- src/app/pages/settings/settings.component.ts | 37 +++++++++++++++++++ src/common/DaemonSettings.ts | 1 + src/polyfills.ts | 2 +- 9 files changed, 120 insertions(+), 5 deletions(-) create mode 100644 app/process/I2pdProcess.ts diff --git a/app/main.ts b/app/main.ts index f2af560..9205ed6 100644 --- a/app/main.ts +++ b/app/main.ts @@ -9,7 +9,7 @@ import * as path from 'path'; import * as fs from 'fs'; import * as os from 'os'; import axios, { AxiosRequestConfig } from 'axios'; -import { AppMainProcess, MonerodProcess, PrivateTestnet } from './process'; +import { AppMainProcess, I2pdProcess, MonerodProcess, PrivateTestnet } from './process'; import { BatteryUtils, FileUtils, NetworkUtils } from './utils'; app.setName('Monero Daemon'); @@ -772,7 +772,12 @@ try { ipcMain.handle('check-valid-monerod-path', (event: IpcMainInvokeEvent, path: string) => { checkValidMonerodPath(path); - }) + }); + + ipcMain.handle('check-valid-i2pd-path', async (event: IpcMainInvokeEvent, params: { eventId: string, path: string }) => { + const { eventId, path } = params; + win?.webContents.send(eventId, await I2pdProcess.isValidPath(path)); + }); ipcMain.handle('show-notification', (event: IpcMainInvokeEvent, options?: NotificationConstructorOptions) => { showNotification(options); diff --git a/app/preload.js b/app/preload.js index f0e34f7..d2aa134 100644 --- a/app/preload.js +++ b/app/preload.js @@ -1,7 +1,22 @@ // preload.js const { contextBridge, ipcRenderer } = require('electron'); +function newId() { + return parseInt(`${Math.random()*1000}`); +} + contextBridge.exposeInMainWorld('electronAPI', { + checkValidI2pdPath: (path, callback) => { + const eventId = `on-check-valid-i2pd-path-${newId()}`; + + const handler = (event, result) => { + ipcRenderer.off(eventId, handler); + callback(result); + }; + + ipcRenderer.on(eventId, handler); + ipcRenderer.invoke('check-valid-i2pd-path', { eventId, path }); + }, httpPost: (params, callback) => { const { id } = params; diff --git a/app/process/I2pdProcess.ts b/app/process/I2pdProcess.ts new file mode 100644 index 0000000..1f90fd2 --- /dev/null +++ b/app/process/I2pdProcess.ts @@ -0,0 +1,8 @@ +import { AppChildProcess } from "./AppChildProcess"; + +export class I2pdProcess extends AppChildProcess { + + public static async isValidPath(path: string): Promise { + return false; + } +} \ No newline at end of file diff --git a/app/process/index.ts b/app/process/index.ts index fbe4102..584b507 100644 --- a/app/process/index.ts +++ b/app/process/index.ts @@ -2,4 +2,5 @@ export { AppMainProcess } from "./AppMainProcess"; export { ProcessStats } from "./ProcessStats"; export { AppChildProcess } from "./AppChildProcess"; export { MonerodProcess } from "./MonerodProcess"; -export { PrivateTestnet } from "./PrivateTestnet"; \ No newline at end of file +export { PrivateTestnet } from "./PrivateTestnet"; +export { I2pdProcess } from "./I2pdProcess"; \ No newline at end of file diff --git a/src/app/core/services/daemon/daemon.service.ts b/src/app/core/services/daemon/daemon.service.ts index ec14277..785c09c 100644 --- a/src/app/core/services/daemon/daemon.service.ts +++ b/src/app/core/services/daemon/daemon.service.ts @@ -251,6 +251,20 @@ export class DaemonService { return await checkPromise; } + + public async checkValidI2pdPath(path: string): Promise { + if (path == null || path == undefined || path.replace(' ', '') == '') { + return false; + } + + const checkPromise = new Promise((resolve) => { + window.electronAPI.checkValidI2pdPath(path, resolve); + }); + + return await checkPromise; + } + + public async getSettings(): Promise { const db = await this.openDbPromise; const result = await db.get(this.storeName, 1); diff --git a/src/app/pages/settings/settings.component.html b/src/app/pages/settings/settings.component.html index 1318e13..d4b2ce0 100644 --- a/src/app/pages/settings/settings.component.html +++ b/src/app/pages/settings/settings.component.html @@ -1092,7 +1092,41 @@

TOR Anonymous Inbound

- +

I2pd

+ +
+ +
+ + + +
+ Path to i2pd executable +
+ +
+

Config file

+ +
+ +
+ +
+ +
+ Import custom i2pd config file +
+ +
+ +
+ +
+ Export current saved i2pd settings to config file +
+ +
+

I2P Tx Proxy

diff --git a/src/app/pages/settings/settings.component.ts b/src/app/pages/settings/settings.component.ts index ec35b9b..ded2249 100644 --- a/src/app/pages/settings/settings.component.ts +++ b/src/app/pages/settings/settings.component.ts @@ -735,6 +735,22 @@ export class SettingsComponent extends BasePageComponent implements AfterViewIni throw new Error("Could not get monerod mime type"); } + private async getI2pdFileSpec(): Promise<{ extensions?: string[]; mimeType: string; }> { + const { platform } = await this.electronService.getOsType(); + + if (platform == 'win32') { + return { mimeType: 'application/vnd.microsoft.portable-executable', extensions: ['exe']}; + } + else if (platform == 'darwin') { + return { mimeType: 'application/octet-stream' }; + } + else if (platform == 'linux') { + return { mimeType: 'application/x-executable'}; + } + + throw new Error("Could not get i2pd mime type"); + } + public async importMonerodConfigFile(): Promise { try { try { @@ -827,6 +843,27 @@ export class SettingsComponent extends BasePageComponent implements AfterViewIni } } + public async chooseI2pdFile(): Promise { + const spec = await this.getI2pdFileSpec(); + const file = await this.electronService.selectFile(spec.extensions); + + if (file == '') { + return; + } + + const valid = await this.daemonService.checkValidI2pdPath(file); + if (valid) { + this.ngZone.run(() => { + const currentSettings = this.currentSettings; + if (currentSettings instanceof PrivnetDaemonSettings) return; + else currentSettings.i2pdPath = file; + }); + } + else { + window.electronAPI.showErrorBox('Invalid i2pd path', `Invalid i2pd path provided: ${file}`); + } + } + public async chooseBanListFile(): Promise { const file = await this.electronService.selectFile(['txt']); diff --git a/src/common/DaemonSettings.ts b/src/common/DaemonSettings.ts index 7a85615..1b30811 100644 --- a/src/common/DaemonSettings.ts +++ b/src/common/DaemonSettings.ts @@ -2,6 +2,7 @@ import { DaemonSettingsDuplicateExclusiveNodeError, DaemonSettingsDuplicatePrior export class DaemonSettings { public monerodPath: string = ''; + public i2pdPath: string = ''; public startAtLogin: boolean = false; public startAtLoginMinimized: boolean = false; diff --git a/src/polyfills.ts b/src/polyfills.ts index 7a621bb..63f4c6e 100644 --- a/src/polyfills.ts +++ b/src/polyfills.ts @@ -95,7 +95,7 @@ declare global { onMoneroClose: (callback: (event: any, code: number) => void) => void; onMoneroStdout: (callbak: (event: any, out: string) => void) => void; unregisterOnMoneroStdout: () => void; - + checkValidI2pdPath: (path: string, callback: (valid: boolean) => void) => void; isWifiConnected: () => void; onIsWifiConnectedResponse: (callback: (event: any, connected: boolean) => void) => void; unregisterOnIsWifiConnectedResponse: () => void;