facebook / react-native

A framework for building native applications using React
https://reactnative.dev
MIT License
118.51k stars 24.27k forks source link

Question: Best practice for CommandCenter -> ReactJS view comms? #1026

Closed jaygarcia closed 9 years ago

jaygarcia commented 9 years ago

I'm currently working on a Chiptunes mode player and am wiring in iOS CommandCenter. CommandCenter is responsible for listening to events from the home screen, bottom drawer, USB command inputs (car audio controllers, etc) and headphone remotes.

The wiring needs to be complete so that I can wire up events such as play, pause, next and previous track.

The current communication is as such: CommandCenter -> ViewManager -> STOP

I'm having trouble figuring out how to publish events from the view manager to the view (there will only be one "Player" view ever.

Does anyone have any strategies to overcome this? Should I be thinking of app-level events?

Here's the command center hook if anyone's wondering:

    MCModPlayer *player = [MCModPlayer sharedManager];

    /** Remote control management**/
    MPRemoteCommandCenter *commandCenter = [MPRemoteCommandCenter sharedCommandCenter];

    [commandCenter.playCommand addTargetWithHandler:^MPRemoteCommandHandlerStatus(MPRemoteCommandEvent *event) {
        [player resume];

        NSLog(@"playCommand");

//        How does one emit an event to a view from the view controller (View Manager) when the VM doesn't know of a particular view?
//        [self.bridge.eventDispatcher sendInputEventWithName:@"topChange" body:body];

        return MPRemoteCommandHandlerStatusSuccess;
    }];
nicklockwood commented 9 years ago

Take a look at the implementation for RCTWebView, which solves a similar problem.

nicklockwood commented 9 years ago

Although, if your command center is a singelton, and doesn't have any UI of its own, should it perhaps just be a regular bridge module, rather than a view manager?

nicklockwood commented 9 years ago

It sounds like your problem is more similar to something like RCTReachability, or RCTLocationObserver, where the native module just has methods and sends events, but has no view of its own.

jaygarcia commented 9 years ago

I started down that route but could not figure out how to inform the Ui of a state change. :-/

Reading through the source, I found that the only way to go from bridge > view is to route events via react tag.

I'm a newb.

JG

@moduscreate

:: sent from my mobile device ::

On Apr 26, 2015, at 09:35, Nick Lockwood notifications@github.com wrote:

Although, if your command center is a singelton, and doesn't have any UI of its own, should it perhaps just be a regular bridge module, rather than a view manager?

— Reply to this email directly or view it on GitHub.

jaygarcia commented 9 years ago

I have not looked at that source. I will after I get home. :)

Many thanks. You guys flipping own for working on the weekends.

JG

@moduscreate

:: sent from my mobile device ::

On Apr 26, 2015, at 09:42, Nick Lockwood notifications@github.com wrote:

It sounds like your problem is more similar to something like RCTReachability, or RCTLocationObserver, where the native module just has methods and sends events, but has no view of its own.

— Reply to this email directly or view it on GitHub.

jaygarcia commented 9 years ago

@nicklockwood !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

You effing nailed it dude! Thank you so much.

jaygarcia commented 9 years ago

For those interested, here's the product of this effort:

https://www.youtube.com/watch?v=VaZnJ-_R3rU

sahrens commented 9 years ago

Did you use an event emitter?

On Apr 26, 2015, at 11:35 AM, Jay Garcia notifications@github.com wrote:

For those interested, here's the product of this effort:

https://www.youtube.com/watch?v=VaZnJ-_R3rU

— Reply to this email directly or view it on GitHub.

jaygarcia commented 9 years ago

@sahrens eventDispatcher. It's working like a friggin champ.

 [commandCenter.previousTrackCommand addTargetWithHandler:^MPRemoteCommandHandlerStatus(MPRemoteCommandEvent *event) {
        //TODO: Handle previous track (have no idea what to do here atm);
        NSLog(@"previousTrackCommand");

       [_bridge.eventDispatcher sendDeviceEventWithName:@"commandCenterEvent" body:@{
            @"eventType" : @"previousTrack"
        }];
        return MPRemoteCommandHandlerStatusSuccess;
    }];
brentvatne commented 9 years ago

@jaygarcia - how about publishing a library that exposes this functionality to JS?