Skip to content

Commit

Permalink
Allow Modal to handle hardware escape key in the same way the back bu…
Browse files Browse the repository at this point in the history
…tton is handled (#31564)

Summary:
On Android, when a hardware keyboard is connected pressing the escape key will partially dismiss an active `<Modal>` without calling the `onRequestClose` callback. The modal will disappear, but I beleive the underlying activity may still be present, blocking interaction with the main app below and leaving things in a partially broken state.

This code change allows the escape key to be handled in the same way as the hardware back button, calling the `onRequestClose` and allowing the developer to decide the behaviour.

This issue isn't present on iOS, so no change is required there.

## Changelog

<!-- Help reviewers and the release process by writing your own changelog entry. For an example, see:
https://github.com/facebook/react-native/wiki/Changelog
-->

[Android] [Fixed] - Fix Modal being dismissed incorrectly when pressing escape on a hardware keyboard

Pull Request resolved: #31564

Test Plan: I've tested this manually locally, but unsure if it's possible to test in an automated way as the emulator didn't respond to a hardware escape key in the same way as a physical device.

Reviewed By: ShikaSD

Differential Revision: D28953718

Pulled By: lunaleaps

fbshipit-source-id: 5547bc5d894da0d3d9daf4515b1af9c2407815db
  • Loading branch information
levibuzolic authored and facebook-github-bot committed Aug 14, 2021
1 parent ecd6927 commit f51773e
Showing 1 changed file with 7 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -293,24 +293,20 @@ protected void showOrUpdate() {
@Override
public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
if (event.getAction() == KeyEvent.ACTION_UP) {
// We need to stop the BACK button from closing the dialog by default so we capture
// that
// event and instead inform JS so that it can make the decision as to whether or not
// to
// allow the back button to close the dialog. If it chooses to, it can just set
// visible
// to false on the Modal and the Modal will go away
if (keyCode == KeyEvent.KEYCODE_BACK) {
// We need to stop the BACK button and ESCAPE key from closing the dialog by default
// so we capture that event and instead inform JS so that it can make the decision as
// to whether or not to allow the back/escape key to close the dialog. If it chooses
// to, it can just set visible to false on the Modal and the Modal will go away
if (keyCode == KeyEvent.KEYCODE_BACK || keyCode == KeyEvent.KEYCODE_ESCAPE) {
Assertions.assertNotNull(
mOnRequestCloseListener,
"setOnRequestCloseListener must be called by the manager");
mOnRequestCloseListener.onRequestClose(dialog);
return true;
} else {
// We redirect the rest of the key events to the current activity, since the
// activity
// expects to receive those events and react to them, ie. in the case of the dev
// menu
// activity expects to receive those events and react to them, ie. in the case of
// the dev menu
Activity currentActivity = ((ReactContext) getContext()).getCurrentActivity();
if (currentActivity != null) {
return currentActivity.onKeyUp(keyCode, event);
Expand Down

0 comments on commit f51773e

Please sign in to comment.