diff --git a/web/chat/message-reply-button.react.js b/web/chat/message-reply-button.react.js
index 38600c47b..c74cdbfd8 100644
--- a/web/chat/message-reply-button.react.js
+++ b/web/chat/message-reply-button.react.js
@@ -1,36 +1,36 @@
// @flow
import invariant from 'invariant';
import * as React from 'react';
import { createMessageReply } from 'lib/shared/message-utils';
+import CommIcon from '../CommIcon.react.js';
import type { InputState } from '../input/input-state';
-import SWMansionIcon from '../SWMansionIcon.react';
import css from './chat-message-list.css';
import type { OnMessagePositionWithContainerInfo } from './position-types';
type Props = {
+messagePositionInfo: OnMessagePositionWithContainerInfo,
+onReplyClick: () => void,
+inputState: InputState,
};
function MessageReplyButton(props: Props): React.Node {
const { inputState, onReplyClick, messagePositionInfo } = props;
const { addReply } = inputState;
const { item } = messagePositionInfo;
const replyClicked = React.useCallback(() => {
invariant(item.messageInfo.text, 'text should be set in message clicked');
addReply(createMessageReply(item.messageInfo.text));
onReplyClick();
}, [addReply, item, onReplyClick]);
return (
-
+
);
}
export default MessageReplyButton;
diff --git a/web/chat/message-tooltip.react.js b/web/chat/message-tooltip.react.js
index 1cf32e00f..b6297db06 100644
--- a/web/chat/message-tooltip.react.js
+++ b/web/chat/message-tooltip.react.js
@@ -1,264 +1,264 @@
// @flow
import classNames from 'classnames';
import invariant from 'invariant';
import * as React from 'react';
import type { ChatMessageInfoItem } from 'lib/selectors/chat-selectors';
import { useSidebarExistsOrCanBeCreated } from 'lib/shared/thread-utils';
import type { ThreadInfo } from 'lib/types/thread-types';
+import CommIcon from '../CommIcon.react.js';
import type { InputState } from '../input/input-state';
import {
useOnClickThread,
useOnClickPendingSidebar,
} from '../selectors/nav-selectors';
-import SWMansionIcon from '../SWMansionIcon.react';
import MessageReplyButton from './message-reply-button.react';
import css from './message-tooltip.css';
import type {
ItemAndContainerPositionInfo,
MessagePositionInfo,
OnMessagePositionWithContainerInfo,
PositionInfo,
} from './position-types';
import { tooltipPositions, type TooltipPosition } from './tooltip-utils';
import {
TooltipMenu,
type TooltipStyle,
TooltipTextItem,
} from './tooltip.react';
const messageActionIconExcessVerticalWhitespace = 10;
const openSidebarText = 'Go to thread';
const createSidebarText = 'Create thread';
type TooltipType = 'sidebar' | 'reply';
type MessageTooltipProps = {
+threadInfo: ThreadInfo,
+item: ChatMessageInfoItem,
+availableTooltipPositions: $ReadOnlyArray,
+setMouseOverMessagePosition?: (
messagePositionInfo: MessagePositionInfo,
) => void,
+mouseOverMessagePosition: OnMessagePositionWithContainerInfo,
+canReply?: boolean,
+inputState?: ?InputState,
};
function MessageTooltip(props: MessageTooltipProps): React.Node {
const {
threadInfo,
item,
availableTooltipPositions,
setMouseOverMessagePosition,
mouseOverMessagePosition,
canReply,
inputState,
} = props;
const { containerPosition } = mouseOverMessagePosition;
const [activeTooltip, setActiveTooltip] = React.useState();
const [pointingTo, setPointingTo] = React.useState();
const showTooltip = React.useCallback(
(tooltipType: TooltipType, iconPosition: ItemAndContainerPositionInfo) => {
if (activeTooltip) {
return;
}
setActiveTooltip(tooltipType);
setPointingTo(iconPosition);
},
[activeTooltip],
);
const hideTooltip = React.useCallback(() => {
setActiveTooltip(null);
}, []);
const showSidebarTooltip = React.useCallback(
(event: SyntheticEvent) => {
const rect = event.currentTarget.getBoundingClientRect();
const iconPosition = getIconPosition(rect, containerPosition);
showTooltip('sidebar', iconPosition);
},
[containerPosition, showTooltip],
);
const showReplyTooltip = React.useCallback(
(event: SyntheticEvent) => {
const rect = event.currentTarget.getBoundingClientRect();
const iconPosition = getIconPosition(rect, containerPosition);
showTooltip('reply', iconPosition);
},
[containerPosition, showTooltip],
);
const { threadCreatedFromMessage, messageInfo } = item;
const onThreadOpen = useOnClickThread(threadCreatedFromMessage);
const onPendingSidebarOpen = useOnClickPendingSidebar(
messageInfo,
threadInfo,
);
const onSidebarButtonClick = React.useCallback(
(event: SyntheticEvent) => {
if (threadCreatedFromMessage) {
onThreadOpen(event);
} else {
onPendingSidebarOpen(event);
}
},
[onPendingSidebarOpen, onThreadOpen, threadCreatedFromMessage],
);
const onReplyButtonClick = React.useCallback(() => {
invariant(
setMouseOverMessagePosition,
'setMouseOverMessagePosition should be set if replyButton exists',
);
setMouseOverMessagePosition({ type: 'off', item: item });
}, [item, setMouseOverMessagePosition]);
let tooltipText = '';
if (activeTooltip === 'reply') {
tooltipText = 'Reply';
} else if (activeTooltip === 'sidebar') {
tooltipText = threadCreatedFromMessage
? openSidebarText
: createSidebarText;
}
let tooltipMenu = null;
if (pointingTo && activeTooltip) {
tooltipMenu = (
);
}
let replyButton;
if (canReply) {
invariant(inputState, 'inputState must be set if replyButton exists');
invariant(
mouseOverMessagePosition,
'mouseOverMessagePosition must be set if replyButton exists',
);
replyButton = (
{activeTooltip === 'reply' ? tooltipMenu : null}
);
}
const sidebarExistsOrCanBeCreated = useSidebarExistsOrCanBeCreated(
threadInfo,
item,
);
let sidebarButton;
if (sidebarExistsOrCanBeCreated) {
sidebarButton = (
-
+
{activeTooltip === 'sidebar' ? tooltipMenu : null}
);
}
const { isViewer } = messageInfo.creator;
const messageActionButtonsContainerClassName = classNames({
[css.messageActionContainer]: true,
[css.messageActionButtons]: true,
[css.messageActionButtonsViewer]: isViewer,
[css.messageActionButtonsNonViewer]: !isViewer,
});
return (
{sidebarButton}
{replyButton}
);
}
function getIconPosition(
rect: ClientRect,
containerPosition: PositionInfo,
): ItemAndContainerPositionInfo {
const { top, bottom, left, right, width, height } = rect;
return {
containerPosition,
itemPosition: {
top:
top - containerPosition.top + messageActionIconExcessVerticalWhitespace,
bottom:
bottom -
containerPosition.top -
messageActionIconExcessVerticalWhitespace,
left: left - containerPosition.left,
right: right - containerPosition.left,
width,
height: height - messageActionIconExcessVerticalWhitespace * 2,
},
};
}
function getMessageActionTooltipStyle(
tooltipPosition: TooltipPosition,
): TooltipStyle {
let className;
if (tooltipPosition === tooltipPositions.TOP_RIGHT) {
className = classNames(
css.messageActionTopRightTooltip,
css.messageActionExtraAreaTop,
css.messageActionExtraAreaTopRight,
);
} else if (tooltipPosition === tooltipPositions.TOP_LEFT) {
className = classNames(
css.messageActionTopLeftTooltip,
css.messageActionExtraAreaTop,
css.messageActionExtraAreaTopLeft,
);
} else if (tooltipPosition === tooltipPositions.RIGHT) {
className = classNames(
css.messageActionRightTooltip,
css.messageActionExtraArea,
css.messageActionExtraAreaRight,
);
} else if (tooltipPosition === tooltipPositions.LEFT) {
className = classNames(
css.messageActionLeftTooltip,
css.messageActionExtraArea,
css.messageActionExtraAreaLeft,
);
}
invariant(className, `${tooltipPosition} is not valid for message tooltip`);
return { className };
}
export default MessageTooltip;