Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Apple TV react-native doesn't follow Apple's tvOS guidelines for menu key behavior #18930

Closed
3 tasks done
douglowder opened this issue Apr 19, 2018 · 15 comments
Closed
3 tasks done
Assignees
Labels
Bug Help Wanted :octocat: Issues ideal for external contributors. Platform: tvOS tvOS applications. Resolution: Locked This issue was locked by the bot.

Comments

@douglowder
Copy link
Contributor

When running a react-native app built for tvOS, the remote control's menu key does not exit the app and return to the tvOS home screen, as required by Apple. See guidelines at https://developer.apple.com/tvos/human-interface-guidelines/remote-and-controllers/remote/

This is happening because the RCTTVRemoteHandler class is adding a menu key gesture recognizer by default to RCTRootView. The gesture recognizer should be added if a screen is pushed onto a navigation stack and we are navigating back to a lower level screen; it should not be added for the app's main view.

Environment

Environment:
OS: macOS High Sierra 10.13.4
Node: 8.9.1
Yarn: 1.5.1
npm: 5.5.1
Watchman: Not Found
Xcode: Xcode 9.3 Build version 9E145
Android Studio: 3.1 AI-173.4697961

Packages: (wanted => installed)
react: ^16.0.0 => 16.3.2
react-native: ^0.54.0 => 0.54.4

Steps to Reproduce

See issue description above -- the same thing happens on both tvOS simulator and a real tvOS device.

Expected Behavior

Menu key should exit the app as required.
For apps that use navigation frameworks that back-navigate using menu key, the correct behavior needs to be implemented.

Actual Behavior

See description above.

@douglowder douglowder self-assigned this Apr 19, 2018
@react-native-bot
Copy link
Collaborator

Thanks for posting this! It looks like your issue may refer to an older version of React Native. Can you reproduce the issue on the latest release, v0.55?

Thank you for your contributions.

@euroclydon37
Copy link

Just curious how this is coming along? Let me know if I can help in any way or if you know of a quick work around.

And thanks for all your work porting RN to Apple TV.

@douglowder
Copy link
Contributor Author

@euroclydon37 I've made some progress.... The issue can be resolved by modifying RCTTVRemoteHandler to not create a gesture recognizer for the menu key. However, this would break apps that needed a menu key, e.g. ones with a navigation stack and using BackHandler. This will need some thought to come up with a graceful solution.

@react-native-bot react-native-bot added Help Wanted :octocat: Issues ideal for external contributors. and removed ⏪Old Version labels Jun 12, 2018
@mmg-mike
Copy link

mmg-mike commented Jul 9, 2018

I thought the Menu button would go back to the previous screen, and when the root screen of the app is reached, it would exit to the Apple TV home screen? The home button will always exit the app?

From the Apple Docs:

" Users expect to press the Menu button on the remote and return to a previous screen or the main Apple TV Home screen. Pressing Menu at the top level of an app or game should always exit to the Apple TV Home screen. During gameplay, pressing Menu should show or hide an in-game pause menu that includes an option to navigate back to the game’s main menu. "

@andrewagain
Copy link

@mrendsley Yes, that is exactly what the menu button is supposed to do. The problem is that there is no way to get the menu button to go to the Apple TV Home screen from the root screen of your app.

@andrewagain
Copy link

andrewagain commented Jan 8, 2019

In case it helps anybody else, this was my workaround.

I added the below method to my bridge that lets me enable/disable the menu button gesture recognizer. If the gesture recognizer is enabled, we can handle the menu button and go back a screen. If the gesture recognizer is NOT enabled, the app will close.

#import <React/RCTRootView.h>
#import <React/RCTTVRemoteHandler.h>
#import <React/RCTRootViewInternal.h>

RCT_EXPORT_METHOD(setMenuHandlerEnabled: (nonnull NSNumber*)enabled) {
    dispatch_async(dispatch_get_main_queue(), ^{
        // get your RCTRootView somehow - your code may differ here
        RSTVAppDelegate *appDelegate = (RSTVAppDelegate*)[[UIApplication sharedApplication] delegate];
        RCTRootView *rootView = (RCTRootView*)appDelegate.rootViewController.view;

        // get the menu button gesture recognizer and enable/disable it
        UITapGestureRecognizer *menuTapRecognizer = [rootView.tvRemoteHandler.tvRemoteGestureRecognizers objectForKey:RCTTVRemoteEventMenu];
        menuTapRecognizer.enabled = [enabled boolValue];
    });
}

Then in my javascript I call NativeModules.YourBridge.setMenuHandlerEnabled(false); when my home screen mounts or the user returns to my homescreen. I call NativeModules.YourBridge.setMenuHandlerEnabled(true); when the user visits any other screen.

@hufkens
Copy link

hufkens commented Feb 18, 2019

@ahfarmer I'm trying to use your workaround. But for some reason I can't import these

#import <React/RCTTVRemoteHandler.h>
TVMenuManager.m:12:9: 'React/RCTTVRemoteHandler.h' file not found

The same for RCTRootViewInternal.h The files are there in the React/Base folder and the other file imports work (ex. RCTRootView.h).

Any idea?

@andrewagain
Copy link

@hufkens Hmmmm sorry I'm not sure. Maybe a difference in our setup? I am using CocoaPods and react-native version 0.57.8.

@hufkens
Copy link

hufkens commented Feb 18, 2019

@ahfarmer I found way to add / remove the gesture handler without those 2 imports. There is no progress on fixing this properly in react-native?

@thymikee
Copy link
Contributor

FYI there's been a discussion lately on whether to extract tvOS out of the core: react-native-community/discussions-and-proposals#111

Since unfortunately there's no incentive from anyone on the core team to fix it in foreseeable future, I believe it makes sense to close it. But please keep the discussion going if you find it helpful.

@TheoGit
Copy link

TheoGit commented May 28, 2019

@hufkens could you share how you "found way to add / remove the gesture handler without those 2 imports" please

@hufkens
Copy link

hufkens commented May 29, 2019

Sure.

I made a method that will look for the GestureHandler. Keep a reference to it in the AppDegelate. Later you can remove the GestureHandler when your app reaches the Top level. In this case the App will close and go to the Home screen. You can re-add the GestureRecognizer when necessary.

- (void)findMenuHandler:(UIView*)rootView {
  for(UIGestureRecognizer *gr in rootView.gestureRecognizers) {
    if ([gr.allowedPressTypes.firstObject isEqualToValue:@(UIPressTypeMenu)]) {
      self.menuGestureRecognizer = gr;
    }
  }
}


- (void)setMenuHandlerEnabled:(BOOL)enabled {
  UIWindow * window = [[UIApplication sharedApplication] keyWindow];
  RCTRootView *rootView = (RCTRootView*)window.rootViewController.view;
  if (enabled) {
    [rootView addGestureRecognizer:self.menuGestureRecognizer];
  } else {
    [rootView removeGestureRecognizer:self.menuGestureRecognizer];
  }
}

douglowder added a commit to react-native-tvos/react-native-tvos that referenced this issue Jun 4, 2019
@douglowder
Copy link
Contributor Author

Going forward, Apple TV is going to be supported in a community repo separate from RN core.... https://github.com/react-native-community/react-native-tvos . Just added a commit that fixes this issue by adding a new TVMenuControl module, with methods to enable and disable the menu key gesture handler. The commit includes changes to the RNTester app to show how to use the new module to enable the menu key when pushing a screen, and disabling the menu key when you're back to the bottom level of your navigation.

douglowder added a commit to react-native-tvos/react-native-tvos that referenced this issue Jun 26, 2019
douglowder added a commit to react-native-tvos/react-native-tvos that referenced this issue Jul 31, 2019
@oscargallegoglobant
Copy link

Hey @hufkens!
I'm trying your solution on AppDelegate.m file and I'm getting this error message:

Property 'menuGestureRecognizer' not found on object of type 'AppDelegate *'

Maybe I'm missing something?

Thank you

@hufkens
Copy link

hufkens commented Aug 26, 2019

@oscargallegoglobant You will need to add a property on the AppDelegate for the menuGestureRecognizer.

@property (nonatomic, strong) UIGestureRecognizer *menuGestureRecognizer;

Or start using the version on https://github.com/react-native-community/react-native-tvos where this feature has been added. All new features bug fixes are maintained in the community repo now.

douglowder added a commit to react-native-tvos/react-native-tvos that referenced this issue Sep 27, 2019
douglowder added a commit to react-native-tvos/react-native-tvos that referenced this issue Oct 22, 2019
douglowder added a commit to react-native-tvos/react-native-tvos that referenced this issue Oct 23, 2019
* Add back TabBarIOS to 0.60.4

* Fixups to get RNTesterPods working on tvOS in 0.60.4

* Remove TabBarIOS deprecation warnings

* YellowBox uses TouchableOpacity for TV

* Better styling and focus engine accessibility for YellowBox on tvOS

* Correct Apple TV menu key behavior (fix RN issue facebook/react-native#18930)

* Only show async storage warning once on tvOS

* Remove deprecated APIs from RNTester examples to reduce warnings

* Change package name to react-native-tvos

* RNTester imports from react-native-tvos instead of react-native

* Fix tvOS tests

* Fix tvOS JS errors
@facebook facebook locked as resolved and limited conversation to collaborators Mar 19, 2020
@react-native-bot react-native-bot added the Resolution: Locked This issue was locked by the bot. label Mar 19, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Bug Help Wanted :octocat: Issues ideal for external contributors. Platform: tvOS tvOS applications. Resolution: Locked This issue was locked by the bot.
Projects
None yet
Development

No branches or pull requests

10 participants