Xzandro / sw-exporter

This tool will parse intercepted data from Summoners War and extract information on the monsters and runes of the user.
Apache License 2.0
414 stars 194 forks source link

[PLUGIN] Extending react code #349

Closed rheinertleon closed 3 years ago

rheinertleon commented 3 years ago

I am writing a plugin which evaluates all runes of a set of complex rules. Since I want these rules to be customizable; especially the weigths it would be nice to use the GUI for just that (the normal plugin configs are not suitable unfortunatly).

So my thought was to extend the react dom at the level of routers in View.js. Is there a way (maybe already) to add a router with a custom react-element which will also show up in the right navigation when initializing a plugin?

Such a possibility would also solve #279 I suppose.

rheinertleon commented 3 years ago

Any thoughts on this? I could make a PR where plugins may export a route which then will be passed to the react app.

Xzandro commented 3 years ago

It's always a tough decision to make how far plugins should be allowed to influence the main app. In perspective of potential malicious intents. My policy was that I would like it more if you have some kind of website and send the data you need to there and thus have complete freedom over the UI there. Or export a file and read it from another app.

rheinertleon commented 3 years ago

Interestingly I came from the opposite direction: I wanted to do an own website, but saw that syncing runes will be a pain (because I want to evaluate runes as they drop).

Nevertheless I understand your concerns. That's why I kept the extension as simple as possible with no influence on existing behavior. You can view the results on the two branches on my fork.

Branch plugin_routes - one route per plugin (suggested). Can be tested by adding the following code to the export of any plugin:

  route: {
    menuItemText: 'Menu Label',
    component: () => 'Hello from plugin export'
  }

Branch plugin_multiple_routes - one route per plugin. Can be tested by adding the following code to the export of any plugin:

  routes: [
    {
      path: '/test_path',
      name: 'Menu Label',
      component: () => 'Hello from plugin export'
    }
  ]

A side of the decision on whether plugins may have multiple routes there are other (minor) decisions to make:

rheinertleon commented 3 years ago

If only my simple example would have included a JSX-component like () => <div>Hello World</div> I would have noticed earlier that this does not work: For some reason such a return will not be accepted by react if it comes from remote.getGlobal. I have tested this behavior by setting a global var on () => require('react').createElement('div', null, 'Hello World'), reading it in View and rendering it by setting the component of any route on it. While this will result in some error like 'Uncaught Invariant Violation: Objects are not valid as a React child (found: object with keys {$$typeof, type, key, ref, props, _owner, _store})', defining the very same function in the file directly and using it as the component works perfectly fine.

Do you have any idea why this happens? This might be an easy fix, if one understands whats going on.

My alternative idea to load the plugin in View.js directly (or rather outsource the loadPlugins-function) leads to the warning 'Critical dependency: the request of a dependency is an expression'. Oddly this causes the entire app to just be blank.

rheinertleon commented 3 years ago

My guess is that by requiring the global variables over this getGlobal function, the objects are stripped down to an exchangable format, which does not allow a react element to really stay a react element but instead is a json, which react cant render.

rheinertleon commented 3 years ago

Seems like the alternative of importing the component of the plugins dynamically is not allowed by webpack: (source) Sadly this means my idea of extending the react code by plugins is impossible. Thus I will close this issue.