Message: Fix quick reaction position (#2969)

This commit is contained in:
Alexander Zinchuk 2023-04-15 13:51:28 +02:00
parent 180599f5d4
commit a27ec8243b
5 changed files with 46 additions and 27 deletions

View File

@ -80,6 +80,7 @@
opacity: 0;
transition: transform 0.2s ease-out, opacity 0.2s ease-out;
transition-delay: 0.2s;
z-index: 1;
&.visible {
opacity: 1 !important;

View File

@ -263,6 +263,9 @@ type ReactionsPosition =
'inside'
| 'outside'
| 'none';
type QuickReactionPosition =
'in-content'
| 'in-meta';
const NBSP = '\u00A0';
// eslint-disable-next-line max-len
@ -371,7 +374,7 @@ const Message: FC<OwnProps & StateProps> = ({
// eslint-disable-next-line no-null/no-null
const bottomMarkerRef = useRef<HTMLDivElement>(null);
// eslint-disable-next-line no-null/no-null
const contentRef = useRef<HTMLDivElement>(null);
const quickReactionRef = useRef<HTMLDivElement>(null);
const messageHeightRef = useRef(0);
@ -492,7 +495,7 @@ const Message: FC<OwnProps & StateProps> = ({
handleBeforeContextMenu,
chatId,
isContextMenuShown,
contentRef,
quickReactionRef,
isOwn,
isInDocumentGroupNotLast,
);
@ -641,6 +644,8 @@ const Message: FC<OwnProps & StateProps> = ({
reactionsPosition = 'none';
}
const quickReactionPosition: QuickReactionPosition = isCustomShape ? 'in-meta' : 'in-content';
useEnsureMessage(
isRepliesChat && message.replyToChatId ? message.replyToChatId : chatId,
hasReply ? message.replyToMessageId : undefined,
@ -788,6 +793,25 @@ const Message: FC<OwnProps & StateProps> = ({
);
}
function renderQuickReactionButton() {
if (!defaultReaction) return undefined;
return (
<div
className={buildClassName('quick-reaction', isQuickReactionVisible && !activeReactions && 'visible')}
onClick={handleSendQuickReaction}
ref={quickReactionRef}
>
<ReactionStaticEmoji
reaction={defaultReaction}
size={QUICK_REACTION_SIZE}
availableReactions={availableReactions}
observeIntersection={observeIntersectionForPlaying}
/>
</div>
);
}
function renderReactionsAndMeta() {
const meta = (
<MessageMeta
@ -798,6 +822,9 @@ const Message: FC<OwnProps & StateProps> = ({
outgoingStatus={outgoingStatus}
signature={signature}
withReactionOffset={reactionsPosition === 'inside'}
renderQuickReactionButton={
withQuickReactionButton && quickReactionPosition === 'in-meta' ? renderQuickReactionButton : undefined
}
availableReactions={availableReactions}
isTranslated={Boolean(requestedTranslationLanguage ? currentTranslatedText : undefined)}
onClick={handleMetaClick}
@ -1216,7 +1243,6 @@ const Message: FC<OwnProps & StateProps> = ({
className={buildClassName('message-content-wrapper', contentClassName.includes('text') && 'can-select-text')}
>
<div
ref={contentRef}
className={contentClassName}
style={style}
dir="auto"
@ -1256,19 +1282,7 @@ const Message: FC<OwnProps & StateProps> = ({
{withAppendix && (
<div className="svg-appendix" dangerouslySetInnerHTML={isOwn ? APPENDIX_OWN : APPENDIX_NOT_OWN} />
)}
{withQuickReactionButton && (
<div
className={buildClassName('quick-reaction', isQuickReactionVisible && !activeReactions && 'visible')}
onClick={handleSendQuickReaction}
>
<ReactionStaticEmoji
reaction={defaultReaction}
size={QUICK_REACTION_SIZE}
availableReactions={availableReactions}
observeIntersection={observeIntersectionForPlaying}
/>
</div>
)}
{withQuickReactionButton && quickReactionPosition === 'in-content' && renderQuickReactionButton()}
</div>
{message.inlineButtons && (
<InlineButtons message={message} onClick={clickBotInlineButton} />

View File

@ -168,8 +168,6 @@
.Message:not(.own) {
.custom-shape .with-subheader + .MessageMeta {
right: auto;
left: 13.25rem;
bottom: 0.25rem;
}
}

View File

@ -1,4 +1,4 @@
import type { FC } from '../../../lib/teact/teact';
import type { FC, TeactNode } from '../../../lib/teact/teact';
import React, { memo, useMemo } from '../../../lib/teact/teact';
import { getActions } from '../../../global';
@ -31,6 +31,7 @@ type OwnProps = {
isPinned?: boolean;
onClick: (e: React.MouseEvent<HTMLDivElement>) => void;
onTranslationClick: (e: React.MouseEvent<HTMLDivElement>) => void;
renderQuickReactionButton?: () => TeactNode | undefined;
onOpenThread: NoneToVoidFunction;
};
@ -40,6 +41,7 @@ const MessageMeta: FC<OwnProps> = ({
signature,
withReactionOffset,
repliesThreadInfo,
renderQuickReactionButton,
noReplies,
isTranslated,
isPinned,
@ -140,6 +142,7 @@ const MessageMeta: FC<OwnProps> = ({
{outgoingStatus && (
<MessageOutgoingStatus status={outgoingStatus} />
)}
{renderQuickReactionButton && renderQuickReactionButton()}
</span>
);
};

View File

@ -30,7 +30,7 @@ export default function useOuterHandlers(
handleBeforeContextMenu: (e: React.MouseEvent) => void,
chatId: string,
isContextMenuShown: boolean,
contentRef: RefObject<HTMLDivElement>,
quickReactionRef: RefObject<HTMLDivElement>,
isOwn: boolean,
shouldHandleMouseLeave: boolean,
) {
@ -46,16 +46,18 @@ export default function useOuterHandlers(
}
function handleMouseMove(e: React.MouseEvent) {
const container = contentRef.current;
if (!container) return;
const quickReactionContainer = quickReactionRef.current;
if (!quickReactionContainer) return;
const { clientX, clientY } = e;
const {
x, width, y, height,
} = container.getBoundingClientRect();
x: quickReactionX, width: quickReactionWidth, y: quickReactionY, height: quickReactionHeight,
} = quickReactionContainer.getBoundingClientRect();
const x = quickReactionX + quickReactionWidth / 2;
const y = quickReactionY + quickReactionHeight / 2;
const isVisibleX = Math.abs((isOwn ? (clientX - x) : (x + width - clientX))) < QUICK_REACTION_AREA_WIDTH;
const isVisibleY = Math.abs(y + height - clientY) < QUICK_REACTION_AREA_HEIGHT;
const isVisibleX = Math.abs(x - clientX) < QUICK_REACTION_AREA_WIDTH;
const isVisibleY = Math.abs(y - clientY) < QUICK_REACTION_AREA_HEIGHT;
if (isVisibleX && isVisibleY) {
markQuickReactionVisible();
} else {
@ -63,7 +65,8 @@ export default function useOuterHandlers(
}
}
function handleSendQuickReaction() {
function handleSendQuickReaction(e: React.MouseEvent<HTMLDivElement, MouseEvent>) {
e.stopPropagation();
sendDefaultReaction({
chatId,
messageId,