Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
wip
Browse files Browse the repository at this point in the history
yolossn committed May 3, 2024

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
1 parent 688fdf1 commit 48518cf
Showing 9 changed files with 1,354 additions and 1,159 deletions.
139 changes: 85 additions & 54 deletions app/electron/main.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import 'regenerator-runtime/runtime';
import { ChildProcess, ChildProcessWithoutNullStreams, execSync, fork, spawn } from 'child_process';
import { ChildProcessWithoutNullStreams, execSync, spawn } from 'child_process';
import { randomBytes } from 'crypto';
import dotenv from 'dotenv';
import { app, BrowserWindow, dialog, ipcMain, Menu, MenuItem, screen, shell } from 'electron';
@@ -11,6 +11,7 @@ import open from 'open';
import path from 'path';
import url from 'url';
import yargs from 'yargs';
import PluginManager from '../../plugins/headlamp-plugin/plugin-management';
import i18n from './i18next.config';
import windowSize from './windowSize';

@@ -498,6 +499,87 @@ function startElecron() {

console.log('Check for updates: ', shouldCheckForUpdates);

class PluginEventListeners {
private pluginManager: PluginManager;
private abortControllers: {};

constructor() {
this.pluginManager = new PluginManager();
this.abortControllers = {};
}

setupEventHandlers() {
ipcMain.on('install-plugin', (event, URL, destinationFolder, headlampVersion) => {
const controller = new AbortController();
const cancelSignal = controller.signal;
this.abortControllers[URL] = controller;

this.pluginManager.install(
URL,
destinationFolder,
headlampVersion,
progressData => {
if (cancelSignal.aborted) {
console.log('aborting install plugin', URL);
return;
}
event.sender.send('install-plugin-progress', progressData);
if (progressData.type === 'success' || progressData.type === 'error') {
delete this.abortControllers[URL];
}
},
cancelSignal
);
});

ipcMain.on('update-plugin', (event, pluginName, destinationFolder, headlampVersion) => {
const controller = new AbortController();
const cancelSignal = controller.signal;
this.abortControllers[pluginName] = controller;

console.log('in update plugin,', pluginName, destinationFolder, headlampVersion);

this.pluginManager.update(
pluginName,
destinationFolder,
headlampVersion,
progressData => {
if (cancelSignal.aborted) {
console.log('aborting update plugin', pluginName);
return;
}
event.sender.send('update-plugin-progress', progressData);
if (progressData.type === 'success' || progressData.type === 'error') {
delete this.abortControllers[pluginName];
}
},
cancelSignal
);
});

ipcMain.on('uninstall-plugin', (event, pluginName) => {
this.pluginManager.uninstall(pluginName, undefined, progressData => {
event.sender.send('uninstall-plugin-progress', progressData);
});
});

ipcMain.on('list-plugins', (event, folder) => {
this.pluginManager.list(folder, progressData => {
event.sender.send('list-plugins', progressData);
});
});

ipcMain.on('cancel-plugin-process', (event, identifier) => {
console.log('got cancel request', identifier, this.abortControllers);
if (this.abortControllers[identifier]) {
const controller = this.abortControllers[identifier];
controller.abort();
delete this.abortControllers[identifier];
}
});
}
}

async function createWindow() {
let frontendPath = '';
if (isDev) {
@@ -647,6 +729,8 @@ function startElecron() {
}
});

new PluginEventListeners().setupEventHandlers();

/**
* Data sent from the renderer process when a 'run-command' event is emitted.
*/
@@ -707,59 +791,6 @@ function startElecron() {

ipcMain.on('run-command', handleRunCommand);

/**
* Represents the arguments for a plugin command.
*/
interface PluginCommandArgs {
id: string;
command: string;
args: string[];
}

/**
* Handles a plugin commands from the renderer process.
*
* Forks the current electron process to run the plugin command and sends
* 'plugin-command-stdout', 'plugin-command-stderr', and 'plugin-command-exit'
* events back to the renderer process with the plugin command's output and exit code.
*
*
* @param {IpcMainEvent} event - The IPC event object representing the incoming command.
* @param {PluginCommandArgs} data - The data containing plugin command details.
* @returns {void}
*/
function handlePluginCommand(event: IpcMainEvent, data: PluginCommandArgs) {
const { id, command, args } = data;

const includesJFlag = args.includes('-j');
const argsWithJFlag = includesJFlag ? args : [...args, '-j'];

const child: ChildProcess = fork('plugin-management.js', [command, ...argsWithJFlag], {
env: {
ELECTRON_RUN_AS_NODE: '1',
},
silent: true,
});

if (child.stdout !== null) {
child.stdout.on('data', (data: string | Buffer) => {
event.sender.send('plugin-command-stdout', id, data.toString());
});
}

if (child.stderr !== null) {
child.stderr.on('data', (data: string | Buffer) => {
event.sender.send('plugin-command-stderr', id, data.toString());
});
}

child.on('exit', (code: number | null) => {
event.sender.send('plugin-command-exit', id, code);
});
}

ipcMain.on('plugin-command', handlePluginCommand);

if (!useExternalServer) {
const runningHeadlamp = await getRunningHeadlampPIDs();
let shouldWaitForKill = true;
9 changes: 9 additions & 0 deletions app/electron/preload.ts
Original file line number Diff line number Diff line change
@@ -12,6 +12,11 @@ contextBridge.exposeInMainWorld('desktopApi', {
'pluginsLoaded',
'run-command',
'plugin-command',
'install-plugin',
'update-plugin',
'uninstall-plugin',
'list-plugins',
'cancel-plugin-process',
];
if (validChannels.includes(channel)) {
ipcRenderer.send(channel, data);
@@ -29,6 +34,10 @@ contextBridge.exposeInMainWorld('desktopApi', {
'plugin-command-stdout',
'plugin-command-stderr',
'plugin-command-exit',
'install-plugin-progress',
'update-plugin-progress',
'uninstall-plugin-progress',
'list-plugins',
];
if (validChannels.includes(channel)) {
// Deliberately strip event as it includes `sender`
38 changes: 38 additions & 0 deletions frontend/src/components/App/runCommand.ts
Original file line number Diff line number Diff line change
@@ -160,3 +160,41 @@ export function runPluginCommand(
},
};
}

export class PluginManagerWrapper {
static install(URL: string, progressCallback: (progress: {}) => void) {
window.desktopApi.send('install-plugin', URL);

window.desktopApi.receive(`install-plugin-progress`, (progress: {}) => {
progressCallback(progress);
});
}

static update(name: string, progressCallback: (progress: {}) => void) {
window.desktopApi.send('update-plugin', name);

window.desktopApi.receive(`update-plugin-progress`, (progress: {}) => {
progressCallback(progress);
});
}

static uninstall(name: string, progressCallback: (progress: {}) => void) {
window.desktopApi.send('uninstall-plugin', name, undefined);

window.desktopApi.receive(`uninstall-plugin-progress`, (progress: {}) => {
progressCallback(progress);
});
}

static list(progressCallback: (progress: {}) => void) {
window.desktopApi.send('list-plugins');

window.desktopApi.receive(`list-plugins`, (progress: {}) => {
progressCallback(progress);
});
}

static cancel(identifier: string) {
window.desktopApi.send('cancel-plugin-process', identifier);
}
}
4 changes: 2 additions & 2 deletions frontend/src/plugin/registry.tsx
Original file line number Diff line number Diff line change
@@ -2,7 +2,7 @@ import { has } from 'lodash';
import React from 'react';
import { AppLogoProps, AppLogoType } from '../components/App/AppLogo';
import { runCommand } from '../components/App/runCommand';
import { runPluginCommand } from '../components/App/runCommand';
import { PluginManagerWrapper } from '../components/App/runCommand';
import { setBrandingAppLogoComponent } from '../components/App/themeSlice';
import { ClusterChooserProps, ClusterChooserType } from '../components/cluster/ClusterChooser';
import {
@@ -686,5 +686,5 @@ export {
DefaultDetailsViewSection,
getHeadlampAPIHeaders,
runCommand,
runPluginCommand,
PluginManagerWrapper,
};
Loading

0 comments on commit 48518cf

Please sign in to comment.