657 changes: 653 additions & 4 deletions ReactNativeClient/package-lock.json

Large diffs are not rendered by default.

5 changes: 5 additions & 0 deletions ReactNativeClient/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,17 @@
"color": "^3.1.2",
"diacritics": "^1.3.0",
"diff-match-patch": "^1.0.4",
"es6-promise-pool": "^2.5.0",
"events": "^1.1.1",
"file-uri-to-path": "^1.0.0",
"font-awesome-filetypes": "^2.1.0",
"form-data": "^2.1.4",
"highlight.js": "^10.2.1",
"html-entities": "^1.2.1",
"htmlparser2": "^4.1.0",
"immer": "^7.0.9",
"joplin-turndown": "^4.0.30",
"joplin-turndown-plugin-gfm": "^1.0.12",
"jsc-android": "241213.1.0",
"json-stringify-safe": "^5.0.1",
"katex": "^0.12.0",
Expand Down Expand Up @@ -85,6 +89,7 @@
"string-natural-compare": "^2.0.2",
"string-padding": "^1.0.2",
"timers": "^0.1.1",
"uglifycss": "0.0.29",
"url": "^0.11.0",
"url-parse": "^1.4.7",
"uslug": "git+https://github.com/laurent22/uslug.git#emoji-support",
Expand Down
1,526 changes: 719 additions & 807 deletions ReactNativeClient/root.js

Large diffs are not rendered by default.

127 changes: 127 additions & 0 deletions ReactNativeClient/services/plugins/PluginRunner.js
149 changes: 149 additions & 0 deletions ReactNativeClient/services/plugins/PluginRunner.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
import Plugin from 'lib/services/plugins/Plugin';
import BasePluginRunner from 'lib/services/plugins/BasePluginRunner';
import executeSandboxCall from 'lib/services/plugins/utils/executeSandboxCall';
import Global from 'lib/services/plugins/api/Global';
import Setting from 'lib/models/Setting';
import { EventHandlers } from 'lib/services/plugins/utils/mapEventHandlersToIds';
import shim from 'lib/shim';

enum PluginMessageTarget {
MainWindow = 'mainWindow',
Plugin = 'plugin',
}

export interface PluginMessage {
target: PluginMessageTarget,
pluginId: string,
callbackId?: string,
path?: string,
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++) {
arg[i] = mapEventIdsToHandlers(pluginId, arg[i]);
}
return arg;
} else if (typeof arg === 'string' && arg.indexOf('___plugin_event_') === 0) {
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;
} else if (arg === undefined) {
return undefined;
} else if (typeof arg === 'object') {
for (const n in arg) {
arg[n] = mapEventIdsToHandlers(pluginId, arg[n]);
}
}

return arg;
}

export default class PluginRunner extends BasePluginRunner {

protected eventHandlers_:EventHandlers = {};

constructor() {
super();

this.eventHandler = this.eventHandler.bind(this);
}

private async eventHandler(eventHandlerId:string, args:any[]) {
const cb = this.eventHandlers_[eventHandlerId];
return cb(...args);
}

async run(plugin:Plugin, _pluginApi:Global) {
console.info('RUNNING', plugin);

// const scriptPath = `${Setting.value('tempDir')}/plugin_${plugin.id}.js`;
// await shim.fsDriver().writeFile(scriptPath, plugin.scriptText, 'utf8');

// const pluginWindow = bridge().newBrowserWindow({
// show: false,
// webPreferences: {
// nodeIntegration: true,
// },
// });

// bridge().electronApp().registerPluginWindow(plugin.id, pluginWindow);

// pluginWindow.loadURL(`${require('url').format({
// pathname: require('path').join(__dirname, 'plugin_index.html'),
// protocol: 'file:',
// slashes: true,
// })}?pluginId=${encodeURIComponent(plugin.id)}&pluginScript=${encodeURIComponent(`file://${scriptPath}`)}`);

// pluginWindow.webContents.once('dom-ready', () => {
// pluginWindow.webContents.openDevTools();
// });

// ipcRenderer.on('pluginMessage', async (_event:any, message:PluginMessage) => {
// if (message.target !== PluginMessageTarget.MainWindow) return;
// if (message.pluginId !== plugin.id) return;

// if (message.mainWindowCallbackId) {
// const promise = callbackPromises[message.mainWindowCallbackId];

// if (!promise) {
// console.error('Got a callback without matching promise: ', message);
// return;
// }

// 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,
// });
// }
// });
}

}
5 changes: 0 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,6 @@
"clean": "gulp clean",
"postinstall": "cd Tools && npm i && cd .. && npm run clean && cd ReactNativeClient && npm i && cd .. && cd ElectronClient && npm i && cd .. && cd CliClient && npm i && cd .. && gulp build"
},
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
},
"repository": {
"type": "git",
"url": "git+https://github.com/laurent22/joplin.git"
Expand Down