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
20 changes: 19 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 @@ -209,12 +212,21 @@ class BottomSheet extends Component {
}

componentWillUnmount() {
const { isFullScreen } = this.props;

this.dimensionsChangeSubscription.remove();
this.keyboardShowListener.remove();
this.keyboardHideListener.remove();
if ( this.androidModalClosedSubscription ) {
this.androidModalClosedSubscription.remove();
}

if ( this.props.isVisible ) {
// For full screen modals we add a delay for the keyboard
const keyboardDelay = isFullScreen ? 500 : 0;
showAndroidSoftKeyboard( { delay: keyboardDelay } );
}

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

// Restore Keyboard Visibility
showAndroidSoftKeyboard();

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

if ( handleHardwareButtonPress && handleHardwareButtonPress() ) {
return;
}
Expand Down Expand Up @@ -528,6 +544,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,59 @@ private ConnectionStatusCallback requestConnectionStatusCallback(final Callback
};
}

@ReactMethod
public void showAndroidSoftKeyboard(Integer delayMillis) {
Activity currentActivity = mReactContext.getCurrentActivity();
if (currentActivity != null) {
View currentFocusedView = currentActivity.getCurrentFocus();
if (currentFocusedView != null) {
fluiddot marked this conversation as resolved.
Show resolved Hide resolved
// Cancel any previously scheduled Runnable
if (mKeyboardRunnable != null) {
currentActivity.getWindow().getDecorView().removeCallbacks(mKeyboardRunnable);
}

final Runnable showTheKeyboardNow = new Runnable() {
@Override
public void run() {
try {
View activeFocusedView = currentActivity.getCurrentFocus();
if (activeFocusedView != null && currentActivity.getWindow().getDecorView().isShown()) {
fluiddot marked this conversation as resolved.
Show resolved Hide resolved
InputMethodManager imm =
(InputMethodManager) mReactContext.getSystemService(Context.INPUT_METHOD_SERVICE);
imm.showSoftInput(activeFocusedView, InputMethodManager.SHOW_IMPLICIT);
}
} catch (Exception e) {
// Noop
}
}
};

// Schedule the keyboard showing with a delay
if (currentFocusedView.hasWindowFocus()) {
currentActivity.getWindow().getDecorView().postDelayed(showTheKeyboardNow, delayMillis);
fluiddot marked this conversation as resolved.
Show resolved Hide resolved
} else {
currentFocusedView.getViewTreeObserver().addOnWindowFocusChangeListener(new ViewTreeObserver.OnWindowFocusChangeListener() {
@Override
public void onWindowFocusChanged(boolean hasFocus) {
if (hasFocus) {
currentActivity.getWindow().getDecorView().postDelayed(showTheKeyboardNow, delayMillis);
currentFocusedView.getViewTreeObserver().removeOnWindowFocusChangeListener(this);
}
}
});
}
}
}
}
fluiddot marked this conversation as resolved.
Show resolved Hide resolved

@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
16 changes: 16 additions & 0 deletions packages/react-native-bridge/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -515,6 +515,22 @@ export function sendEventToHost( eventName, properties ) {
);
}

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

const { delay = 0 } = options || {};
RNReactNativeGutenbergBridge.showAndroidSoftKeyboard( delay );
}

/**
* 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