diff --git a/web/chat/message.react.js b/web/chat/message.react.js
--- a/web/chat/message.react.js
+++ b/web/chat/message.react.js
@@ -47,14 +47,7 @@
message = ;
} else {
invariant(item.robotext, "Flow can't handle our fancy types :(");
- message = (
-
- );
+ message = ;
}
return (
diff --git a/web/chat/robotext-message.react.js b/web/chat/robotext-message.react.js
--- a/web/chat/robotext-message.react.js
+++ b/web/chat/robotext-message.react.js
@@ -1,15 +1,15 @@
// @flow
-import classNames from 'classnames';
+// import classNames from 'classnames';
import * as React from 'react';
import { useDispatch } from 'react-redux';
import { type RobotextChatMessageInfoItem } from 'lib/selectors/chat-selectors';
import { threadInfoSelector } from 'lib/selectors/thread-selectors';
import { splitRobotext, parseRobotextEntity } from 'lib/shared/message-utils';
-import { useSidebarExistsOrCanBeCreated } from 'lib/shared/thread-utils';
import type { Dispatch } from 'lib/types/redux-types';
import { type ThreadInfo } from 'lib/types/thread-types';
+import { longAbsoluteDate } from 'lib/utils/date-utils';
import Markdown from '../markdown/markdown.react';
import { linkRules } from '../markdown/rules.react';
@@ -17,37 +17,42 @@
import { updateNavInfoActionType } from '../types/nav-types';
import { InlineSidebar } from './inline-sidebar.react';
import MessageTooltip from './message-tooltip.react';
-import type {
- MessagePositionInfo,
- OnMessagePositionWithContainerInfo,
-} from './position-types';
import css from './robotext-message.css';
-import { tooltipPositions } from './tooltip-utils';
+import { useTooltipContext } from './tooltip-provider';
+import {
+ calculateTooltipSize,
+ findTooltipPosition,
+ getMessageActionTooltipStyle,
+ tooltipPositions,
+ useRobotextMessageTooltipActions,
+} from './tooltip-utils';
-// eslint-disable-next-line no-unused-vars
const availableTooltipPositionsForRobotext = [
- tooltipPositions.RIGHT_TOP,
- tooltipPositions.RIGHT,
tooltipPositions.LEFT,
+ tooltipPositions.LEFT_TOP,
+ tooltipPositions.LEFT_BOTTOM,
+ tooltipPositions.RIGHT,
+ tooltipPositions.RIGHT_TOP,
+ tooltipPositions.RIGHT_BOTTOM,
];
type BaseProps = {
+item: RobotextChatMessageInfoItem,
+threadInfo: ThreadInfo,
- +setMouseOverMessagePosition: (
- messagePositionInfo: MessagePositionInfo,
- ) => void,
- +mouseOverMessagePosition: ?OnMessagePositionWithContainerInfo,
};
type Props = {
...BaseProps,
- // Redux state
- +sidebarExistsOrCanBeCreated: boolean,
+ +onMouseLeave: ?() => mixed,
+ +onMouseEnter: (event: SyntheticEvent
) => mixed,
+ containsInlineSidebar: boolean,
};
class RobotextMessage extends React.PureComponent {
render() {
let inlineSidebar;
- if (this.props.item.threadCreatedFromMessage) {
+ if (
+ this.props.containsInlineSidebar &&
+ this.props.item.threadCreatedFromMessage
+ ) {
inlineSidebar = (
;
- }
-
- let messageTooltipLinks;
- if (messageTooltip) {
- messageTooltipLinks = (
-
- {messageTooltip}
-
- );
- }
-
return (
{this.linkedRobotext()}
- {messageTooltipLinks}
{inlineSidebar}
@@ -131,25 +110,7 @@
return textParts;
}
-
- onMouseEnter = (event: SyntheticEvent
) => {
- const { item } = this.props;
- const rect = event.currentTarget.getBoundingClientRect();
- const { top, bottom, left, right, height, width } = rect;
- const messagePosition = { top, bottom, left, right, height, width };
- this.props.setMouseOverMessagePosition({
- type: 'on',
- item,
- messagePosition,
- });
- };
-
- onMouseLeave = () => {
- const { item } = this.props;
- this.props.setMouseOverMessagePosition({ type: 'off', item });
- };
}
-
type BaseInnerThreadEntityProps = {
+id: string,
+name: string,
@@ -198,14 +159,86 @@
const ConnectedRobotextMessage: React.ComponentType = React.memo(
function ConnectedRobotextMessage(props) {
- const sidebarExistsOrCanBeCreated = useSidebarExistsOrCanBeCreated(
- props.threadInfo,
- props.item,
+ const { item, threadInfo } = props;
+ const [
+ onMouseLeaveCallback,
+ setOnMouseLeaveCallback,
+ ] = React.useState() => mixed>(null);
+
+ const { renderTooltip } = useTooltipContext();
+
+ const containsInlineSidebar = !!props.item.threadCreatedFromMessage;
+
+ const timeZone = useSelector(state => state.timeZone);
+
+ const messageTimestamp = React.useMemo(() => {
+ const time = props.item.messageInfo.time;
+ return longAbsoluteDate(time, timeZone);
+ }, [props.item.messageInfo.time, timeZone]);
+
+ const tooltipActions = useRobotextMessageTooltipActions(item, threadInfo);
+
+ const tooltip = React.useMemo(
+ () => (
+
+ ),
+ [messageTimestamp, tooltipActions],
+ );
+
+ const onMouseEnter = React.useCallback(
+ (event: SyntheticEvent) => {
+ const rect = event.currentTarget.getBoundingClientRect();
+ const { top, bottom, left, right, height, width } = rect;
+ const messagePosition = { top, bottom, left, right, height, width };
+
+ if (renderTooltip) {
+ const tooltipLabels = tooltipActions.map(action => action.label);
+ const tooltipSize = calculateTooltipSize({
+ tooltipLabels,
+ timestamp: messageTimestamp,
+ });
+ const tooltipPosition = findTooltipPosition({
+ sourcePositionInfo: messagePosition,
+ tooltipSize,
+ availablePositions: availableTooltipPositionsForRobotext,
+ preventDisplayingBelowSource: containsInlineSidebar,
+ });
+ if (!tooltipPosition) {
+ return;
+ }
+ const tooltipPositionStyle = getMessageActionTooltipStyle({
+ tooltipPosition,
+ sourcePositionInfo: messagePosition,
+ tooltipSize: tooltipSize,
+ });
+
+ const renderTooltipResult = renderTooltip({
+ newNode: tooltip,
+ tooltipPosition: tooltipPositionStyle,
+ });
+ if (renderTooltipResult) {
+ const { onMouseLeaveCallback: callback } = renderTooltipResult;
+ setOnMouseLeaveCallback((() => callback: () => () => mixed));
+ }
+ }
+ },
+ [
+ containsInlineSidebar,
+ messageTimestamp,
+ renderTooltip,
+ tooltip,
+ tooltipActions,
+ ],
);
return (
);
},