mirror of https://github.com/laurent22/joplin.git
Plugins: Allow custom commands to return a result
parent
60a6f714bc
commit
5d39860707
|
@ -21,8 +21,12 @@ export interface PluginMessage {
|
|||
args?: any[],
|
||||
result?: any,
|
||||
error?: any,
|
||||
mainWindowCallbackId?: string,
|
||||
}
|
||||
|
||||
let callbackIndex = 1;
|
||||
const callbackPromises:any = {};
|
||||
|
||||
function mapEventIdsToHandlers(pluginId:string, arg:any) {
|
||||
if (Array.isArray(arg)) {
|
||||
for (let i = 0; i < arg.length; i++) {
|
||||
|
@ -33,12 +37,21 @@ function mapEventIdsToHandlers(pluginId:string, arg:any) {
|
|||
const eventId = arg;
|
||||
|
||||
return async (...args:any[]) => {
|
||||
const callbackId = `cb_${pluginId}_${Date.now()}_${callbackIndex++}`;
|
||||
|
||||
const promise = new Promise((resolve, reject) => {
|
||||
callbackPromises[callbackId] = { resolve, reject };
|
||||
});
|
||||
|
||||
ipcRenderer.send('pluginMessage', {
|
||||
callbackId: callbackId,
|
||||
target: PluginMessageTarget.Plugin,
|
||||
pluginId: pluginId,
|
||||
eventId: eventId,
|
||||
args: args,
|
||||
});
|
||||
|
||||
return promise;
|
||||
};
|
||||
} else if (arg === null) {
|
||||
return null;
|
||||
|
@ -95,26 +108,41 @@ export default class PluginRunner extends BasePluginRunner {
|
|||
if (message.target !== PluginMessageTarget.MainWindow) return;
|
||||
if (message.pluginId !== plugin.id) return;
|
||||
|
||||
const mappedArgs = mapEventIdsToHandlers(plugin.id, message.args);
|
||||
const fullPath = `joplin.${message.path}`;
|
||||
if (message.mainWindowCallbackId) {
|
||||
const promise = callbackPromises[message.mainWindowCallbackId];
|
||||
|
||||
this.logger().debug(`PluginRunner: execute call: ${fullPath}: ${mappedArgs}`);
|
||||
if (!promise) {
|
||||
console.error('Got a callback without matching promise: ', message);
|
||||
return;
|
||||
}
|
||||
|
||||
let result:any = null;
|
||||
let error:any = null;
|
||||
try {
|
||||
result = await executeSandboxCall(plugin.id, pluginApi, fullPath, mappedArgs, this.eventHandler);
|
||||
} catch (e) {
|
||||
error = e ? e : new Error('Unknown error');
|
||||
if (message.error) {
|
||||
promise.reject(message.error);
|
||||
} else {
|
||||
promise.resolve(message.result);
|
||||
}
|
||||
} else {
|
||||
const mappedArgs = mapEventIdsToHandlers(plugin.id, message.args);
|
||||
const fullPath = `joplin.${message.path}`;
|
||||
|
||||
this.logger().debug(`PluginRunner: execute call: ${fullPath}: ${mappedArgs}`);
|
||||
|
||||
let result:any = null;
|
||||
let error:any = null;
|
||||
try {
|
||||
result = await executeSandboxCall(plugin.id, pluginApi, fullPath, mappedArgs, this.eventHandler);
|
||||
} catch (e) {
|
||||
error = e ? e : new Error('Unknown error');
|
||||
}
|
||||
|
||||
ipcRenderer.send('pluginMessage', {
|
||||
target: PluginMessageTarget.Plugin,
|
||||
pluginId: plugin.id,
|
||||
pluginCallbackId: message.callbackId,
|
||||
result: result,
|
||||
error: error,
|
||||
});
|
||||
}
|
||||
|
||||
ipcRenderer.send('pluginMessage', {
|
||||
target: PluginMessageTarget.Plugin,
|
||||
pluginId: plugin.id,
|
||||
callbackId: message.callbackId,
|
||||
result: result,
|
||||
error: error,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -53,7 +53,7 @@
|
|||
return promise;
|
||||
};
|
||||
|
||||
ipcRenderer.on('pluginMessage', (event, message) => {
|
||||
ipcRenderer.on('pluginMessage', async (_event, message) => {
|
||||
if (message.eventId) {
|
||||
const eventHandler = eventHandlers_[message.eventId];
|
||||
|
||||
|
@ -62,12 +62,28 @@
|
|||
return;
|
||||
}
|
||||
|
||||
eventHandler(...message.args);
|
||||
let result = null;
|
||||
let error = null;
|
||||
try {
|
||||
result = await eventHandler(...message.args);
|
||||
} catch (e) {
|
||||
error = e;
|
||||
}
|
||||
|
||||
if (message.callbackId) {
|
||||
ipcRenderer.send('pluginMessage', {
|
||||
target: 'mainWindow',
|
||||
pluginId: pluginId,
|
||||
mainWindowCallbackId: message.callbackId,
|
||||
result: result,
|
||||
error: error,
|
||||
});
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (message.callbackId) {
|
||||
const promise = callbackPromises[message.callbackId];
|
||||
if (message.pluginCallbackId) {
|
||||
const promise = callbackPromises[message.pluginCallbackId];
|
||||
if (!promise) {
|
||||
console.error('Got a callback without matching promise: ', message);
|
||||
return;
|
||||
|
|
|
@ -203,7 +203,7 @@ export default class CommandService extends BaseService {
|
|||
delete command.runtime;
|
||||
}
|
||||
|
||||
public async execute(commandName:string, ...args:any[]):Promise<any> {
|
||||
public async execute(commandName:string, ...args:any[]):Promise<any | void> {
|
||||
const command = this.commandByName(commandName);
|
||||
this.logger().info('CommandService::execute:', commandName, args);
|
||||
return command.runtime.execute({ state: this.store_.getState() }, ...args);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import CommandService, { CommandDeclaration, CommandRuntime } from 'lib/services/CommandService';
|
||||
import CommandService, { CommandContext, CommandDeclaration, CommandRuntime } from 'lib/services/CommandService';
|
||||
import { Command } from './types';
|
||||
|
||||
/**
|
||||
|
@ -62,7 +62,9 @@ export default class JoplinCommands {
|
|||
if ('iconName' in command) declaration.iconName = command.iconName;
|
||||
|
||||
const runtime:CommandRuntime = {
|
||||
execute: command.execute,
|
||||
execute: (_context:CommandContext, ...args:any[]) => {
|
||||
return command.execute(...args);
|
||||
},
|
||||
};
|
||||
|
||||
if ('enabledCondition' in command) runtime.enabledCondition = command.enabledCondition;
|
||||
|
|
Loading…
Reference in New Issue