2016-07-08 13:26:23 -08:00
|
|
|
import { ipcRenderer, remote } from 'electron';
|
|
|
|
|
import notify from './notify';
|
|
|
|
|
import { createProxy } from 'react-proxy';
|
2016-07-07 16:16:44 -08:00
|
|
|
|
2016-07-08 13:26:23 -08:00
|
|
|
// remote interface to `../plugins`
|
|
|
|
|
let plugins = remote.require('./plugins');
|
2016-07-07 16:16:44 -08:00
|
|
|
|
2016-07-08 13:26:23 -08:00
|
|
|
// `require`d modules
|
|
|
|
|
let modules;
|
2016-07-07 16:16:44 -08:00
|
|
|
|
2016-07-08 13:26:23 -08:00
|
|
|
// the fs locations where usr plugins are stored
|
|
|
|
|
const { path, localPath } = plugins.getBasePaths();
|
|
|
|
|
|
|
|
|
|
// where we store the decorated components
|
|
|
|
|
let proxies = {};
|
|
|
|
|
|
|
|
|
|
const clearCache = () => {
|
|
|
|
|
// clear require cache
|
|
|
|
|
for (const entry in window.require.cache) {
|
|
|
|
|
if (entry.indexOf(path) === 0 || entry.indexOf(localPath) === 0) {
|
|
|
|
|
// `require` is webpacks', `window.require`, electron's
|
|
|
|
|
delete window.require.cache[entry];
|
|
|
|
|
}
|
2016-07-07 16:16:44 -08:00
|
|
|
}
|
2016-07-08 13:26:23 -08:00
|
|
|
};
|
2016-07-07 16:16:44 -08:00
|
|
|
|
2016-07-08 13:26:23 -08:00
|
|
|
const loadModules = () => {
|
|
|
|
|
console.log('(re)loading renderer plugins');
|
|
|
|
|
const paths = plugins.getPaths();
|
|
|
|
|
modules = paths.plugins.concat(paths.localPlugins).map((path) => {
|
|
|
|
|
// window.require allows us to ensure this doens't get
|
|
|
|
|
// in the way of our build
|
|
|
|
|
try {
|
|
|
|
|
return window.require(path);
|
|
|
|
|
} catch (err) {
|
|
|
|
|
const name = remote.require('path').basename(path);
|
|
|
|
|
console.error(err.stack);
|
|
|
|
|
notify('Plugin load error', `"${name}" failed to load in the renderer process. Check Developer Tools for details.`);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const updateProxy = (name) => {
|
|
|
|
|
const [Component, proxy] = proxies[name];
|
|
|
|
|
let decorated = Component;
|
|
|
|
|
modules.forEach((mod) => {
|
|
|
|
|
const decorator = mod[`decorate${name}`];
|
|
|
|
|
if (decorator) {
|
|
|
|
|
console.log('decorating', name);
|
|
|
|
|
decorated = decorator(Component, __webpack_require__);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
if (decorated !== Component) {
|
|
|
|
|
proxy.update(decorated);
|
2016-07-07 16:16:44 -08:00
|
|
|
}
|
2016-07-08 13:26:23 -08:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const updateProxies = () => {
|
|
|
|
|
for (const name in proxies) {
|
|
|
|
|
updateProxy(name);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// load modules for initial decoration
|
|
|
|
|
loadModules();
|
|
|
|
|
|
|
|
|
|
// we want to refresh our modules cache every time
|
|
|
|
|
// plugins reload.
|
|
|
|
|
// the re-painting happens by the top-level `Config` component
|
|
|
|
|
// that reacts to configuration changes and plugin changes
|
|
|
|
|
ipcRenderer.on('plugins change', () => {
|
|
|
|
|
clearCache();
|
|
|
|
|
loadModules();
|
|
|
|
|
updateProxies();
|
|
|
|
|
});
|
2016-07-07 16:16:44 -08:00
|
|
|
|
2016-07-08 13:26:23 -08:00
|
|
|
export default function decorate (Component, props = null) {
|
|
|
|
|
const name = Component.name;
|
2016-07-07 16:16:44 -08:00
|
|
|
|
2016-07-08 13:26:23 -08:00
|
|
|
if (!proxies[name]) {
|
|
|
|
|
const proxy = createProxy(Component);
|
|
|
|
|
proxies[name] = [Component, proxy];
|
|
|
|
|
updateProxy(name);
|
2016-07-07 16:16:44 -08:00
|
|
|
}
|
|
|
|
|
|
2016-07-08 13:26:23 -08:00
|
|
|
const [, proxy] = proxies[name];
|
|
|
|
|
return proxy.get();
|
2016-07-07 16:16:44 -08:00
|
|
|
}
|