From 16320b92a58a0de2b3815053ba0bc6724271c5bd Mon Sep 17 00:00:00 2001 From: IDCs Date: Tue, 14 Jan 2025 08:57:16 +0000 Subject: [PATCH 1/2] Adding ability to import and install archives via cmdline closes nexus-mods/vortex#16896 --- src/extensions/download_management/index.ts | 10 +++++++++- src/util/commandLine.ts | 4 ++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/extensions/download_management/index.ts b/src/extensions/download_management/index.ts index 906903d18..71737b123 100644 --- a/src/extensions/download_management/index.ts +++ b/src/extensions/download_management/index.ts @@ -811,10 +811,18 @@ function processCommandline(api: IExtensionApi) { const { commandLine } = state.session.base; const cliUrl = commandLine.download ?? commandLine.install; - if (cliUrl) { api.events.emit('start-download-url', cliUrl, undefined, commandLine.install !== undefined); } + + const arcPath = commandLine.installArchive; + if (typeof arcPath === 'string' && path.isAbsolute(arcPath)) { + api.events.emit('import-downloads', [arcPath], (dlIds: string[]) => { + dlIds.forEach(dlId => { + api.events.emit('start-install-download', dlId); + }); + }); + } } function init(context: IExtensionContextExt): boolean { diff --git a/src/util/commandLine.ts b/src/util/commandLine.ts index 1d19b2582..adb60c976 100644 --- a/src/util/commandLine.ts +++ b/src/util/commandLine.ts @@ -10,6 +10,7 @@ import startupSettings from './startupSettings'; export interface IParameters { download?: string; install?: string; + installArchive?: string; installExtension?: string; report?: string; restore?: string; @@ -50,6 +51,7 @@ const ARG_COUNTS = { '-s': 1, '--download': 1, '--install': 1, + '--install-archive': 1, '--install-extension': 1, '--start-minimized': 1, '--game': 1, @@ -168,6 +170,7 @@ function parseCommandline(argv: string[], electronIsShitHack: boolean): IParamet + '(any supported protocol like nxm:, https:, ...).') .option('-i, --install ', 'Start downloadling & installing the specified url ' + '(any supported protocol like nxm:, https:, ...).') + .option('--install-archive ', 'Start installing the specified archive. Use absolute path.') .option('--install-extension ', 'Start downloadling & installing the specified ' + 'vortex extension. id can be "modId:".') .option('-g, --get ', 'Print the state variable at the specified path and quit. ' @@ -222,6 +225,7 @@ const SKIP_ARGS = { '--game': 1, '--profile': 1, '--install': 1, + '--install-archive': 1, '--install-extension': 1, '--restore': 1, '--merge': 1, From c66c6591e19979f40f9d7182350efbe17441247c Mon Sep 17 00:00:00 2001 From: IDCs Date: Tue, 14 Jan 2025 09:17:33 +0000 Subject: [PATCH 2/2] support archive installation arguments from other vortex instances --- src/app/Application.ts | 10 +++++++--- src/app/MainWindow.ts | 10 ++++++++++ src/renderer.tsx | 25 +++++++++++++++++++++---- 3 files changed, 38 insertions(+), 7 deletions(-) diff --git a/src/app/Application.ts b/src/app/Application.ts index a4e247862..6d0cd6ef0 100644 --- a/src/app/Application.ts +++ b/src/app/Application.ts @@ -1098,7 +1098,7 @@ class Application { } private applyArguments(args: IParameters) { - if (args.download || args.install) { + if (args.download || args.install || args.installArchive) { const prom: Promise = (this.mMainWindow === undefined) // give the main instance a moment to fully start up ? Promise.delay(2000) @@ -1106,8 +1106,12 @@ class Application { prom.then(() => { if (this.mMainWindow !== undefined) { - this.mMainWindow.sendExternalURL(args.download || args.install, - args.install !== undefined); + if (args.download || args.install) { + this.mMainWindow.sendExternalURL(args.download || args.install, args.install !== undefined); + } + if (args.installArchive) { + this.mMainWindow.installModFromArchive(args.installArchive); + } } else { // TODO: this instructions aren't very correct because we know Vortex doesn't have // a UI and needs to be shut down from the task manager diff --git a/src/app/MainWindow.ts b/src/app/MainWindow.ts index 6912dc916..8e23fbccc 100644 --- a/src/app/MainWindow.ts +++ b/src/app/MainWindow.ts @@ -272,6 +272,16 @@ class MainWindow { } } + public installModFromArchive(archivePath: string) { + if (this.mWindow != null) { + try { + this.mWindow.webContents.send('install-archive', archivePath); + } catch (err) { + log('error', 'failed to send install-archive', { archivePath, error: err.message }); + } + } + } + public getHandle(): Electron.BrowserWindow { return this.mWindow; } diff --git a/src/renderer.tsx b/src/renderer.tsx index 2a6eb88d7..2461e1a07 100644 --- a/src/renderer.tsx +++ b/src/renderer.tsx @@ -1,6 +1,4 @@ -/** - * entry point for the renderer process(es) - */ +/* eslint-disable */ if (process.env.DEBUG_REACT_RENDERS === 'true') { // eslint-disable-next-line @typescript-eslint/no-var-requires @@ -518,9 +516,22 @@ function init() { const startupPromise = new Promise(resolve => (startupFinished = resolve)); + const api = extensions.getApi(); // tslint:disable-next-line:no-unused-variable - const globalNotifications = new GlobalNotifications(extensions.getApi()); + const globalNotifications = new GlobalNotifications(api); + function startinstallFromArchive(filePath: string) { + startupPromise.then(() => { + if (typeof filePath !== 'string' || !path.isAbsolute(filePath)) { + return; + } + api.events.emit('import-downloads', [filePath], (dlIds: string[]) => { + dlIds.forEach(dlId => { + api.events.emit('start-install-download', dlId); + }); + }); + }); + } function startDownloadFromURL(url: string, fileName?: string, install?: boolean) { startupPromise.then(() => { if (typeof url !== 'string') { @@ -558,6 +569,12 @@ function init() { }, ); + ipcRenderer.on( + 'install-archive', + (event, filePath: string) => { + startinstallFromArchive(filePath); + }); + ipcRenderer.on('relay-event', (sender, event, ...args) => { eventEmitter.emit(event, ...args); });