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

[Mobile] - Android - Bring the Keyboard back when closing modals #57069

Merged
16 changes: 15 additions & 1 deletion packages/components/src/mobile/bottom-sheet/index.native.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,10 @@ import SafeArea from 'react-native-safe-area';
/**
* WordPress dependencies
*/
import { subscribeAndroidModalClosed } from '@wordpress/react-native-bridge';
import {
subscribeAndroidModalClosed,
showAndroidSoftKeyboard,
} from '@wordpress/react-native-bridge';
import { Component } from '@wordpress/element';
import { withPreferredColorScheme } from '@wordpress/compose';

Expand Down Expand Up @@ -215,6 +218,11 @@ class BottomSheet extends Component {
if ( this.androidModalClosedSubscription ) {
this.androidModalClosedSubscription.remove();
}

if ( this.props.isVisible ) {
showAndroidSoftKeyboard();
}

if ( this.safeAreaEventSubscription === null ) {
return;
}
Expand Down Expand Up @@ -315,6 +323,9 @@ class BottomSheet extends Component {
onDismiss() {
const { onDismiss } = this.props;

// Restore Keyboard Visibility
showAndroidSoftKeyboard();

if ( onDismiss ) {
onDismiss();
}
Expand Down Expand Up @@ -368,6 +379,7 @@ class BottomSheet extends Component {
onHardwareButtonPress() {
const { onClose } = this.props;
const { handleHardwareButtonPress } = this.state;

if ( handleHardwareButtonPress && handleHardwareButtonPress() ) {
return;
}
Expand Down Expand Up @@ -528,6 +540,8 @@ class BottomSheet extends Component {
}
onAccessibilityEscape={ this.onCloseBottomSheet }
testID="bottom-sheet"
hardwareAccelerated={ true }
useNativeDriverForBackdrop={ true }
{ ...rest }
>
<KeyboardAvoidingView
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ exports[`LinksUI LinksUI renders 1`] = `
backdropOpacity={0.2}
backdropTransitionInTiming={50}
backdropTransitionOutTiming={50}
hardwareAccelerated={true}
isVisible={true}
onAccessibilityEscape={[Function]}
onBackButtonPress={[Function]}
Expand All @@ -18,6 +19,7 @@ exports[`LinksUI LinksUI renders 1`] = `
preferredColorScheme="light"
swipeDirection="down"
testID="link-settings-modal"
useNativeDriverForBackdrop={true}
>
<View
behavior={false}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import android.os.Vibrator;
import android.provider.Settings;
import android.view.View;
import android.view.ViewTreeObserver;
import android.view.inputmethod.InputMethodManager;

import androidx.annotation.Nullable;
Expand Down Expand Up @@ -44,6 +45,7 @@ public class RNReactNativeGutenbergBridgeModule extends ReactContextBaseJavaModu
DeferredEventEmitter.JSEventEmitter {
private final ReactApplicationContext mReactContext;
private final GutenbergBridgeJS2Parent mGutenbergBridgeJS2Parent;
private Runnable mKeyboardRunnable;

private static final String EVENT_NAME_REQUEST_GET_HTML = "requestGetHtml";
private static final String EVENT_NAME_UPDATE_HTML = "updateHtml";
Expand Down Expand Up @@ -554,14 +556,69 @@ private ConnectionStatusCallback requestConnectionStatusCallback(final Callback
};
}

@ReactMethod
public void showAndroidSoftKeyboard() {
Activity currentActivity = mReactContext.getCurrentActivity();
if (isAnyViewFocused()) {
// Cancel any previously scheduled Runnable
if (mKeyboardRunnable != null) {
currentActivity.getWindow().getDecorView().removeCallbacks(mKeyboardRunnable);
}

View currentFocusedView = getCurrentFocusedView();
currentFocusedView.getViewTreeObserver().addOnWindowFocusChangeListener(new ViewTreeObserver.OnWindowFocusChangeListener() {
@Override
public void onWindowFocusChanged(boolean hasFocus) {
if (hasFocus) {
mKeyboardRunnable = createShowKeyboardRunnable();
currentActivity.getWindow().getDecorView().post(mKeyboardRunnable);
currentFocusedView.getViewTreeObserver().removeOnWindowFocusChangeListener(this);
}
}
});
}
}

private Runnable createShowKeyboardRunnable() {
return new Runnable() {
@Override
public void run() {
try {
Activity activity = mReactContext.getCurrentActivity();
View activeFocusedView = getCurrentFocusedView();
if (activeFocusedView != null && activity.getWindow().getDecorView().isShown()) {
InputMethodManager imm =
(InputMethodManager) mReactContext.getSystemService(Context.INPUT_METHOD_SERVICE);
imm.showSoftInput(activeFocusedView, InputMethodManager.SHOW_IMPLICIT);
}
} catch (Exception e) {
// Noop
}
}
};
}

private View getCurrentFocusedView() {
Activity activity = mReactContext.getCurrentActivity();
if (activity == null) {
return null;
}
return activity.getCurrentFocus();
}

private boolean isAnyViewFocused() {
View getCurrentFocusedView = getCurrentFocusedView();
return getCurrentFocusedView != null;
}

@ReactMethod
public void hideAndroidSoftKeyboard() {
Activity currentActivity = mReactContext.getCurrentActivity();
if (currentActivity != null) {
View currentFocusedView = currentActivity.getCurrentFocus();
if (currentFocusedView != null) {
InputMethodManager imm =
(InputMethodManager) mReactContext.getSystemService(Context.INPUT_METHOD_SERVICE);
(InputMethodManager) mReactContext.getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(currentFocusedView.getWindowToken(), 0);
}
}
Expand Down
14 changes: 14 additions & 0 deletions packages/react-native-bridge/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -515,6 +515,20 @@ export function sendEventToHost( eventName, properties ) {
);
}

/**
* Shows Android's soft keyboard if there's a TextInput focused and
* the keyboard is hidden.
*
* @return {void}
*/
export function showAndroidSoftKeyboard() {
fluiddot marked this conversation as resolved.
Show resolved Hide resolved
if ( isIOS ) {
return;
}

RNReactNativeGutenbergBridge.showAndroidSoftKeyboard();
}

/**
* Hides Android's soft keyboard.
*
Expand Down
1 change: 1 addition & 0 deletions test/native/setup.js
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ jest.mock( '@wordpress/react-native-bridge', () => {
subscribeOnRedoPressed: jest.fn(),
useIsConnected: jest.fn( () => ( { isConnected: true } ) ),
editorDidMount: jest.fn(),
showAndroidSoftKeyboard: jest.fn(),
hideAndroidSoftKeyboard: jest.fn(),
editorDidAutosave: jest.fn(),
subscribeMediaUpload: jest.fn(),
Expand Down
Loading