Message Context Menu: Fix reaction selector not closing on Esc (#3327)

This commit is contained in:
Alexander Zinchuk 2023-06-18 12:03:33 +02:00
parent 8fc05e97ff
commit 8dbb4402a4
4 changed files with 23 additions and 2 deletions

View File

@ -21,6 +21,7 @@ import {
selectIsCurrentUserPremium, selectIsCurrentUserPremium,
selectIsMessageProtected, selectIsMessageProtected,
selectIsPremiumPurchaseBlocked, selectIsPremiumPurchaseBlocked,
selectIsReactionPickerOpen,
selectMessageCustomEmojiSets, selectMessageCustomEmojiSets,
selectMessageTranslations, selectMessageTranslations,
selectRequestedTranslationLanguage, selectRequestedTranslationLanguage,
@ -110,6 +111,7 @@ type StateProps = {
maxUniqueReactions?: number; maxUniqueReactions?: number;
threadId?: number; threadId?: number;
canPlayAnimatedEmojis?: boolean; canPlayAnimatedEmojis?: boolean;
isReactionPickerOpen?: boolean;
}; };
const ContextMenuContainer: FC<OwnProps & StateProps> = ({ const ContextMenuContainer: FC<OwnProps & StateProps> = ({
@ -163,6 +165,7 @@ const ContextMenuContainer: FC<OwnProps & StateProps> = ({
threadId, threadId,
onClose, onClose,
onCloseAnimationEnd, onCloseAnimationEnd,
isReactionPickerOpen,
}) => { }) => {
const { const {
openChat, openChat,
@ -473,6 +476,7 @@ const ContextMenuContainer: FC<OwnProps & StateProps> = ({
return ( return (
<div className={buildClassName('ContextMenuContainer', transitionClassNames)}> <div className={buildClassName('ContextMenuContainer', transitionClassNames)}>
<MessageContextMenu <MessageContextMenu
isReactionPickerOpen={isReactionPickerOpen}
availableReactions={availableReactions} availableReactions={availableReactions}
topReactions={topReactions} topReactions={topReactions}
message={message} message={message}
@ -681,6 +685,7 @@ export default memo(withGlobal<OwnProps>(
canShowOriginal: hasTranslation, canShowOriginal: hasTranslation,
canSelectLanguage: hasTranslation, canSelectLanguage: hasTranslation,
canPlayAnimatedEmojis: selectCanPlayAnimatedEmojis(global), canPlayAnimatedEmojis: selectCanPlayAnimatedEmojis(global),
isReactionPickerOpen: selectIsReactionPickerOpen(global),
}; };
}, },
)(ContextMenuContainer)); )(ContextMenuContainer));

View File

@ -73,3 +73,8 @@
} }
} }
} }
.ReactionSelector-hidden {
opacity: 0;
transition: 300ms opacity;
}

View File

@ -39,6 +39,7 @@ import ReactionSelector from './ReactionSelector';
import './MessageContextMenu.scss'; import './MessageContextMenu.scss';
type OwnProps = { type OwnProps = {
isReactionPickerOpen?: boolean;
availableReactions?: ApiAvailableReaction[]; availableReactions?: ApiAvailableReaction[];
topReactions?: ApiReaction[]; topReactions?: ApiReaction[];
isOpen: boolean; isOpen: boolean;
@ -122,6 +123,7 @@ const REACTION_SELECTOR_WIDTH_REM = 19.25;
const ANIMATION_DURATION = 200; const ANIMATION_DURATION = 200;
const MessageContextMenu: FC<OwnProps> = ({ const MessageContextMenu: FC<OwnProps> = ({
isReactionPickerOpen,
availableReactions, availableReactions,
topReactions, topReactions,
isOpen, isOpen,
@ -222,6 +224,12 @@ const MessageContextMenu: FC<OwnProps> = ({
onClose(); onClose();
}); });
useEffect(() => {
if (isOpen && areItemsHidden && !isReactionPickerOpen) {
onClose();
}
}, [onClose, isOpen, isReactionPickerOpen, areItemsHidden]);
const handleOpenCustomEmojiSets = useLastCallback(() => { const handleOpenCustomEmojiSets = useLastCallback(() => {
if (!customEmojiSets) return; if (!customEmojiSets) return;
if (customEmojiSets.length === 1) { if (customEmojiSets.length === 1) {
@ -329,6 +337,7 @@ const MessageContextMenu: FC<OwnProps> = ({
isCurrentUserPremium={isCurrentUserPremium} isCurrentUserPremium={isCurrentUserPremium}
canPlayAnimatedEmojis={canPlayAnimatedEmojis} canPlayAnimatedEmojis={canPlayAnimatedEmojis}
onShowMore={handleOpenReactionPicker} onShowMore={handleOpenReactionPicker}
className={buildClassName(areItemsHidden && 'ReactionSelector-hidden')}
/> />
)} )}

View File

@ -6,7 +6,7 @@ import type {
} from '../../../api/types'; } from '../../../api/types';
import type { IAnchorPosition } from '../../../types'; import type { IAnchorPosition } from '../../../types';
import { createClassNameBuilder } from '../../../util/buildClassName'; import buildClassName, { createClassNameBuilder } from '../../../util/buildClassName';
import { import {
isSameReaction, canSendReaction, getReactionUniqueKey, sortReactions, isSameReaction, canSendReaction, getReactionUniqueKey, sortReactions,
} from '../../../global/helpers'; } from '../../../global/helpers';
@ -32,6 +32,7 @@ type OwnProps = {
isCurrentUserPremium?: boolean; isCurrentUserPremium?: boolean;
canPlayAnimatedEmojis?: boolean; canPlayAnimatedEmojis?: boolean;
onShowMore: (position: IAnchorPosition) => void; onShowMore: (position: IAnchorPosition) => void;
className?: string;
}; };
const cn = createClassNameBuilder('ReactionSelector'); const cn = createClassNameBuilder('ReactionSelector');
@ -48,6 +49,7 @@ const ReactionSelector: FC<OwnProps> = ({
canPlayAnimatedEmojis, canPlayAnimatedEmojis,
onToggleReaction, onToggleReaction,
onShowMore, onShowMore,
className,
}) => { }) => {
// eslint-disable-next-line no-null/no-null // eslint-disable-next-line no-null/no-null
const ref = useRef<HTMLDivElement>(null); const ref = useRef<HTMLDivElement>(null);
@ -94,7 +96,7 @@ const ReactionSelector: FC<OwnProps> = ({
if (!reactionsToRender.length) return undefined; if (!reactionsToRender.length) return undefined;
return ( return (
<div className={cn('&', lang.isRtl && 'isRtl')} ref={ref}> <div className={buildClassName(cn('&', lang.isRtl && 'isRtl'), className)} ref={ref}>
<div className={cn('bubble-small', lang.isRtl && 'isRtl')} /> <div className={cn('bubble-small', lang.isRtl && 'isRtl')} />
<div className={cn('items-wrapper')}> <div className={cn('items-wrapper')}>
<div className={cn('bubble-big', lang.isRtl && 'isRtl')} /> <div className={cn('bubble-big', lang.isRtl && 'isRtl')} />