Attachment Modal: Send attachments on enter when input not focused (#6397)
This commit is contained in:
parent
c9f9b27332
commit
28a41a6764
@ -14,7 +14,7 @@ import type {
|
|||||||
} from '../../../types';
|
} from '../../../types';
|
||||||
import type { Signal } from '../../../util/signals';
|
import type { Signal } from '../../../util/signals';
|
||||||
|
|
||||||
import { EDITABLE_INPUT_ID } from '../../../config';
|
import { EDITABLE_INPUT_ID, EDITABLE_INPUT_MODAL_ID } from '../../../config';
|
||||||
import { requestForcedReflow, requestMutation } from '../../../lib/fasterdom/fasterdom';
|
import { requestForcedReflow, requestMutation } from '../../../lib/fasterdom/fasterdom';
|
||||||
import { selectCanPlayAnimatedEmojis, selectDraft, selectIsInSelectMode } from '../../../global/selectors';
|
import { selectCanPlayAnimatedEmojis, selectDraft, selectIsInSelectMode } from '../../../global/selectors';
|
||||||
import { selectSharedSettings } from '../../../global/selectors/sharedState';
|
import { selectSharedSettings } from '../../../global/selectors/sharedState';
|
||||||
@ -23,7 +23,7 @@ import {
|
|||||||
IS_ANDROID, IS_EMOJI_SUPPORTED, IS_IOS, IS_TOUCH_ENV,
|
IS_ANDROID, IS_EMOJI_SUPPORTED, IS_IOS, IS_TOUCH_ENV,
|
||||||
} from '../../../util/browser/windowEnvironment';
|
} from '../../../util/browser/windowEnvironment';
|
||||||
import buildClassName from '../../../util/buildClassName';
|
import buildClassName from '../../../util/buildClassName';
|
||||||
import captureKeyboardListeners from '../../../util/captureKeyboardListeners';
|
import captureKeyboardListeners, { hasActiveHandler } from '../../../util/captureKeyboardListeners';
|
||||||
import { getIsDirectTextInputDisabled } from '../../../util/directInputManager';
|
import { getIsDirectTextInputDisabled } from '../../../util/directInputManager';
|
||||||
import parseEmojiOnlyString from '../../../util/emoji/parseEmojiOnlyString';
|
import parseEmojiOnlyString from '../../../util/emoji/parseEmojiOnlyString';
|
||||||
import focusEditableElement from '../../../util/focusEditableElement';
|
import focusEditableElement from '../../../util/focusEditableElement';
|
||||||
@ -379,6 +379,22 @@ const MessageInput: FC<OwnProps & StateProps> = ({
|
|||||||
document.addEventListener('keydown', handleCloseContextMenu);
|
document.addEventListener('keydown', handleCloseContextMenu);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const isSendShortcut = useLastCallback((e: KeyboardEvent | React.KeyboardEvent<HTMLDivElement>) => {
|
||||||
|
return e.key === 'Enter'
|
||||||
|
&& !e.shiftKey
|
||||||
|
&& !isMobileDevice
|
||||||
|
&& (
|
||||||
|
(messageSendKeyCombo === 'enter' && !e.shiftKey)
|
||||||
|
|| (messageSendKeyCombo === 'ctrl-enter' && (e.ctrlKey || e.metaKey))
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
const handleSendShortcut = useLastCallback((e: KeyboardEvent | React.KeyboardEvent<HTMLDivElement>) => {
|
||||||
|
e.preventDefault();
|
||||||
|
closeTextFormatter();
|
||||||
|
onSend();
|
||||||
|
});
|
||||||
|
|
||||||
function handleKeyDown(e: React.KeyboardEvent<HTMLDivElement>) {
|
function handleKeyDown(e: React.KeyboardEvent<HTMLDivElement>) {
|
||||||
// https://levelup.gitconnected.com/javascript-events-handlers-keyboard-and-load-events-1b3e46a6b0c3#1960
|
// https://levelup.gitconnected.com/javascript-events-handlers-keyboard-and-load-events-1b3e46a6b0c3#1960
|
||||||
const { isComposing } = e;
|
const { isComposing } = e;
|
||||||
@ -394,19 +410,8 @@ const MessageInput: FC<OwnProps & StateProps> = ({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isComposing && e.key === 'Enter' && !e.shiftKey) {
|
if (!isComposing && isSendShortcut(e)) {
|
||||||
if (
|
handleSendShortcut(e);
|
||||||
!isMobileDevice
|
|
||||||
&& (
|
|
||||||
(messageSendKeyCombo === 'enter' && !e.shiftKey)
|
|
||||||
|| (messageSendKeyCombo === 'ctrl-enter' && (e.ctrlKey || e.metaKey))
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
e.preventDefault();
|
|
||||||
|
|
||||||
closeTextFormatter();
|
|
||||||
onSend();
|
|
||||||
}
|
|
||||||
} else if (!isComposing && e.key === 'ArrowUp' && !html && !e.metaKey && !e.ctrlKey && !e.altKey) {
|
} else if (!isComposing && e.key === 'ArrowUp' && !html && !e.metaKey && !e.ctrlKey && !e.altKey) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
editLastMessage();
|
editLastMessage();
|
||||||
@ -474,8 +479,7 @@ const MessageInput: FC<OwnProps & StateProps> = ({
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (
|
if (
|
||||||
!chatId
|
!chatId
|
||||||
|| editableInputId !== EDITABLE_INPUT_ID
|
|| (editableInputId !== EDITABLE_INPUT_ID && editableInputId !== EDITABLE_INPUT_MODAL_ID)
|
||||||
|| noFocusInterception
|
|
||||||
|| isMobileDevice
|
|| isMobileDevice
|
||||||
|| isSelectModeActive
|
|| isSelectModeActive
|
||||||
) {
|
) {
|
||||||
@ -483,18 +487,29 @@ const MessageInput: FC<OwnProps & StateProps> = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
const handleDocumentKeyDown = (e: KeyboardEvent) => {
|
const handleDocumentKeyDown = (e: KeyboardEvent) => {
|
||||||
if (getIsDirectTextInputDisabled()) {
|
const target = e.target as HTMLElement | undefined;
|
||||||
|
const input = inputRef.current!;
|
||||||
|
|
||||||
|
const shouldHandleDocumentKeyDown =
|
||||||
|
isActive && input && target
|
||||||
|
&& target !== input
|
||||||
|
&& target.tagName !== 'INPUT'
|
||||||
|
&& target.tagName !== 'TEXTAREA'
|
||||||
|
&& !target.isContentEditable
|
||||||
|
&& !hasActiveHandler('Enter');
|
||||||
|
|
||||||
|
if (!shouldHandleDocumentKeyDown) return;
|
||||||
|
|
||||||
|
if (isSendShortcut(e)) {
|
||||||
|
handleSendShortcut(e);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { key } = e;
|
const { key } = e;
|
||||||
const target = e.target as HTMLElement | undefined;
|
if (noFocusInterception || getIsDirectTextInputDisabled() || IGNORE_KEYS.includes(key)) {
|
||||||
|
|
||||||
if (!target || IGNORE_KEYS.includes(key)) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const input = inputRef.current!;
|
|
||||||
const isSelectionCollapsed = document.getSelection()?.isCollapsed;
|
const isSelectionCollapsed = document.getSelection()?.isCollapsed;
|
||||||
|
|
||||||
if (
|
if (
|
||||||
@ -504,18 +519,10 @@ const MessageInput: FC<OwnProps & StateProps> = ({
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
focusEditableElement(input, true, true);
|
||||||
input
|
|
||||||
&& target !== input
|
|
||||||
&& target.tagName !== 'INPUT'
|
|
||||||
&& target.tagName !== 'TEXTAREA'
|
|
||||||
&& !target.isContentEditable
|
|
||||||
) {
|
|
||||||
focusEditableElement(input, true, true);
|
|
||||||
|
|
||||||
const newEvent = new KeyboardEvent(e.type, e as any);
|
const newEvent = new KeyboardEvent(e.type, e as any);
|
||||||
input.dispatchEvent(newEvent);
|
input.dispatchEvent(newEvent);
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
document.addEventListener('keydown', handleDocumentKeyDown, true);
|
document.addEventListener('keydown', handleDocumentKeyDown, true);
|
||||||
@ -523,7 +530,8 @@ const MessageInput: FC<OwnProps & StateProps> = ({
|
|||||||
return () => {
|
return () => {
|
||||||
document.removeEventListener('keydown', handleDocumentKeyDown, true);
|
document.removeEventListener('keydown', handleDocumentKeyDown, true);
|
||||||
};
|
};
|
||||||
}, [chatId, editableInputId, isMobileDevice, isSelectModeActive, noFocusInterception]);
|
}, [chatId, editableInputId, isMobileDevice,
|
||||||
|
isActive, isSelectModeActive, noFocusInterception]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const captureFirstTab = debounce((e: KeyboardEvent) => {
|
const captureFirstTab = debounce((e: KeyboardEvent) => {
|
||||||
|
|||||||
@ -62,6 +62,11 @@ function hasActiveHandlers() {
|
|||||||
return Object.values(handlers).some((keyHandlers) => Boolean(keyHandlers.length));
|
return Object.values(handlers).some((keyHandlers) => Boolean(keyHandlers.length));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function hasActiveHandler(key: string) {
|
||||||
|
const handlerName = keyToHandlerName[key];
|
||||||
|
return handlerName ? Boolean(handlers[handlerName].length) : false;
|
||||||
|
}
|
||||||
|
|
||||||
function handleKeyDown(e: KeyboardEvent) {
|
function handleKeyDown(e: KeyboardEvent) {
|
||||||
const handlerName = keyToHandlerName[e.key];
|
const handlerName = keyToHandlerName[e.key];
|
||||||
if (!handlerName) {
|
if (!handlerName) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user