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: Events in modal not sent to RN #15389

Closed
rada opened this issue Aug 6, 2017 · 6 comments
Closed

Apple TV: Events in modal not sent to RN #15389

rada opened this issue Aug 6, 2017 · 6 comments
Labels
Resolution: Locked This issue was locked by the bot.

Comments

@rada
Copy link

rada commented Aug 6, 2017

Is this a bug report?

Yes

Have you read the Contributing Guidelines?

Yes

Environment

  1. react-native -v: 0.47.1
  2. node -v: 6.5.0
  3. npm -v: 3.10.3

Then, specify:

  • Target Platform: AppleTV
  • Development Operating System: macOS Sierra (10.12.5)
  • Build tools: Xcode (8.3.3)

Steps to Reproduce

(Write your steps here:)

  1. Open the app (console) log.
  2. In the Tab 2 (in the demo app provided below) move around the Touchable elements. (In Simulator, use either the arrow keys on the keyboard or the Apple TV remote). Press the Play/Pause button on the Apple TV remote. Press the Menu button on the Apple TV remote.
  3. Check the log to see events (right, left, top, up, focus, blur, PlayPause) being printed as you move around the touchables.
  4. Select and press any Touchable to open Modal
  5. Once in Modal, again move around the Touchables the same way. Press PlayPause button.
  6. Check the log for the events being printed.

Expected Behavior

On each move/select of a random Touchable, the events right, left etc. are being printed (sent to RN) in the log. On the Menu and PlayPause button press in the Apple TV remote, the corresponding events are printed in the log.

Actual Behavior

In the Tab View, the events right, left, up, down, focus, blur, select, playPause are printed (sent to RN) as expected.

Issue 1: In the Modal View, only the events focus, blur and select are printed (sent to RN). The events PlayPause, right, left, up and down are not printed (sent to RN).

Issue 2: in The Tab View, the event 'Menu' is only sent if the Tab Bar menu is visible i.e. the Menu button needs to be pressed twice.

Reproducible Demo

https://gitlab.com/radamich/tvTabBar/tree/tvosEvents

Events.js

import React, { Component } from 'react';
import ReactNative from 'ReactNative';
import {
	Text,
	View,
	StyleSheet,
	TouchableHighlight,
	Modal,
} from 'react-native';
import TVEventHandler from 'TVEventHandler';

export default class Events extends Component {

	constructor(props) {
		super(props);

		this.state = {
			modalVisible: false,
		};
		this._tvEventHandler = new TVEventHandler();
	}

	_enableTVEventHandler() {
		this._tvEventHandler.enable(this, (cmp, evt) => {
			const myTag = ReactNative.findNodeHandle(cmp);
			console.log('Event.js TVEventHandler: ', evt.eventType);
			// if (evt.eventType !== 'blur' && evt.eventType !== 'focus') {
			// 	console.log('Event.js TVEventHandler: ', evt.eventType);
			// }
		});
	}

	_disableTVEventHandler() {
		if (this._tvEventHandler) {
			this._tvEventHandler.disable();
			delete this._tvEventHandler;
		}
	}

	componentDidMount() {
		this._enableTVEventHandler();
	}

	componentWillUnmount() {
		this._disableTVEventHandler();
	}

	_renderRow() {
		return (
			<View style={styles.row}>
				{
					Array.from({ length: 7 }).map((_, index) => {
						return (
							<TouchableHighlight
								key={index}
								onPress={() => { this.setState({ modalVisible: !this.state.modalVisible }); }}
							>
								<View style={styles.item}>
									<Text style={styles.itemText}>{ index }</Text>
								</View>
							</TouchableHighlight>
						);
					})
				}
			</View>
		);
	}

	render() {
		return (
			<View style={styles.container}>
				<Modal visible={this.state.modalVisible}>
					<View style={styles.modal}>
						{ this._renderRow() }
						{ this._renderRow() }
					</View>
				</Modal>
				{ this._renderRow() }
				{ this._renderRow() }
			</View>
		);
	}
}

const styles = StyleSheet.create({
	container: {
		flex: 1,
		backgroundColor: 'darkslategrey',
	},
	row: {
		flexDirection: 'row',
		padding: 30,
	},
	item: {
		width: 200,
		height: 100,
		borderColor: 'cyan',
		borderWidth: 2,
		margin: 30,
		alignItems: 'center',
		justifyContent: 'center',
	},
	itemText: {
		fontSize: 40,
		color: 'cyan',
	},
	modal: {
		flex: 1,
		backgroundColor: 'steelblue',
	},
});

cc @dlowder-salesforce

@JulienKode
Copy link
Contributor

JulienKode commented Aug 6, 2017

@rada I have the same problem, when I look the code some times ago, If I remember the event are not forward to react native

We need to add this feature in the future

@rada
Copy link
Author

rada commented Aug 6, 2017

@JulienKode It seems the feature is already there in Modal but it works only for some events.

@JulienKode
Copy link
Contributor

@rada you are right 👍

@JulienKode
Copy link
Contributor

JulienKode commented Aug 7, 2017

#15341 Will fix this problem

@rada
Copy link
Author

rada commented Sep 19, 2017

When can this be fixed/implemented?

douglowder added a commit to douglowder/react-native that referenced this issue Sep 24, 2017
cdlewis pushed a commit to cdlewis/react-native that referenced this issue Nov 19, 2017
…#15389)

Summary:
**Motivation**

Fix an issue (facebook#15389) where `TVEventHandler` would not work when a modal was visible.  The solution adds the gesture recognizers from the native `RCTTVRemoteHandler` to the native modal view (except for the menu button recognizer, which still needs special handling in modals).  This PR also fixes some breakages in compiling React Native for tvOS.

**Test plan**

Compilation fixes should enable tvOS compile test to pass in Travis CI.

The modal fix can be tested with the following component, modified from the original source in facebook#15389 .

``` javascript
import React, { Component } from 'react';
import ReactNative from 'ReactNative';
import {
    Text,
    View,
    StyleSheet,
    TouchableHighlight,
    TVEventHandler,
    Modal,
} from 'react-native';

export default class Events extends Component {

    constructor(props) {
        super(props);

        this.state = {
            modalVisible: false,
        };
        this._tvEventHandler = new TVEventHandler();
    }

    _enableTVEventHandler() {
        this._tvEventHandler.enable(this, (cmp, evt) => {
            const myTag = ReactNative.findNodeHandle(cmp);
            console.log('Event.js TVEventHandler: ', evt.eventType);
            // if (evt.eventType !== 'blur' && evt.eventType !== 'focus') {
            //  console.log('Event.js TVEventHandler: ', evt.eventType);
            // }
        });
    }

    _disableTVEventHandler() {
        if (this._tvEventHandler) {
            this._tvEventHandler.disable();
            delete this._tvEventHandler;
        }
    }

    componentDidMount() {
        this._enableTVEventHandler();
    }

    componentWillUnmount() {
        this._disableTVEventHandler();
    }

    _renderRow() {
        return (
            <View style={styles.row}>
                {
                    Array.from({ length: 7 }).map((_, index) => {
                        return (
                            <TouchableHighlight
                                key={index}
                                onPress={() => { this.setState({ modalVisible: !this.state.modalVisible }); }}
                            >
                                <View style={styles.item}>
                                    <Text style={styles.itemText}>{ index }</Text>
                                </View>
                            </TouchableHighlight>
                        );
                    })
                }
            </View>
        );
    }

    onTVEvent(cmp, evt) {
      console.log('Modal.js TVEventHandler: ', evt.eventType);
    }

    hideModal() {
      this.setState({
        modalVisible: false
      });
    }

    render() {
        return (
            <View style={styles.container}>
                <Modal visible={this.state.modalVisible}
                       onRequestClose={() => this.hideModal()}>
                    <View style={styles.modal}>
                        { this._renderRow() }
                        { this._renderRow() }
                    </View>
                </Modal>
                { this._renderRow() }
                { this._renderRow() }
            </View>
        );
    }
}

const styles = StyleSheet.create({
    container: {
        flex: 1,
        backgroundColor: 'darkslategrey',
    },
    row: {
        flexDirection: 'row',
        padding: 30,
    },
    item: {
        width: 200,
        height: 100,
        borderColor: 'cyan',
        borderWidth: 2,
        margin: 30,
        alignItems: 'center',
        justifyContent: 'center',
    },
    itemText: {
        fontSize: 40,
        color: 'cyan',
    },
    modal: {
        flex: 1,
        backgroundColor: 'steelblue',
    },
});
```
**Release Notes**

After this change, the `onRequestClose` property will be required for a `Modal` in Apple TV.
Closes facebook#16076

Differential Revision: D6288801

Pulled By: hramos

fbshipit-source-id: 446ae94a060387324aa9e528bd93cdabc9b5b37f
@huqiliang
Copy link

huqiliang commented Jul 17, 2018

I have the same issue in android platform when use remote control , is it have some solution?

@facebook facebook locked as resolved and limited conversation to collaborators Nov 9, 2018
@react-native-bot react-native-bot added the Resolution: Locked This issue was locked by the bot. label Nov 9, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Resolution: Locked This issue was locked by the bot.
Projects
None yet
Development

No branches or pull requests

4 participants