From f51773ecdedbac19d25eb20894e532edef2cb304 Mon Sep 17 00:00:00 2001 From: Levi Buzolic Date: Fri, 13 Aug 2021 19:26:20 -0700 Subject: [PATCH] Allow Modal to handle hardware escape key in the same way the back button is handled (#31564) Summary: On Android, when a hardware keyboard is connected pressing the escape key will partially dismiss an active `` 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 [Android] [Fixed] - Fix Modal being dismissed incorrectly when pressing escape on a hardware keyboard Pull Request resolved: https://github.com/facebook/react-native/pull/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 --- .../react/views/modal/ReactModalHostView.java | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/modal/ReactModalHostView.java b/ReactAndroid/src/main/java/com/facebook/react/views/modal/ReactModalHostView.java index 318594c2eb5574..561b96d13baefb 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/modal/ReactModalHostView.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/modal/ReactModalHostView.java @@ -293,14 +293,11 @@ 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"); @@ -308,9 +305,8 @@ public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) { 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);