Mm 10601 - Use Enter Key to send message on Hardware Keyboards (#3760)

* Reacting to shift-enter events on iOS

* moving keyEvent logic to handleHardwareEnterPress

* configured android to work with keyEvents

* using dispatchKeyEvent instead of onKeyUp

* using react-native-hw-keyboard-event

* cleanup

* updated package name

* update package name

* using react-native-hw-keyboard-event v0.0.2

* reverted cocoapods version change

* Documentation

* fix detection of Shift-Enter on android

* simplify dispatchKeyEvent()

* fix for stacked hardware keyboard events

* Update android/app/src/main/java/com/mattermost/rnbeta/MainActivity.java

Co-Authored-By: Miguel Alatzar <migbot@users.noreply.github.com>

* simplify dispatchKeyEvent

* removed yarn.lock

* using react-native-hw-keyboard-event v0.0.4

* Using ACTION_UP instead of ACTION_DOWN

Co-authored-by: Miguel Alatzar <migbot@users.noreply.github.com>
This commit is contained in:
Emilio Rodriguez 2020-02-04 17:34:14 +01:00 committed by GitHub
parent e62c9b7a6d
commit 0b98d82bfa
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 87 additions and 31 deletions

View file

@ -263,7 +263,9 @@ dependencies {
implementation project(':@sentry_react-native')
implementation project(':react-native-android-open-settings')
implementation project(':react-native-haptic-feedback')
implementation project(':react-native-hw-keyboard-event')
implementation project(':react-native-permissions')
implementation project(':react-native-fast-image')
// For animated GIF support

View file

@ -4,6 +4,8 @@ import android.os.Bundle;
import androidx.annotation.Nullable;
import com.reactnativenavigation.NavigationActivity;
import android.view.KeyEvent;
import com.github.emilioicai.hwkeyboardevent.HWKeyboardEventModule;
public class MainActivity extends NavigationActivity {
@Override
@ -11,4 +13,19 @@ public class MainActivity extends NavigationActivity {
super.onCreate(savedInstanceState);
setContentView(R.layout.launch_screen);
}
/*
https://mattermost.atlassian.net/browse/MM-10601
Required by react-native-hw-keyboard-event
(https://github.com/emilioicai/react-native-hw-keyboard-event)
*/
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
if (event.getKeyCode() == KeyEvent.KEYCODE_ENTER && event.getAction() == KeyEvent.ACTION_UP) {
String keyPressed = event.isShiftPressed() ? "shift-enter" : "enter";
HWKeyboardEventModule.getInstance().keyPressed(keyPressed);
return true;
}
return super.dispatchKeyEvent(event);
};
}

View file

@ -6,6 +6,7 @@ import android.content.Context;
import android.content.RestrictionsManager;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;
import java.io.File;
import java.util.HashMap;
import java.util.Arrays;
@ -69,6 +70,8 @@ import com.facebook.soloader.SoLoader;
import com.mattermost.share.RealPathUtil;
import com.github.emilioicai.hwkeyboardevent.HWKeyboardEventPackage;
public class MainApplication extends NavigationApplication implements INotificationsApplication, INotificationsDrawerApplication {
public static MainApplication instance;
@ -202,7 +205,8 @@ public class MainApplication extends NavigationApplication implements INotificat
new LinearGradientPackage(),
new ReactVideoPackage(),
new RNGestureHandlerPackage(),
new RNPasteableTextInputPackage()
new RNPasteableTextInputPackage(),
new HWKeyboardEventPackage()
);
}

View file

@ -53,3 +53,5 @@ include ':@react-native-community_async-storage'
project(':@react-native-community_async-storage').projectDir = new File(rootProject.projectDir, '../node_modules/@react-native-community/async-storage/android')
include ':@react-native-community_netinfo'
project(':@react-native-community_netinfo').projectDir = new File(rootProject.projectDir, '../node_modules/@react-native-community/netinfo/android')
include ':react-native-hw-keyboard-event'
project(':react-native-hw-keyboard-event').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-hw-keyboard-event/android')

View file

@ -21,6 +21,7 @@ import {
import {intlShape} from 'react-intl';
import RNFetchBlob from 'rn-fetch-blob';
import Button from 'react-native-button';
import HWKeyboardEvent from 'react-native-hw-keyboard-event';
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons';
import slashForwardBoxIcon from 'assets/images/icons/slash-forward-box.png';
@ -129,6 +130,7 @@ export default class PostTextBoxBase extends PureComponent {
EventEmitter.on(event, this.handleInsertTextToDraft);
AppState.addEventListener('change', this.handleAppStateChange);
HWKeyboardEvent.onHWKeyPressed(this.handleHardwareEnterPress);
if (Platform.OS === 'android') {
Keyboard.addListener('keyboardDidHide', this.handleAndroidKeyboard);
@ -156,6 +158,7 @@ export default class PostTextBoxBase extends PureComponent {
EventEmitter.off(event, this.handleInsertTextToDraft);
AppState.removeEventListener('change', this.handleAppStateChange);
HWKeyboardEvent.removeOnHWKeyPressed();
if (Platform.OS === 'android') {
Keyboard.removeListener('keyboardDidHide', this.handleAndroidKeyboard);
@ -375,6 +378,14 @@ export default class PostTextBoxBase extends PureComponent {
this.blur();
};
handleHardwareEnterPress = (keyEvent) => {
switch (keyEvent.pressedKey) {
case 'enter': this.handleSendMessage();
break;
case 'shift-enter': this.handleInsertTextToDraft('\n');
}
}
handleAndroidBack = () => {
const {channelId, files, rootId} = this.props;
if (files.length) {

View file

@ -18,6 +18,7 @@
#import <UserNotifications/UserNotifications.h>
#import "Mattermost-Swift.h"
#import <os/log.h>
#import <RNHWKeyboardEvent.h>
@implementation AppDelegate
@ -139,4 +140,30 @@ NSString* const NOTIFICATION_UPDATE_BADGE_ACTION = @"update_badge";
restorationHandler:restorationHandler];
}
/*
https://mattermost.atlassian.net/browse/MM-10601
Required by react-native-hw-keyboard-event
(https://github.com/emilioicai/react-native-hw-keyboard-event)
*/
RNHWKeyboardEvent *hwKeyEvent = nil;
- (NSMutableArray<UIKeyCommand *> *)keyCommands {
NSMutableArray *keys = [NSMutableArray new];
if (hwKeyEvent == nil) {
hwKeyEvent = [[RNHWKeyboardEvent alloc] init];
}
if ([hwKeyEvent isListening]) {
[keys addObject: [UIKeyCommand keyCommandWithInput:@"\r" modifierFlags:0 action:@selector(sendEnter:)]];
[keys addObject: [UIKeyCommand keyCommandWithInput:@"\r" modifierFlags:UIKeyModifierShift action:@selector(sendShiftEnter:)]];
}
return keys;
}
- (void)sendEnter:(UIKeyCommand *)sender {
NSString *selected = sender.input;
[hwKeyEvent sendHWKeyEvent:@"enter"];
}
- (void)sendShiftEnter:(UIKeyCommand *)sender {
NSString *selected = sender.input;
[hwKeyEvent sendHWKeyEvent:@"shift-enter"];
}
@end

View file

@ -210,6 +210,8 @@ PODS:
- React
- react-native-document-picker (3.2.4):
- React
- react-native-hw-keyboard-event (0.0.4):
- React
- react-native-image-picker (2.0.0):
- React
- react-native-local-auth (1.5.0):
@ -335,6 +337,7 @@ DEPENDENCIES:
- "react-native-cameraroll (from `../node_modules/@react-native-community/cameraroll`)"
- react-native-cookies (from `../node_modules/react-native-cookies/ios`)
- react-native-document-picker (from `../node_modules/react-native-document-picker`)
- react-native-hw-keyboard-event (from `../node_modules/react-native-hw-keyboard-event`)
- react-native-image-picker (from `../node_modules/react-native-image-picker`)
- react-native-local-auth (from `../node_modules/react-native-local-auth`)
- "react-native-netinfo (from `../node_modules/@react-native-community/netinfo`)"
@ -430,6 +433,8 @@ EXTERNAL SOURCES:
:path: "../node_modules/react-native-cookies/ios"
react-native-document-picker:
:path: "../node_modules/react-native-document-picker"
react-native-hw-keyboard-event:
:path: "../node_modules/react-native-hw-keyboard-event"
react-native-image-picker:
:path: "../node_modules/react-native-image-picker"
react-native-local-auth:
@ -523,6 +528,7 @@ SPEC CHECKSUMS:
react-native-cameraroll: ad20f5a93c25cb83a76455df57a2c62fbb63aaed
react-native-cookies: 854d59c4135c70b92a02ca4930e68e4e2eb58150
react-native-document-picker: c36bf5f067a581657ecaf7124dcd921a8be19061
react-native-hw-keyboard-event: b517cefb8d5c659a38049c582de85ff43337dc53
react-native-image-picker: ba7fe85b3373ff33d4827210d989dfcbbd68f7f9
react-native-local-auth: 5081a70211643de74bb207e007401a0c81b37a20
react-native-netinfo: 892a5130be97ff8bb69c523739c424a2ffc296d1

46
package-lock.json generated
View file

@ -7065,8 +7065,7 @@
},
"ansi-regex": {
"version": "2.1.1",
"bundled": true,
"optional": true
"bundled": true
},
"aproba": {
"version": "1.2.0",
@ -7084,13 +7083,11 @@
},
"balanced-match": {
"version": "1.0.0",
"bundled": true,
"optional": true
"bundled": true
},
"brace-expansion": {
"version": "1.1.11",
"bundled": true,
"optional": true,
"requires": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
@ -7103,18 +7100,15 @@
},
"code-point-at": {
"version": "1.1.0",
"bundled": true,
"optional": true
"bundled": true
},
"concat-map": {
"version": "0.0.1",
"bundled": true,
"optional": true
"bundled": true
},
"console-control-strings": {
"version": "1.1.0",
"bundled": true,
"optional": true
"bundled": true
},
"core-util-is": {
"version": "1.0.2",
@ -7217,8 +7211,7 @@
},
"inherits": {
"version": "2.0.3",
"bundled": true,
"optional": true
"bundled": true
},
"ini": {
"version": "1.3.5",
@ -7228,7 +7221,6 @@
"is-fullwidth-code-point": {
"version": "1.0.0",
"bundled": true,
"optional": true,
"requires": {
"number-is-nan": "^1.0.0"
}
@ -7241,20 +7233,17 @@
"minimatch": {
"version": "3.0.4",
"bundled": true,
"optional": true,
"requires": {
"brace-expansion": "^1.1.7"
}
},
"minimist": {
"version": "0.0.8",
"bundled": true,
"optional": true
"bundled": true
},
"minipass": {
"version": "2.3.5",
"bundled": true,
"optional": true,
"requires": {
"safe-buffer": "^5.1.2",
"yallist": "^3.0.0"
@ -7271,7 +7260,6 @@
"mkdirp": {
"version": "0.5.1",
"bundled": true,
"optional": true,
"requires": {
"minimist": "0.0.8"
}
@ -7344,8 +7332,7 @@
},
"number-is-nan": {
"version": "1.0.1",
"bundled": true,
"optional": true
"bundled": true
},
"object-assign": {
"version": "4.1.1",
@ -7355,7 +7342,6 @@
"once": {
"version": "1.4.0",
"bundled": true,
"optional": true,
"requires": {
"wrappy": "1"
}
@ -7431,8 +7417,7 @@
},
"safe-buffer": {
"version": "5.1.2",
"bundled": true,
"optional": true
"bundled": true
},
"safer-buffer": {
"version": "2.1.2",
@ -7462,7 +7447,6 @@
"string-width": {
"version": "1.0.2",
"bundled": true,
"optional": true,
"requires": {
"code-point-at": "^1.0.0",
"is-fullwidth-code-point": "^1.0.0",
@ -7480,7 +7464,6 @@
"strip-ansi": {
"version": "3.0.1",
"bundled": true,
"optional": true,
"requires": {
"ansi-regex": "^2.0.0"
}
@ -7519,13 +7502,11 @@
},
"wrappy": {
"version": "1.0.2",
"bundled": true,
"optional": true
"bundled": true
},
"yallist": {
"version": "3.0.3",
"bundled": true,
"optional": true
"bundled": true
}
}
},
@ -12740,6 +12721,11 @@
"resolved": "https://registry.npmjs.org/react-native-haptic-feedback/-/react-native-haptic-feedback-1.8.2.tgz",
"integrity": "sha512-arY2vsQtcF6Z/HggcfASTFzXm5HLUvK08rj6xPs6b95mpUDyStxEoC2c6MCFx+GSqnpBuOQvQCf42Zp0ATnWoQ=="
},
"react-native-hw-keyboard-event": {
"version": "0.0.4",
"resolved": "https://registry.npmjs.org/react-native-hw-keyboard-event/-/react-native-hw-keyboard-event-0.0.4.tgz",
"integrity": "sha512-G8qp0nm17PHigLb/axgdF9xg51BKCG2p1AGeq//J/luLp5zNczIcQJh+nm02R1MeEUE3e53wqO4LMe0MV3raZg=="
},
"react-native-image-gallery": {
"version": "github:mattermost/react-native-image-gallery#c1a9f7118e90cc87d47620bc0584c9cac4b0cf38",
"from": "github:mattermost/react-native-image-gallery#c1a9f7118e90cc87d47620bc0584c9cac4b0cf38",

View file

@ -44,6 +44,7 @@
"react-native-fast-image": "7.0.2",
"react-native-gesture-handler": "1.5.3",
"react-native-haptic-feedback": "1.8.2",
"react-native-hw-keyboard-event": "0.0.4",
"react-native-image-gallery": "github:mattermost/react-native-image-gallery#c1a9f7118e90cc87d47620bc0584c9cac4b0cf38",
"react-native-image-picker": "2.0.0",
"react-native-keyboard-aware-scroll-view": "0.9.1",