Giter Club home page Giter Club logo

react-juce's Introduction

React-JUCE

Write cross-platform native apps with React.js and JUCE

React-JUCE (formerly named Blueprint) is a hybrid JavaScript/C++ framework that enables a React.js frontend for a JUCE application or plugin. It provides an embedded, ES5 JavaScript engine via Duktape, native hooks for rendering the React component tree to juce::Component instances, and a flexbox layout engine via Yoga.

For more information, see the introductory blog post here: Blueprint: A JUCE Rendering Backend for React.js

Status

Approaching Beta. We hope to announce a beta release in the coming weeks, after which we will aim our focus at stability and completeness on the path to a 1.0 release.

Anticipated Breaking Changes

  • We'll be renaming Blueprint to react-juce before beta (#34)
  • Updating the examples and npm init template to point to npm instead of the local package
  • ReactApplicationRoot::evaluate and ReactApplicationRoot::evaluateFile (#115)
  • Refactoring the hot reloader and decoupling the EcmascriptEngine from ReactApplicationRoot (#65)

Resources

Maintainers

Examples

React-JUCE is a young project, but already it provides the framework on which the entire user interface for Creative Intent's Remnant plugin is built.

Creative Intent Remnant: Screenshot

Besides that, you can check out the example code in the examples/ directory. See the "Documentation" section below for building and running the demo plugin. If you have a project written with React-JUCE that you want to share, get in touch! I would love to showcase your work.

Contributing

See CONTRIBUTING.md

License

See LICENSE.md

react-juce's People

Contributors

bisubus avatar dependabot[bot] avatar eupston avatar fefanto avatar ilionic avatar jrlanglois avatar julianstorer avatar mjmaurer avatar nick-thompson avatar olidacombe avatar rbaxter08 avatar remaininlight avatar stfufane avatar szk2s avatar tobiashienzsch avatar tobq avatar utokusa avatar vvvar avatar zigen avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

react-juce's Issues

Open question: Event support

As it stands, Blueprint doesn't really have event support. There's a non-standard implementation of pushing events to JavaScript by registering global functions in your app bundle and calling them from C++, with one special case for finding view instances and pushing events right to them.

A proper implementation would catch events on visible view elements and create something like React's SyntheticEvent, then bubble that event up the virtual React element tree. React has a library for doing exactly this, but it is not a public library and likely way too unstable to try to rely on just yet. We could attempt to implement our own, but it would likely be incomplete for a while.

Another option is to provide a global EventBridge in Blueprint, which is already kind of implemented, and have every React element that needs events subscribe to the event bridge and filter events by some known id. This skips the question of bubbling and goes more the route of something like Rxjs, but still would benefit from some kind of SyntheticEvent wrapper. In this case, we would need to find a way for a React element to access the internal id of a given view from the renderer, so that it knows what to filter on. Not sure exactly how to provide that, and I'm also questioning whether that's the right idea in the first place... seems like it could be a design flaw.

I'll spend some time studying the React Native implementation and proposing ideas here

Hot Reloading

Specifically, implementing a feature for reloading the javascript bundle on the fly, without the need for recompiling. There's a halfway implementation in there right now, but it's pretty poorly thought out, and likely should not be something that the ReactApplicationRoot implements.

Might be able to leverage Webpack's Hot Module loader and get the Duktape engine to just eval a new block of code during an update.

Perhaps this is a nice time to consider something like a BlueprintGenericEditor, similar to JUCE's GenericEditor so that you can just return new BlueprintGenericEditor(File("whatever")) from your processor's createEditor hook. That seems like it might be the right place to implement hot reloading (maybe just tear down the ReactApplicationRoot and make a new one on update)

Optimize var args

Where we interface with native methods, I've used ES6 rest/spread for var args (see EventBridge, BlueprintRenderer, and NativeMethods). Duktape notes any use of the arguments object as having a major performance impact, and the babel rest/spread transform compiles to using arguments. Probably a win to be had here with the old function dispatchViewEvent(a, b, c, d, e, f) var args trick, but it's a little hard to determine without profiling.

Low priority anyway until the native methods / event interface is more stable.

Add Typescript definitions/support

It would be great to add TypeScript definitions/support to Blueprint. Strong types will be a familiar warm blanket for less JS savvy C++ devs.

Being able to define interfaces and the like for component properties will help with avoiding errors at compile time (View would certainly benefit from this addition). It's inherently a little more complex to debug type mismatches and referencing undefined vars in Blueprint.

Add a proper Duktape fatal error handler

This happens at the time of creating the duktape context, should provide some kind of top level error handler like the one you see in React Native which just pops up a big red error screen with the error message and stack trace.

Add CMakeLists.txt to compile blueprint.cpp as static and/or shared libs

Hi Nick,

Currently using blueprint on linux in a CMake based build system. Would you be open to an MR with a simple CMakeLists.txt that effectively adds targets for a static and shared lib build of blueprint.cpp ?

This could add something along the lines of

add_library(blueprint_static STATIC blueprint.cpp)
add_library(blueprint SHARED blueprint.cpp)

 target_include_directories(
  blueprint_static
  ./yoga
  ./duktape/src-noline
)

This would allow other CMake projects to simpy use something like the following to add blueprint:

add_subdirectory(../Libraries/blueprint/blueprint)
target_link_libraries(MyApp blueprint_static)

Pass js function as prop to native view

This will be some duktape/juce trickery in readVarFromDukStack inside the EcmascriptEngine implementation to check if the given stack index is a function (duk_require_function or similar), and if it is, push that function into some global stash keyed by a unique id (https://wiki.duktape.org/howtonativepersistentreferences), then construct a juce::var::NativeFunction that captures that unique ID and invokes that function from the global stash in the js environment when the constructed native function is invoked.

This will enable cleaner View callbacks (i.e. can get rid of the dispatchViewEvent hack), which will facilitate interesting components like a Canvas component who passes an onDraw function prop to native to be called back by a timer every 30-60Hz

Clean up the `nativeMethodWrapper`

Commit 3811b06 introduces a better way to handle native method registration, used in the pushVarToDukStack and readVarFromDukStack methods to support passing e.g. a DynamicObject that has a juce::var::NativeFunction as a property.

The original nativeMethodWrapper is still lingering in there as used by the registerNativeMethod API, but it should be replaced with the newer stuff. See the TODOs inline: 3811b06#diff-9dd78235906a309d67f6d946b57e928fR17

Enable Custom Duktape Integrations

This issue sparked from discussion in PR #61: #61 (comment)

As Blueprint has grown, we've had to modify the duktape config inline to support the changes we need, which very much feels like (1) not the way duktape is meant to be integrated into a project and (2) it limits the end user's flexibility with duktape and Blueprint. For example, Duktape offers a compile configuration for low memory embedded environments, and there's no straightforward way to enable that in Blueprint as an end user.

This issue is meant to track this discussion and find a properly flexible way for integrating duktape

Distinguish Errors and Fatal Errors

Sparked from conversation in PR #61: #61 (comment)

In Duktape we have sort of two classes of errors: normal errors from which we can recover the js engine, and fatal errors from which we cannot. A normal error that goes uncaught becomes a fatal error, and so do explicit fatal cases from within Duktape itself. In ReactAppRoot we can catch almost all errors by making sure we do everything inside duk_pcall wrappers, and when we catch those errors we pop up the red stacktrace screen and wait for the user to update the bundle. This works great in dev, but we need a way to let the user define a custom error handler override so that, for example, they don't ship this red stacktrace screen in production.

Then we need a second override (or perhaps just a flag to the former override) to distinguish for cases where we're dealing with a fatal error, which I anticipate being rare cases, but cases we need to cover. I think it's fair for our default implementation to be just throwing a C++ error and crashing out, but obviously users should be able to customize that behavior.

Clean up `dispatchViewEvent`

With closing #32, we have a much nicer way to support invoking function props from a native view implementation. For example: 97ebe8c#diff-0fb21fdaed83bdf217e9ec1889cc57afR85

That means that all of the dispatchViewEvent stuff (e.g. https://github.com/nick-thompson/blueprint/blob/326867e9907cb20edcd7ea34b578d76d1a773364/packages/juce-blueprint/esm/lib/BlueprintBackend.js#L86) can be removed and "view events" can call callback props directly (e.g. https://github.com/nick-thompson/blueprint/blob/master/blueprint/core/blueprint_View.cpp#L156)

Rename project?

Someone sent me a link to this recently: https://blueprintjs.com/

Turns out "React" + "Blueprint" is already a thing... might be time to come up with a new name for this project!

Improve HostConfig.prepareUpdate

In the HostConfig in BlueprintRenderer.js the prepareUpdate method is pretty innefficient. It creates an update payload that contains all the old properties and all the new properties. Instead, it should create an update payload containing only new or changed properties so that we don't call into View::setProperty on things that haven't changed

Measure cost of native function invocations from js

This comes from the longer term goal of implementing the 2d Canvas API via native calls to a juce::Graphics& instance; I want to understand the difference in executing a call to the graphics instance from native vs from the javascript environment to get a sense of how practical this would be from a performance standpoint. I think even a simple benchmark would do:

for (int i = 0; i < 100000; ++i) {
  g.drawRect(0, 0, i, i);
}

vs binding a call to g.drawRect into the js interpreter, and running

js.evaluate(R"
  function test() {
    for (let i = 0; i < 10000; ++i) {
      ctx.drawRect(0, 0, i, i);
    }
  }
");
// Measure this:
js.invoke("test");

Optimize layout computation

Right now the ReactApplicationRoot calls performShadowTreeLayout on every setProperty call. This is obviously overkill; in an ideal case we would run the shadow tree layout only once after the ReactRenderer update lifecycle has completed.

There are probably a couple ways to tackle this, but initially it looks like the renderer calls resetAfterCommit in the host config once it has finished committing updates to every affected child. I think we could defer the performShadowTreeLayout call to that hook...

Implement a full Duktape Debugger Transport

Sparked from discussion in PR #61: #61 (comment)

To implement debugging with Duktape we're using their debug-trans-socket/duk_trans_socket_unix.c implementation with a little hack for preventing SIGPIPE issues. Their implementation seems to refer to itself as not production quality, so the task here is to revisit this debugger transport and implement whatever updates we may need to make it effective and robust

Support `getTransform` in `CanvasView`

Per the discussion here in #49, we're working to implement a shim of the CanvasRenderingContext2D API such that from javascript you can draw with something that feels exactly like working on a <canvas/> in web, but actually draws natively via JUCE's Graphics routines.

This particular task is for implementing the transform stack in such a way that we can satisfy the getTransform method by matrix multiplication over a series of juce::AffineTransform matrices, as described in the discussion linked above

Add support for Drag and Drop component/View

It would be great to add support for drag and drop views/components. We could have an outer View/Component type acting as a juce::DragAndDropContainer and apply a "draggable" property to the base View type which would apply to child components of the outer drag/drop container element.

See:

https://developer.mozilla.org/en-US/docs/Web/API/HTML_Drag_and_Drop_API
w3schools.com/html/html5_draganddrop.asp

https://docs.juce.com/master/classDragAndDropContainer.html
https://docs.juce.com/master/classDragAndDropTarget.html

Gain Example Build Failure

I try to build the Gain example in Xcode Version 9.2 (9C40b).
The example fails to build with the error message,

In file included from /Users/vallahiboyle/Desktop/JUCE/blueprint/examples/GainPlugin/JuceLibraryCode/include_blueprint.cpp:9:
In file included from ../../../../../blueprint/blueprint/blueprint.cpp:24:
../../../../../blueprint/blueprint/duktape/src-noline/duktape.c:29782:34: warning: implicit conversion loses integer precision: 'unsigned long' to 'duk_uint_fast32_t' (aka 'unsigned int') [-Wshorten-64-to-32]
                        match_val = (1UL << part_idx) + (1UL << (sep_idx + 9));  /* match against rule part/sep bits */
                                  ~ ~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
In file included from /Users/vallahiboyle/Desktop/JUCE/blueprint/examples/GainPlugin/JuceLibraryCode/include_blueprint.cpp:9:
In file included from ../../../../../blueprint/blueprint/blueprint.cpp:27:
../../../../../blueprint/blueprint/blueprint.h:38:9: warning: 'YG_ENUM_BEGIN' macro redefined [-Wmacro-redefined]
#define YG_ENUM_BEGIN(name) enum name: unsigned
        ^
In file included from /Users/vallahiboyle/Desktop/JUCE/blueprint/examples/GainPlugin/JuceLibraryCode/include_blueprint.cpp:9:
In file included from ../../../../../blueprint/blueprint/blueprint.cpp:27:
In file included from ../../../../../blueprint/blueprint/blueprint.h:28:
../../../../../blueprint/blueprint/yoga/yoga/YGMacros.h:30:9: note: previous definition is here
#define YG_ENUM_BEGIN(name) enum name
        ^
clang: error: unable to execute command: Segmentation fault: 11
clang: error: clang frontend command failed due to signal (use -v to see invocation)
Apple LLVM version 9.0.0 (clang-900.0.39.2)
Target: x86_64-apple-darwin16.7.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin


Debugger Support

RIght now there's no debugging other than console.log statements, and that's a pain for larger applications. Duktape does have builtin debug support, just need to find a way to integrate that with this project (https://github.com/svaarala/duktape/blob/master/doc/debugger.rst). I'd like to have an interface something like React Native where you hit CMD+D and it automatically pops up the debugger in a browser window.

Refactor ReactApplicationRoot / DuktapeEngine / UIManager

Right now the ReactApplicationRoot is kind of a monolith of duplicate codepaths that generally breaks down into interacting with and providing an interface for the duktape context, and providing an interface for constructing the View heirarchy. I'd like to split those distinct responsibilities into a DuktapeEngine class and a UIManager class, and let the ReactApplicationRoot be just a simple wrapper composing those two pieces.

This would allow cleaning up, for example, the multiple different ways of registering a native method in Duktape, and the multiple different implementations of marshaling the juce::var to/from duktape.

Reference to ‘AudioBuffer’ is Ambiguous

failed to build examples/BlueprintPlguin AU Plugin with XCode 11.4(11E146) on macOS 10.15.14 (Catalina)

the error shows 'Reference to ‘AudioBuffer’ is Ambiguous'.
JUCE causes this error on XCode11.4 and already solved in JUCE's develop branch. the commit is here

work around

just checkout ext/juce to develop from 5.4.1 (because the commit dddeb1 has not released yet)

solution

when JUCE released new version which includes the commit, we need to update submodule ext/juce to latest

Blueprint "extras" module

It would be great to create a new blueprint-extras or blueprint-components repo/module which provided users with a set of reusable components to get up and running.

For example, blueprint-extras could supply a generic implementation which handles value changes etc. This component could work in a similar fashion to juce::Slider and still allow users to customise the slider's behaviour with onDraw, onValueChanged props etc.

Part of this "extras" module could also include juce-wrapper components as discussed here: https://forum.juce.com/t/introducing-blueprint-build-native-juce-interfaces-with-react-js/34174/25

@nick-thompson I'd be interested to hear your thoughts about this in regards to how such a project could be kicked off.

Open question: Image/BinaryData Support

Handling image data is an interesting challenge, and there are many different ways to do it.

Currently, Blueprint implements an <Image> element that accepts a source property expecting a value that is an SVG string, which on the backend is parsed by a juce::Drawable and drawn at paint time. This works nicely with Webpack's SVG file loader because it automatically reads require('path/to/svg.svg') statements and satisfies them by embedding the raw svg string from the file.

However, this maybe won't scale for larger, more complicated SVGs, and it totally ignores the other common image use case, which is big PNG files either read from disk or carried in BinaryData. One possible path forward is to support BinaryData directly with some kind of C++ interface that lets you register a key/value pair which is a name and a pointer to some specific binary data, and allow that pair to be referenced by the key on the javascript side. <BinaryDataImage sourceKey={'background'} />. I'm not convinced this is a great idea though.

On the flip side, this might be a good case for a problem that Blueprint intentionally does not solve, and leaves open to the user. For example, if you have a big PNG strip for drawing a knob and you use the juce ImageCache to speed that up, maybe the best approach for interfacing with that is to write a custom KnobView and register that view with the ReactApplicationRoot (#8). Then there's no reason for Blueprint to concern itself with binary data, and you can still take full advantage of the techniques that JUCE already has for interacting with it.

Error compiling: invoke is not a member of 'std'

Hi, I am following the Starting a New Project guide and when I built I got the next error:

blueprint/core/blueprint_CanvasView.h: In member function 'virtual void blueprint::CanvasView::paint(juce::Graphics&): error: 'invoke' is not a member of 'std' std::invoke(props["onDraw"].getNativeFunction(), nfargs);.

I dont know if there is a missed step or there is an error there.

I'm using JUCE v5.4.7 on Ubuntu 16.04

Thanks in advance

Implement remaining Canvas API

@nick-thompson, I've started adding more Canvas API functions so figured it makes sense to open an issue here or pop something on the project board to track against? If you're happy with it being here I can assign to myself if you like?

Issue scope is to continue the work started here: 97ebe8c

I guess the aim is to implement bindings for as much of the CanvasRenderingContext2D API as possible: https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D

A good approach is probably to take a section of the API at a time. i.e. "Drawing Rectangles" and "Paths" in the above link.

@nick-thompson, it strikes me that a CanvasCtx object would be a really nice thing to have a typescript definition/interface for. This could really help bullet proof client code. I'd be up for investigating typescript definitions, I intend to try and move my stuff over to TS at some point.

Undefined property access getPublicInstance

Hi Nick.

Trying to do some error troubleshooting and struggling with debugging. Looked into the duktape debugger integration but I expect a decent amount of work there to integrate nicely.

I'm seeing a bunch of "undefined property access" issues in my App component. Can't tell any significant changes that might have caused this. I've tried updating react-reconciler to latest but no joy.

Any chance you could provide some info on how you track down the root cause of such errors in blueprint at the moment?

    in App

Consider adding an error boundary to your tree to customize error handling behavior.
Visit https://fb.me/react-error-boundaries to learn more about error boundaries.
    at [anon] (/home/josh/development/inmusic/ACVS/Software/External/Libraries/blueprint/blueprint/duktape/extras/console/duk_console.c:49) internal
    at error () native strict preventsyield
    at logCapturedError (input:7958) strict
    at logError (input:7992) strict
    at [anon] (input:8858) strict
    at callCallback (input:3293) strict
    at commitUpdateEffects (input:3332) strict
    at commitUpdateQueue (input:3323) strict
    at commitLifeCycles (input:8219) strict
    at commitAllLifeCycles (input:9471) strict
    at [anon] (input:2111) strict
    [...]
MethodTrace: Stubbing undefined property access for getPublicInstance`

Add continuous integration to project

During my first tests with blueprint, npm had a couple of errors which I could solve by deleting the package-lock.json files & running the npm install & npm run build commands with yarn:

yarn
yarn build

The problem could have probably been solved otherwise, but I thought this is a perfect example were CI could help and catch these kinds of errors early.

The project maintainer has to enable the services, but I can create the appveyor.yml (Windows) and .travis.yml (macOS & Linux).

This would also help with automatic documentation generation. See Issue #12

Toby

Refactor a HotReloader out of BlueprintGenericEditor

The BlueprintGenericEditor implements hot reloading by polling the file system to see if the js bundle has changed. It's super simple, and there's no reason that it has to be tied to a notion of a plugin editor (it should be usable no matter what type of app you're using). So I think just pulling that out into a separate class which can be composed wherever you need it makes sense.

HotReloader(std::unique_ptr<ReactApplicationRoot>& appRoot, const juce::File& bundle)

Just run the timer, check the bundle, and reset() the appRoot there. Then BlueprintGenericEditor just composes the HotReloader for this functionality

ScrollView snapping to top

ScrollView is implemented on the JUCE side such that it hijacks the appendChild View method to push the child view into a juce::Viewport. Meanwhile the shadow view tree doesn't have any notion of whether this child is scrolling or not. So when we go through a new layout computation, the shadow view treats the viewport's child as having bounds (0, 0, width, height), and when the layout flushes those bounds to the child, the Viewport listens and treats that as "scroll to 0, 0"

I think the right fix is to have a designated ScrollViewContentShadowView that overrides the flushlayout method of the ShadowView to ask its associated view for a top/left position, then use that top/left with the measured width/height for pushing new bounds to the scroll view content.

We'll expose a ScrollView.Content element on the js interface, which renders to a ScrollViewContentView, and the ReactApplicationRoot will respond to that by creating a regular View with an associated ScrollViewContentShadowView for the above behavior

Refine the "Multiple Bundles" story/behaviour

There are numerous areas of code in ReactApplicationRoot and EcmascriptEngine which may need to behave differently when blueprint supports the loading/evaluation of multiple bundles, i.e. for polyfill behaviour etc.

In particular, things like error handling and hot-reloading will need careful consideration. If a single bundle causes and evaluation error, does this mean we need to reload all bundle? There may be cases for tracking/storing the bundles loaded by callers etc.

Initially it might be good to define what all the use-cases of multiple bundle evaluation are and go from there.

Need to indicate node.js is a dependency in README.md

Not having dealt with npm before, I can imagine others will be as confused as I was!

Also, I have no idea what this means if I want to bring my app to a different system to develop, let alone to just run. Say I'm in a sharing mood and want my friend to test out my app on their system - then what? Do they have to install node.js to run my app?

Style Guide / Code Formatting

For future contributions, it would probably be very helpful to have a common style guide for source files (JavaScript, C++ & Markdown).

For C++ the only real option is clang-format, which is really nice once you find a config that you like.

For JavaScript and Markdown, there are more options. The one that I'm familiar with is Prettier, which does both JS & MD.

We could add a script which runs both tools on the source files.

Is this something you are interested in?

Documentation!

There's a lot to document here and I haven't done any of it :)

Not sure what the tool of choice here is... git storybook looks cool, github pages would be nice, maybe docsify? Either way, should pick one and get started!

JS Dependency Bug: "Unsupported"

A fresh install of blueprint in a new project seems to pull in some dependency somewhere that uses a language feature unsupported by duktape:

Render started...
Error: The above error occurred in the component:
in App

Consider adding an error boundary to your tree to customize error handling behavior.
Visit https://fb.me/react-error-boundaries to learn more about error boundaries.
at [anon] (/Builds/CLion/../../Modules/blueprint/blueprint/duktape/extras/console/duk_console.c:49) internal
at error () native strict preventsyield
at logCapturedError (input:7958) strict
at logError (input:7992) strict
at [anon] (input:8858) strict
at callCallback (input:3293) strict
at commitUpdateEffects (input:3332) strict
at commitUpdateQueue (input:3323) strict
at commitLifeCycles (input:8219) strict
at commitAllLifeCycles (input:9471) strict
at [anon] (input:2111) strict
[...]
Blueprint Fatal Error: uncaught: 'unsupported'
It is now unsafe to execute further code in the EcmascriptEngine.
terminate called after throwing an instance of 'std::runtime_error'
what(): uncaught: 'unsupported'

I think the best way to tackle this is probably (1) compile the duktape CLI tool with debugging support, (2) compile a main.js blueprint bundle with some shims for the native functions, then (3) run that bundle in the duktape CLI and try to catch with the debugger where the unsupported feaature is. Once we have located the bug we can figure out best steps to fix it

Event Loop?

Right now there's no real notion of an event loop. Timers are implemented by a simple map from id (an auto-incremented int) to function with timestamp and the JUCE implementation just runs an interrupt every 4ms to execute any ready timers. This "works" but it's not great, and it won't scale nicely to something like a fetch polyfill which needs to push work off to the cpp side for actually collecting the response and calling back into js with the result.

Camelcase to hyphen?

I'm using hyphenated property names (mostly because Yoga uses hyphenated property names and I didn't want to deal with any mapping), which can be annoying when writing a javascript object literal because you have to quote the key names.

I'm not totally sure I want to add this feature, but it might be a nice to have: some camelCase to hyphenated library so that you can write js object literals without quotes and the renderer will map to hyphenated before pushing to the native code.

Optimize ShadowView::setProperty

This method gets called a lot, and is pretty dominant in early profiling measurements. Need to dig into it, but off the top of my head I think there are gains to be made with:

  • Making a struct of const identifiers for the comparisons so that we don't construct identifiers on every comparison in that call
  • Early returns after the identifier is matched to avoid the remaining comparisons

compilation fails if JUCE_STRICT_REFCOUNTEDPOINTER is defined to 1

This definition disables implicit conversion from ReferenceCountedObjectPtr to ReferencedType* which increases safety. Personally I like higher level of safety. If it contradicts your design, feel free to close this issue :)

Tried building on Windows with MSVS 2019. See juce_ReferenceCountedObject.h for details.

TextView/RawTextView/AttributedString

Right now a TextView (<Text>) holds a set of RawTextView children, and during the render it constructs an AttributedString from the children text for layout and painting.

This is similar to React Native's text implementation, but I'm missing a piece for enabling the nesting of <Text> elements within each other, for cases such as bolding a single word of a sentence. Not sure exactly what the mapping needs to be between TextView / RawTextView / AttributedString, but there's surely a small tweak here that would clean up this design and enable nested TextViews.

Allow references inside lamda

I'm blocked by appRoot->engine.registerNativeMethod not allowing to pass variables inside lambda by reference: [&](void* stash, const juce::var::NativeFunctionArgs& args) - note the [&](...

I'd like to reference the cast of my processor inside the lambda function. Would it be possible to add support for this use case?

Great Library. Thanks.

FR to pregenerate VS projects

The Xcode project is pregenerated by the Projucer and committed to the repo. Would be nice to have the VS projects available as well. The purpose of JUCE is to be cross-platform so it would help get a better sense of the feasibility of this project without having to go through more hoops.

Pimpl for EcmascriptEngine and V8 Implementation

Right now the EcmascriptEngine interface leaks (as in leaky abstraction) the duk_context as a private member variable. Long term I want the EcmascriptEngine to be a generic interface that can be implemented by any one of the various ES5+ compliant embedded js engines, and therefore the EcmascriptEngine interface should be totally implementation-independent. For that reason, I think it's a good idea to adopt the Pimpl pattern and move any duktape specifics into the pimpl class.

With that done, I'd love to take a stab at implementing the interface via V8 and providing the option to run Blueprint via V8 (both with and without the jit enabled): https://v8.dev/docs

Dynamic View Registration

This one's almost already there, basically just need to refactor ReactApplicationRoot's createViewInstance to replace the blocks of if Viewtype == and instead maybe read from a std::map<juce::String, std::function<ViewId()>> and just invoke the function. Then provide a hook for registering a new view factory with the ReactApplication Root...

appRoot.registerViewType('oscilloscope', []() {
    std::unique_ptr<View> view = std::make_unique<MyCustomView>();
    ...etcetera
});

AnimatedView

The blueprint::View has a setFloatBounds method that the ShadowView calls into during a layout step. That method then delegates on to the juce::Component. I want to continue keeping this piece decoupled from the juce::Component interface, but there's a neat opportunity here because of the decoupling:

I want to create an AnimatedView, similiar to juce's ComponentAnimator, where when the View receives a call to setFloatBounds, instead of immediately calling the juce::Component::setBounds, start a timer at 60Hz or something to animate the bounds of the juce::Component. Basically on every tick of the timer nudge the current bounds closer to the target bounds until they're close enough to equal, at which point we stop the timer. How much to nudge on every frame can be configured via a settable property with easeIn, easeOut, linear, etc, options.

Demo plugin(s) + Examples

Right now examples/BlueprintPlugin is half-implemented and doesn't prioritize communicating how to work with the available features. I'd like to put some time into making this more along the lines of a JuceDemoPlugin that shows off what's available and how to use it.

I'll also leave this task open ended for additional demo ideas

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.