Composer: Prevent losing focus when clicking on the message list (#1238)

This commit is contained in:
Alexander Zinchuk 2021-07-07 18:38:52 +03:00
parent fc975f87cc
commit 50d25947fe
4 changed files with 44 additions and 8 deletions

View File

@ -25,6 +25,7 @@ import useLang from '../../hooks/useLang';
import ContextMenuContainer from './message/ContextMenuContainer.async';
import useFlag from '../../hooks/useFlag';
import useShowTransition from '../../hooks/useShowTransition';
import { preventMessageInputBlur } from './helpers/preventMessageInputBlur';
type OwnProps = {
message: ApiMessage;
@ -96,6 +97,11 @@ const ActionMessage: FC<OwnProps & StateProps> = ({
} = useContextMenuHandlers(ref);
const isContextMenuShown = contextMenuPosition !== undefined;
const handleMouseDown = (e: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
preventMessageInputBlur(e);
handleBeforeContextMenu(e);
};
if (isEmbedded) {
return <span className="embedded-action-message">{renderText(content as string)}</span>;
}
@ -114,7 +120,7 @@ const ActionMessage: FC<OwnProps & StateProps> = ({
id={`message${message.id}`}
className={className}
data-message-id={message.id}
onMouseDown={handleBeforeContextMenu}
onMouseDown={handleMouseDown}
onContextMenu={handleContextMenu}
>
<span>{content}</span>

View File

@ -45,6 +45,7 @@ import { formatHumanDate } from '../../util/dateFormat';
import useLayoutEffectWithPrevDeps from '../../hooks/useLayoutEffectWithPrevDeps';
import buildClassName from '../../util/buildClassName';
import { groupMessages, MessageDateGroup, isAlbum } from './helpers/groupMessages';
import { preventMessageInputBlur } from './helpers/preventMessageInputBlur';
import { ObserveFn, useIntersectionObserver } from '../../hooks/useIntersectionObserver';
import useOnChange from '../../hooks/useOnChange';
import useStickyDates from './hooks/useStickyDates';
@ -521,7 +522,12 @@ const MessageList: FC<OwnProps & StateProps & DispatchProps> = ({
);
return (
<div ref={containerRef} className={className} onScroll={handleScroll}>
<div
ref={containerRef}
className={className}
onScroll={handleScroll}
onMouseDown={preventMessageInputBlur}
>
{isRestricted ? (
<div className="empty">
<span>
@ -704,11 +710,13 @@ function renderMessages(
<div
className="message-date-group"
key={dateGroup.datetime}
onMouseDown={preventMessageInputBlur}
teactFastList
>
<div
className={buildClassName('sticky-date', !isSchedule && 'interactive')}
key="date-header"
onMouseDown={preventMessageInputBlur}
onClick={!isSchedule ? () => openHistoryCalendar({ selectedAt: dateGroup.datetime }) : undefined}
>
<span dir="auto">

View File

@ -0,0 +1,17 @@
import React from '../../../lib/teact/teact';
import { EDITABLE_INPUT_ID } from '../../../config';
import { IS_SINGLE_COLUMN_LAYOUT } from '../../../util/environment';
export function preventMessageInputBlur(e: React.MouseEvent<HTMLElement>) {
if (
IS_SINGLE_COLUMN_LAYOUT
|| !document.activeElement
|| document.activeElement.id !== EDITABLE_INPUT_ID
|| e.target !== e.currentTarget
) {
return;
}
e.preventDefault();
}

View File

@ -1,4 +1,3 @@
import { MouseEvent as ReactMouseEvent } from 'react';
import React, {
FC,
memo,
@ -67,6 +66,7 @@ import { ROUND_VIDEO_DIMENSIONS } from '../../common/helpers/mediaDimensions';
import { buildContentClassName, isEmojiOnlyMessage } from './helpers/buildContentClassName';
import { getMinMediaWidth, calculateMediaDimensions } from './helpers/mediaDimensions';
import { calculateAlbumLayout } from './helpers/calculateAlbumLayout';
import { preventMessageInputBlur } from '../helpers/preventMessageInputBlur';
import renderText from '../../common/helpers/renderText';
import calculateAuthorWidth from './helpers/calculateAuthorWidth';
import { ObserveFn, useOnIntersect } from '../../../hooks/useIntersectionObserver';
@ -342,7 +342,7 @@ const Message: FC<OwnProps & StateProps & DispatchProps> = ({
appendixRef.current.innerHTML = isOwn ? APPENDIX_OWN : APPENDIX_NOT_OWN;
}, [isOwn, withAppendix]);
const handleGroupDocumentMessagesSelect = useCallback((e: ReactMouseEvent<HTMLDivElement, MouseEvent>) => {
const handleGroupDocumentMessagesSelect = useCallback((e: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
e.stopPropagation();
toggleMessageSelection({
@ -351,7 +351,7 @@ const Message: FC<OwnProps & StateProps & DispatchProps> = ({
});
}, [messageId, message.groupedId, toggleMessageSelection]);
const handleMessageSelect = useCallback((e?: ReactMouseEvent<HTMLDivElement, MouseEvent>) => {
const handleMessageSelect = useCallback((e?: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
const params = isAlbum && album && album.messages
? {
messageId,
@ -366,10 +366,15 @@ const Message: FC<OwnProps & StateProps & DispatchProps> = ({
setReplyingToId({ messageId });
}, [setReplyingToId, messageId]);
const handleContentDoubleClick = useCallback((e: ReactMouseEvent<HTMLDivElement, MouseEvent>) => {
const handleContentDoubleClick = useCallback((e: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
e.stopPropagation();
}, []);
const handleMouseDown = (e: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
preventMessageInputBlur(e);
handleBeforeContextMenu(e);
};
const handleAvatarClick = useCallback(() => {
if (!avatarPeer) {
return;
@ -425,7 +430,7 @@ const Message: FC<OwnProps & StateProps & DispatchProps> = ({
});
}, [chatId, threadId, openMediaViewer, isScheduled]);
const handleClick = useCallback((e: ReactMouseEvent<HTMLDivElement, MouseEvent>) => {
const handleClick = useCallback((e: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
const target = e.target as HTMLDivElement;
if (!target.classList.contains('text-content') && !target.classList.contains('Message')) {
return;
@ -754,7 +759,7 @@ const Message: FC<OwnProps & StateProps & DispatchProps> = ({
data-message-id={messageId}
onClick={isInSelectMode ? handleMessageSelect : IS_ANDROID ? handleClick : undefined}
onDoubleClick={!isInSelectMode ? handleContainerDoubleClick : undefined}
onMouseDown={!isInSelectMode ? handleBeforeContextMenu : undefined}
onMouseDown={!isInSelectMode ? handleMouseDown : undefined}
onContextMenu={!isInSelectMode ? handleContextMenu : undefined}
onMouseEnter={isInDocumentGroup && !isLastInDocumentGroup ? handleDocumentGroupMouseEnter : undefined}
onMouseLeave={isInDocumentGroup && !isLastInDocumentGroup ? handleDocumentGroupMouseLeave : undefined}