Page MenuHomePhabricator

D6634.id23358.diff
No OneTemporary

D6634.id23358.diff

diff --git a/web/chat/message-tooltip.css b/web/chat/message-tooltip.css
--- a/web/chat/message-tooltip.css
+++ b/web/chat/message-tooltip.css
@@ -1,18 +1,9 @@
-div.container {
- display: flex;
- flex-direction: row;
-}
-
-div.containerLeftAlign,
-div.containerCenterAlign {
- flex-direction: row-reverse;
-}
-
div.messageTooltipContainer {
display: flex;
flex-direction: column;
align-items: center;
font-size: var(--s-font-14);
+ padding: 8px 0;
}
div.messageActionContainer {
@@ -71,3 +62,7 @@
div.rightTooltipAlign {
align-items: flex-end;
}
+
+div.emojiKeyboard {
+ position: absolute;
+}
diff --git a/web/chat/message-tooltip.react.js b/web/chat/message-tooltip.react.js
--- a/web/chat/message-tooltip.react.js
+++ b/web/chat/message-tooltip.react.js
@@ -15,15 +15,23 @@
tooltipStyle,
} from './chat-constants.js';
import css from './message-tooltip.css';
-import { useSendReaction } from './reaction-message-utils.js';
+import {
+ useSendReaction,
+ getEmojiKeyboardPosition,
+} from './reaction-message-utils.js';
import { useTooltipContext } from './tooltip-provider.js';
import { useSelector } from '../redux/redux-utils.js';
-import { type MessageTooltipAction } from '../utils/tooltip-utils.js';
+import type {
+ MessageTooltipAction,
+ TooltipSize,
+ TooltipPositionStyle,
+} from '../utils/tooltip-utils.js';
type MessageTooltipProps = {
+actions: $ReadOnlyArray<MessageTooltipAction>,
+messageTimestamp: string,
- +alignment?: 'left' | 'center' | 'right',
+ +tooltipPositionStyle: TooltipPositionStyle,
+ +tooltipSize: TooltipSize,
+item: ChatMessageInfoItem,
+threadInfo: ThreadInfo,
};
@@ -31,15 +39,43 @@
const {
actions,
messageTimestamp,
- alignment = 'left',
+ tooltipPositionStyle,
+ tooltipSize,
item,
threadInfo,
} = props;
const { messageInfo, reactions } = item;
+ const { alignment = 'left' } = tooltipPositionStyle;
+
const [activeTooltipLabel, setActiveTooltipLabel] = React.useState<?string>();
- const { renderEmojiKeyboard } = useTooltipContext();
+ const { shouldRenderEmojiKeyboard } = useTooltipContext();
+
+ // emoji-mart actually doesn't render its contents until a useEffect runs:
+ // https://github.com/missive/emoji-mart/blob/d29728f7b4e295e46f9b64aa80335aa4a3c15b8e/packages/emoji-mart-react/react.tsx#L13-L19
+ // We need to measure the width/height of the picker, but because of this we
+ // need to do the measurement in our own useEffect, in order to guarantee it
+ // runs after emoji-mart's useEffect. To do this, we have to define two pieces
+ // of React state:
+ // - emojiKeyboardNode, which will get set by the emoji keyboard's ref and
+ // will trigger our useEffect
+ // - emojiKeyboardRenderedNode, which will get set in that useEffect and will
+ // trigger the rerendering of this component with the correct height/width
+
+ const [emojiKeyboardNode, setEmojiKeyboardNode] = React.useState(null);
+ const [emojiKeyboardRenderedNode, setEmojiKeyboardRenderedNode] =
+ React.useState(null);
+
+ React.useEffect(() => {
+ if (emojiKeyboardNode) {
+ // It would be more simple to just call getEmojiKeyboardPosition
+ // immediately here, but some quirk of emoji-mart causes the width of the
+ // node to be 0 here. If instead we wait until the next render of this
+ // component to check the width, it ends up being set correctly.
+ setEmojiKeyboardRenderedNode(emojiKeyboardNode);
+ }
+ }, [emojiKeyboardNode]);
const messageActionButtonsContainerClassName = classNames(
css.messageActionContainer,
@@ -113,6 +149,27 @@
);
}, [messageTimestamp, messageTooltipLabelStyle]);
+ const emojiKeyboardPosition = React.useMemo(
+ () =>
+ getEmojiKeyboardPosition(
+ emojiKeyboardRenderedNode,
+ tooltipPositionStyle,
+ tooltipSize,
+ ),
+ [emojiKeyboardRenderedNode, tooltipPositionStyle, tooltipSize],
+ );
+
+ const emojiKeyboardPositionStyle = React.useMemo(() => {
+ if (!emojiKeyboardPosition) {
+ return null;
+ }
+
+ return {
+ bottom: emojiKeyboardPosition.bottom,
+ left: emojiKeyboardPosition.left,
+ };
+ }, [emojiKeyboardPosition]);
+
const nextLocalID = useSelector(state => state.nextLocalID);
const localID = `${localIDPrefix}${nextLocalID}`;
@@ -133,21 +190,24 @@
);
const emojiKeyboard = React.useMemo(() => {
- if (!renderEmojiKeyboard) {
+ if (!shouldRenderEmojiKeyboard) {
return null;
}
- return <Picker data={data} onEmojiSelect={onEmojiSelect} />;
- }, [onEmojiSelect, renderEmojiKeyboard]);
+
+ return (
+ <div
+ ref={setEmojiKeyboardNode}
+ style={emojiKeyboardPositionStyle}
+ className={css.emojiKeyboard}
+ >
+ <Picker data={data} onEmojiSelect={onEmojiSelect} />
+ </div>
+ );
+ }, [emojiKeyboardPositionStyle, onEmojiSelect, shouldRenderEmojiKeyboard]);
const messageTooltipContainerStyle = React.useMemo(() => tooltipStyle, []);
const containerClassName = classNames({
- [css.container]: true,
- [css.containerLeftAlign]: alignment === 'left',
- [css.containerCenterAlign]: alignment === 'center',
- });
-
- const messageTooltipContainerClassNames = classNames({
[css.messageTooltipContainer]: true,
[css.leftTooltipAlign]: alignment === 'left',
[css.centerTooltipAlign]: alignment === 'center',
@@ -155,17 +215,14 @@
});
return (
- <div className={containerClassName}>
+ <>
{emojiKeyboard}
- <div
- className={messageTooltipContainerClassNames}
- style={messageTooltipContainerStyle}
- >
+ <div className={containerClassName} style={messageTooltipContainerStyle}>
<div style={messageTooltipTopLabelStyle}>{tooltipLabel}</div>
{tooltipButtons}
{tooltipTimestamp}
</div>
- </div>
+ </>
);
}
diff --git a/web/chat/tooltip-provider.js b/web/chat/tooltip-provider.js
--- a/web/chat/tooltip-provider.js
+++ b/web/chat/tooltip-provider.js
@@ -26,8 +26,8 @@
type TooltipContextType = {
+renderTooltip: (params: RenderTooltipParams) => RenderTooltipResult,
+clearTooltip: () => mixed,
- +renderEmojiKeyboard: boolean,
- +setRenderEmojiKeyboard: SetState<boolean>,
+ +shouldRenderEmojiKeyboard: boolean,
+ +setShouldRenderEmojiKeyboard: SetState<boolean>,
};
const TooltipContext: React.Context<TooltipContextType> =
@@ -38,8 +38,8 @@
updateTooltip: () => {},
}),
clearTooltip: () => {},
- renderEmojiKeyboard: false,
- setRenderEmojiKeyboard: () => {},
+ shouldRenderEmojiKeyboard: false,
+ setShouldRenderEmojiKeyboard: () => {},
});
type Props = {
@@ -53,7 +53,7 @@
const [tooltipNode, setTooltipNode] = React.useState<React.Node>(null);
const [tooltipPosition, setTooltipPosition] =
React.useState<?TooltipPositionStyle>(null);
- const [renderEmojiKeyboard, setRenderEmojiKeyboard] =
+ const [shouldRenderEmojiKeyboard, setShouldRenderEmojiKeyboard] =
React.useState<boolean>(false);
const clearTooltip = React.useCallback((tooltipToClose: symbol) => {
@@ -63,7 +63,7 @@
tooltipCancelTimer.current = null;
setTooltipNode(null);
setTooltipPosition(null);
- setRenderEmojiKeyboard(false);
+ setShouldRenderEmojiKeyboard(false);
tooltipSymbol.current = null;
}, []);
@@ -156,10 +156,10 @@
() => ({
renderTooltip,
clearTooltip: clearCurrentTooltip,
- renderEmojiKeyboard,
- setRenderEmojiKeyboard,
+ shouldRenderEmojiKeyboard,
+ setShouldRenderEmojiKeyboard,
}),
- [renderTooltip, clearCurrentTooltip, renderEmojiKeyboard],
+ [renderTooltip, clearCurrentTooltip, shouldRenderEmojiKeyboard],
);
return (
diff --git a/web/utils/tooltip-utils.js b/web/utils/tooltip-utils.js
--- a/web/utils/tooltip-utils.js
+++ b/web/utils/tooltip-utils.js
@@ -452,7 +452,7 @@
): ?MessageTooltipAction {
const { messageInfo } = item;
- const { setRenderEmojiKeyboard } = useTooltipContext();
+ const { setShouldRenderEmojiKeyboard } = useTooltipContext();
const canCreateReactionFromMessage = useCanCreateReactionFromMessage(
threadInfo,
@@ -467,10 +467,10 @@
const buttonContent = <CommIcon icon="emote-smile-filled" size={18} />;
const onClickReact = () => {
- if (!setRenderEmojiKeyboard) {
+ if (!setShouldRenderEmojiKeyboard) {
return;
}
- setRenderEmojiKeyboard(true);
+ setShouldRenderEmojiKeyboard(true);
};
return {
@@ -478,7 +478,7 @@
onClick: onClickReact,
label: 'React',
};
- }, [canCreateReactionFromMessage, setRenderEmojiKeyboard]);
+ }, [canCreateReactionFromMessage, setShouldRenderEmojiKeyboard]);
}
function useMessageTooltipActions(
@@ -548,13 +548,12 @@
tooltipSize,
});
- const { alignment } = tooltipPositionStyle;
-
const tooltip = (
<MessageTooltip
actions={tooltipActions}
messageTimestamp={messageTimestamp}
- alignment={alignment}
+ tooltipPositionStyle={tooltipPositionStyle}
+ tooltipSize={tooltipSize}
item={item}
threadInfo={threadInfo}
/>

File Metadata

Mime Type
text/plain
Expires
Wed, Dec 25, 12:20 AM (4 h, 32 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2701185
Default Alt Text
D6634.id23358.diff (9 KB)

Event Timeline