forked from Ivasoft/mattermost-mobile
Open Find Channels with keyboard shortcut (#6260)
This commit is contained in:
@@ -43,10 +43,19 @@ public class MainActivity extends NavigationActivity {
|
||||
*/
|
||||
@Override
|
||||
public boolean dispatchKeyEvent(KeyEvent event) {
|
||||
if (HWKeyboardConnected && event.getKeyCode() == KeyEvent.KEYCODE_ENTER && event.getAction() == KeyEvent.ACTION_UP) {
|
||||
String keyPressed = event.isShiftPressed() ? "shift-enter" : "enter";
|
||||
HWKeyboardEventModule.getInstance().keyPressed(keyPressed);
|
||||
return true;
|
||||
if (HWKeyboardConnected) {
|
||||
int keyCode = event.getKeyCode();
|
||||
int keyAction = event.getAction();
|
||||
if (keyAction == KeyEvent.ACTION_UP) {
|
||||
if (keyCode == KeyEvent.KEYCODE_ENTER) {
|
||||
String keyPressed = event.isShiftPressed() ? "shift-enter" : "enter";
|
||||
HWKeyboardEventModule.getInstance().keyPressed(keyPressed);
|
||||
return true;
|
||||
} else if (keyCode == KeyEvent.KEYCODE_K && event.isCtrlPressed()) {
|
||||
HWKeyboardEventModule.getInstance().keyPressed("find-channels");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return super.dispatchKeyEvent(event);
|
||||
};
|
||||
|
||||
@@ -19,12 +19,11 @@ import {useTheme} from '@context/theme';
|
||||
import {useIsTablet} from '@hooks/device';
|
||||
import useDidUpdate from '@hooks/did_update';
|
||||
import {t} from '@i18n';
|
||||
import EphemeralStore from '@store/ephemeral_store';
|
||||
import {extractFileInfo} from '@utils/file';
|
||||
import {switchKeyboardForCodeBlocks} from '@utils/markdown';
|
||||
import {changeOpacity, makeStyleSheetFromTheme, getKeyboardAppearanceFromTheme} from '@utils/theme';
|
||||
|
||||
const HW_EVENT_IN_SCREEN = ['Channel', 'Thread'];
|
||||
|
||||
type Props = {
|
||||
testID?: string;
|
||||
channelDisplayName?: string;
|
||||
@@ -220,7 +219,14 @@ export default function PostInput({
|
||||
}, [addFiles, intl]);
|
||||
|
||||
const handleHardwareEnterPress = useCallback((keyEvent: {pressedKey: string}) => {
|
||||
if (HW_EVENT_IN_SCREEN.includes(rootId ? Screens.THREAD : Screens.CHANNEL)) {
|
||||
const topScreen = EphemeralStore.getNavigationTopComponentId();
|
||||
let sourceScreen = Screens.CHANNEL;
|
||||
if (rootId) {
|
||||
sourceScreen = Screens.THREAD;
|
||||
} else if (isTablet) {
|
||||
sourceScreen = Screens.HOME;
|
||||
}
|
||||
if (topScreen === sourceScreen) {
|
||||
switch (keyEvent.pressedKey) {
|
||||
case 'enter':
|
||||
sendMessage();
|
||||
@@ -231,7 +237,7 @@ export default function PostInput({
|
||||
break;
|
||||
}
|
||||
}
|
||||
}, [sendMessage, updateValue, value, cursorPosition]);
|
||||
}, [sendMessage, updateValue, value, cursorPosition, isTablet]);
|
||||
|
||||
const onAppStateChange = useCallback((appState: AppStateStatus) => {
|
||||
if (appState !== 'active' && previousAppState.current === 'active') {
|
||||
@@ -271,9 +277,9 @@ export default function PostInput({
|
||||
}, [value]);
|
||||
|
||||
useEffect(() => {
|
||||
HWKeyboardEvent.onHWKeyPressed(handleHardwareEnterPress);
|
||||
const listener = HWKeyboardEvent.onHWKeyPressed(handleHardwareEnterPress);
|
||||
return () => {
|
||||
HWKeyboardEvent.removeOnHWKeyPressed();
|
||||
listener.remove();
|
||||
};
|
||||
}, [handleHardwareEnterPress]);
|
||||
|
||||
|
||||
@@ -3,14 +3,12 @@
|
||||
|
||||
import React, {useCallback} from 'react';
|
||||
import {useIntl} from 'react-intl';
|
||||
import {DeviceEventEmitter, TouchableHighlight} from 'react-native';
|
||||
import {Options} from 'react-native-navigation';
|
||||
import {TouchableHighlight} from 'react-native';
|
||||
|
||||
import CompassIcon from '@components/compass_icon';
|
||||
import FormattedText from '@components/formatted_text';
|
||||
import {Events, Screens} from '@constants';
|
||||
import {useTheme} from '@context/theme';
|
||||
import {showModal} from '@screens/navigation';
|
||||
import {findChannels} from '@screens/navigation';
|
||||
import {changeOpacity, makeStyleSheetFromTheme} from '@utils/theme';
|
||||
import {typography} from '@utils/typography';
|
||||
|
||||
@@ -44,23 +42,9 @@ const SearchField = () => {
|
||||
const styles = getStyleSheet(theme);
|
||||
|
||||
const onPress = useCallback(() => {
|
||||
const options: Options = {modal: {swipeToDismiss: false}};
|
||||
const closeButtonId = 'close-find-channels';
|
||||
const closeButton = CompassIcon.getImageSourceSync('close', 24, theme.sidebarHeaderTextColor);
|
||||
options.topBar = {
|
||||
leftButtons: [{
|
||||
id: closeButtonId,
|
||||
icon: closeButton,
|
||||
testID: closeButtonId,
|
||||
}],
|
||||
};
|
||||
|
||||
DeviceEventEmitter.emit(Events.PAUSE_KEYBOARD_TRACKING_VIEW, true);
|
||||
showModal(
|
||||
Screens.FIND_CHANNELS,
|
||||
findChannels(
|
||||
intl.formatMessage({id: 'find_channels.title', defaultMessage: 'Find Channels'}),
|
||||
{closeButtonId},
|
||||
options,
|
||||
theme,
|
||||
);
|
||||
}, [intl.locale, theme]);
|
||||
|
||||
|
||||
@@ -6,10 +6,13 @@ import {NavigationContainer} from '@react-navigation/native';
|
||||
import React, {useEffect} from 'react';
|
||||
import {useIntl} from 'react-intl';
|
||||
import {DeviceEventEmitter, Platform} from 'react-native';
|
||||
import HWKeyboardEvent from 'react-native-hw-keyboard-event';
|
||||
import {enableFreeze, enableScreens} from 'react-native-screens';
|
||||
|
||||
import {Events, Screens} from '@constants';
|
||||
import {useTheme} from '@context/theme';
|
||||
import {findChannels} from '@screens/navigation';
|
||||
import EphemeralStore from '@store/ephemeral_store';
|
||||
import {alertTeamRemove} from '@utils/navigation';
|
||||
import {notificationError} from '@utils/notification';
|
||||
|
||||
@@ -46,7 +49,7 @@ export default function HomeScreen(props: HomeProps) {
|
||||
return () => {
|
||||
listener.remove();
|
||||
};
|
||||
}, []);
|
||||
}, [intl.locale]);
|
||||
|
||||
useEffect(() => {
|
||||
const listener = DeviceEventEmitter.addListener(Events.LEAVE_TEAM, (displayName: string) => {
|
||||
@@ -56,7 +59,22 @@ export default function HomeScreen(props: HomeProps) {
|
||||
return () => {
|
||||
listener.remove();
|
||||
};
|
||||
});
|
||||
}, [intl.locale]);
|
||||
|
||||
useEffect(() => {
|
||||
const listener = HWKeyboardEvent.onHWKeyPressed((keyEvent: {pressedKey: string}) => {
|
||||
const screen = EphemeralStore.getAllNavigationComponents();
|
||||
if (!screen.includes(Screens.FIND_CHANNELS) && keyEvent.pressedKey === 'find-channels') {
|
||||
findChannels(
|
||||
intl.formatMessage({id: 'find_channels.title', defaultMessage: 'Find Channels'}),
|
||||
theme,
|
||||
);
|
||||
}
|
||||
});
|
||||
return () => {
|
||||
listener.remove();
|
||||
};
|
||||
}, [intl.locale]);
|
||||
|
||||
return (
|
||||
<NavigationContainer
|
||||
|
||||
@@ -688,3 +688,24 @@ export const showAppForm = async (form: AppForm, call: AppCallRequest) => {
|
||||
const passProps = {form, call};
|
||||
showModal(Screens.APP_FORM, form.title || '', passProps);
|
||||
};
|
||||
|
||||
export async function findChannels(title: string, theme: Theme) {
|
||||
const options: Options = {modal: {swipeToDismiss: false}};
|
||||
const closeButtonId = 'close-find-channels';
|
||||
const closeButton = CompassIcon.getImageSourceSync('close', 24, theme.sidebarHeaderTextColor);
|
||||
options.topBar = {
|
||||
leftButtons: [{
|
||||
id: closeButtonId,
|
||||
icon: closeButton,
|
||||
testID: closeButtonId,
|
||||
}],
|
||||
};
|
||||
|
||||
DeviceEventEmitter.emit(Events.PAUSE_KEYBOARD_TRACKING_VIEW, true);
|
||||
showModal(
|
||||
Screens.FIND_CHANNELS,
|
||||
title,
|
||||
{closeButtonId},
|
||||
options,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -71,7 +71,15 @@ class EphemeralStore {
|
||||
|
||||
hasModalsOpened = () => this.navigationModalStack.length > 0;
|
||||
|
||||
private removeNavigationComponent = (componentId: string) => {
|
||||
const index = this.allNavigationComponentIds.indexOf(componentId);
|
||||
if (index >= 0) {
|
||||
this.allNavigationComponentIds.splice(index, 1);
|
||||
}
|
||||
};
|
||||
|
||||
removeNavigationComponentId = (componentId: string) => {
|
||||
this.removeNavigationComponent(componentId);
|
||||
const index = this.navigationComponentIdStack.indexOf(componentId);
|
||||
if (index >= 0) {
|
||||
this.navigationComponentIdStack.splice(index, 1);
|
||||
@@ -79,6 +87,7 @@ class EphemeralStore {
|
||||
};
|
||||
|
||||
removeNavigationModal = (componentId: string) => {
|
||||
this.removeNavigationComponent(componentId);
|
||||
const index = this.navigationModalStack.indexOf(componentId);
|
||||
|
||||
if (index >= 0) {
|
||||
|
||||
@@ -242,17 +242,24 @@ RNHWKeyboardEvent *hwKeyEvent = nil;
|
||||
if ([hwKeyEvent isListening]) {
|
||||
UIKeyCommand *enter = [UIKeyCommand keyCommandWithInput:@"\r" modifierFlags:0 action:@selector(sendEnter:)];
|
||||
UIKeyCommand *shiftEnter = [UIKeyCommand keyCommandWithInput:@"\r" modifierFlags:UIKeyModifierShift action:@selector(sendShiftEnter:)];
|
||||
UIKeyCommand *findChannels = [UIKeyCommand keyCommandWithInput:@"k" modifierFlags:UIKeyModifierCommand action:@selector(sendFindChannels:)];
|
||||
if (@available(iOS 13.0, *)) {
|
||||
[enter setTitle:@"Send message"];
|
||||
[enter setDiscoverabilityTitle:@"Send message"];
|
||||
[shiftEnter setTitle:@"Add new line"];
|
||||
[shiftEnter setDiscoverabilityTitle:@"Add new line"];
|
||||
[findChannels setTitle:@"Find channels"];
|
||||
[findChannels setDiscoverabilityTitle:@"Find channels"];
|
||||
}
|
||||
if (@available(iOS 15.0, *)) {
|
||||
[enter setWantsPriorityOverSystemBehavior:YES];
|
||||
[shiftEnter setWantsPriorityOverSystemBehavior:YES];
|
||||
[findChannels setWantsPriorityOverSystemBehavior:YES];
|
||||
}
|
||||
|
||||
[commands addObject: enter];
|
||||
[commands addObject: shiftEnter];
|
||||
[commands addObject: findChannels];
|
||||
}
|
||||
|
||||
return commands;
|
||||
@@ -266,6 +273,10 @@ RNHWKeyboardEvent *hwKeyEvent = nil;
|
||||
NSString *selected = sender.input;
|
||||
[hwKeyEvent sendHWKeyEvent:@"shift-enter"];
|
||||
}
|
||||
- (void)sendFindChannels:(UIKeyCommand *)sender {
|
||||
NSString *selected = sender.input;
|
||||
[hwKeyEvent sendHWKeyEvent:@"find-channels"];
|
||||
}
|
||||
|
||||
#if RCT_NEW_ARCH_ENABLED
|
||||
#pragma mark - RCTCxxBridgeDelegate
|
||||
|
||||
@@ -12,12 +12,49 @@ index a70aace..6443899 100644
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
diff --git a/node_modules/react-native-hw-keyboard-event/index.d.ts b/node_modules/react-native-hw-keyboard-event/index.d.ts
|
||||
index 91999f1..53c7a42 100644
|
||||
index 91999f1..116b725 100644
|
||||
--- a/node_modules/react-native-hw-keyboard-event/index.d.ts
|
||||
+++ b/node_modules/react-native-hw-keyboard-event/index.d.ts
|
||||
@@ -1,4 +1,4 @@
|
||||
@@ -1,4 +1,5 @@
|
||||
+import {EventSubscription} from "react-native";
|
||||
+
|
||||
declare module "react-native-hw-keyboard-event";
|
||||
|
||||
-export function onHWKeyPressed(hwKeyEvent: { pressedKey: string }): void;
|
||||
+export function onHWKeyPressed(callback: (hwKeyEvent: { pressedKey: string }) => void): void;
|
||||
export function removeOnHWKeyPressed(): void;
|
||||
-export function removeOnHWKeyPressed(): void;
|
||||
+export function onHWKeyPressed(callback: (hwKeyEvent: { pressedKey: string }) => void): EventSubscription;
|
||||
diff --git a/node_modules/react-native-hw-keyboard-event/index.js b/node_modules/react-native-hw-keyboard-event/index.js
|
||||
index 30d4dd9..3dcff70 100644
|
||||
--- a/node_modules/react-native-hw-keyboard-event/index.js
|
||||
+++ b/node_modules/react-native-hw-keyboard-event/index.js
|
||||
@@ -7,28 +7,9 @@ import {
|
||||
|
||||
class HWKeyboardEvent {
|
||||
onHWKeyPressed(cb) {
|
||||
- this.removeOnHWKeyPressed(true);
|
||||
- if (!this.cbStack) {
|
||||
- this.cbStack = [];
|
||||
- }
|
||||
- this.cbStack.push(cb);
|
||||
let keyEvent = new NativeEventEmitter(NativeModules.RNHWKeyboardEvent);
|
||||
- this.listener = keyEvent.addListener("onHWKeyPressed", cb);
|
||||
- }
|
||||
-
|
||||
- removeOnHWKeyPressed(newCbAdded) {
|
||||
- if (this.listener) {
|
||||
- this.listener.remove();
|
||||
- this.listener = null;
|
||||
- }
|
||||
- if (!this.cbStack) return;
|
||||
- if (!newCbAdded) {
|
||||
- this.cbStack.pop();
|
||||
- if (this.cbStack.length > 0) {
|
||||
- // re-add removed listeners in case there where any
|
||||
- this.onHWKeyPressed(this.cbStack[this.cbStack.length - 1]);
|
||||
- }
|
||||
- }
|
||||
+ const listener = keyEvent.addListener("onHWKeyPressed", cb);
|
||||
+ return listener;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user