mirror of
https://github.com/quine-global/hyper.git
synced 2026-01-13 04:28:41 -09:00
improve decoration with persistent state with react-proxy
This commit is contained in:
parent
d74f8ac1dc
commit
4d99089afb
4 changed files with 96 additions and 22 deletions
|
|
@ -1,10 +1,15 @@
|
|||
import Tabs from './tabs';
|
||||
import Term from './term';
|
||||
import Tabs_ from './tabs';
|
||||
import Term_ from './term';
|
||||
import RPC from './rpc';
|
||||
import Mousetrap from 'mousetrap';
|
||||
import classes from 'classnames';
|
||||
import shallowCompare from 'react-addons-shallow-compare';
|
||||
import React, { Component } from 'react';
|
||||
import decorate from './plugins';
|
||||
|
||||
// make subcomponents reload siwth plugin changes
|
||||
const Tabs = decorate(Tabs_);
|
||||
const Term = decorate(Term_);
|
||||
|
||||
export default class HyperTerm extends Component {
|
||||
constructor (props) {
|
||||
|
|
|
|||
14
app/index.js
14
app/index.js
|
|
@ -1,16 +1,14 @@
|
|||
import { render } from 'react-dom';
|
||||
import HyperTerm from './hyperterm';
|
||||
import HyperTerm_ from './hyperterm';
|
||||
import React from 'react';
|
||||
import Config from './config';
|
||||
import Plugins from './plugins';
|
||||
import decorate from './plugins';
|
||||
|
||||
// make the component reload with plugin changes
|
||||
const HyperTerm = decorate(HyperTerm_);
|
||||
|
||||
require('./css/hyperterm.css');
|
||||
require('./css/tabs.css');
|
||||
|
||||
const app = <Config>
|
||||
<Plugins>
|
||||
<HyperTerm />
|
||||
</Plugins>
|
||||
</Config>;
|
||||
|
||||
const app = <Config><HyperTerm /></Config>;
|
||||
render(app, document.getElementById('mount'));
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
"react": "15.1.0",
|
||||
"react-addons-shallow-compare": "15.1.0",
|
||||
"react-dom": "15.1.0",
|
||||
"react-proxy": "1.1.8",
|
||||
"semver-compare": "1.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
|
|
|||
|
|
@ -1,18 +1,88 @@
|
|||
import React from 'react';
|
||||
import { ipcRenderer, remote } from 'electron';
|
||||
import notify from './notify';
|
||||
import { createProxy } from 'react-proxy';
|
||||
|
||||
export default class Plugins extends React.Component {
|
||||
// remote interface to `../plugins`
|
||||
let plugins = remote.require('./plugins');
|
||||
|
||||
componentDidMount () {
|
||||
|
||||
}
|
||||
|
||||
render () {
|
||||
const child = React.Children.only(this.props.children);
|
||||
return React.cloneElement(child, this.props);
|
||||
}
|
||||
|
||||
componentWillUnmount () {
|
||||
// `require`d modules
|
||||
let modules;
|
||||
|
||||
// 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];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
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);
|
||||
}
|
||||
};
|
||||
|
||||
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();
|
||||
});
|
||||
|
||||
export default function decorate (Component, props = null) {
|
||||
const name = Component.name;
|
||||
|
||||
if (!proxies[name]) {
|
||||
const proxy = createProxy(Component);
|
||||
proxies[name] = [Component, proxy];
|
||||
updateProxy(name);
|
||||
}
|
||||
|
||||
const [, proxy] = proxies[name];
|
||||
return proxy.get();
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue