Page MenuHomePhabricator

D7308.id25728.diff
No OneTemporary

D7308.id25728.diff

diff --git a/web/CommIcon.react.js b/web/CommIcon.react.js
--- a/web/CommIcon.react.js
+++ b/web/CommIcon.react.js
@@ -15,7 +15,9 @@
| 'reply-filled'
| 'megaphone'
| 'copy-filled'
- | 'emote-smile-filled';
+ | 'emote-smile-filled'
+ | 'pin'
+ | 'unpin';
type CommIconProps = {
+icon: CommIcons,
diff --git a/web/chat/composed-message.react.js b/web/chat/composed-message.react.js
--- a/web/chat/composed-message.react.js
+++ b/web/chat/composed-message.react.js
@@ -20,7 +20,8 @@
import UserAvatar from '../components/user-avatar.react.js';
import { type InputState, InputStateContext } from '../input/input-state.js';
import { shouldRenderAvatars } from '../utils/avatar-utils.js';
-import { tooltipPositions, useMessageTooltip } from '../utils/tooltip-utils.js';
+import { useMessageTooltip } from '../utils/tooltip-action-utils.js';
+import { tooltipPositions } from '../utils/tooltip-utils.js';
const availableTooltipPositionsForViewerMessage = [
tooltipPositions.LEFT,
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
@@ -19,7 +19,8 @@
import { linkRules } from '../markdown/rules.react.js';
import { updateNavInfoActionType } from '../redux/action-types.js';
import { useSelector } from '../redux/redux-utils.js';
-import { tooltipPositions, useMessageTooltip } from '../utils/tooltip-utils.js';
+import { useMessageTooltip } from '../utils/tooltip-action-utils.js';
+import { tooltipPositions } from '../utils/tooltip-utils.js';
const availableTooltipPositionsForRobotext = [
tooltipPositions.LEFT,
diff --git a/web/modals/chat/toggle-pin-modal.css b/web/modals/chat/toggle-pin-modal.css
new file mode 100644
diff --git a/web/modals/chat/toggle-pin-modal.react.js b/web/modals/chat/toggle-pin-modal.react.js
new file mode 100644
--- /dev/null
+++ b/web/modals/chat/toggle-pin-modal.react.js
@@ -0,0 +1,18 @@
+// @flow
+
+import * as React from 'react';
+
+import type { ChatMessageInfoItem } from 'lib/selectors/chat-selectors.js';
+import type { ThreadInfo } from 'lib/types/thread-types.js';
+
+type TogglePinModalProps = {
+ +item: ChatMessageInfoItem,
+ +threadInfo: ThreadInfo,
+};
+
+// eslint-disable-next-line no-unused-vars
+function TogglePinModal(props: TogglePinModalProps): React.Node {
+ return <></>;
+}
+
+export default TogglePinModal;
diff --git a/web/utils/tooltip-utils.js b/web/utils/tooltip-action-utils.js
copy from web/utils/tooltip-utils.js
copy to web/utils/tooltip-action-utils.js
--- a/web/utils/tooltip-utils.js
+++ b/web/utils/tooltip-action-utils.js
@@ -4,6 +4,7 @@
import _debounce from 'lodash/debounce.js';
import * as React from 'react';
+import { useModalContext } from 'lib/components/modal-provider.react.js';
import type { ChatMessageInfoItem } from 'lib/selectors/chat-selectors.js';
import { createMessageReply } from 'lib/shared/message-utils.js';
import { useCanCreateReactionFromMessage } from 'lib/shared/reaction-utils.js';
@@ -19,325 +20,24 @@
import { threadPermissions } from 'lib/types/thread-types.js';
import { longAbsoluteDate } from 'lib/utils/date-utils.js';
-import { getAppContainerPositionInfo } from './window-utils.js';
import {
- tooltipButtonStyle,
- tooltipLabelStyle,
- tooltipStyle,
-} from '../chat/chat-constants.js';
+ type MessageTooltipAction,
+ findTooltipPosition,
+ getMessageActionTooltipStyle,
+ calculateTooltipSize,
+ type TooltipSize,
+ type TooltipPosition,
+} from './tooltip-utils.js';
import MessageTooltip from '../chat/message-tooltip.react.js';
import type { PositionInfo } from '../chat/position-types.js';
import { useTooltipContext } from '../chat/tooltip-provider.js';
import CommIcon from '../CommIcon.react.js';
import { InputStateContext } from '../input/input-state.js';
+import TogglePinModal from '../modals/chat/toggle-pin-modal.react.js';
import {
useOnClickPendingSidebar,
useOnClickThread,
} from '../selectors/thread-selectors.js';
-import { calculateMaxTextWidth } from '../utils/text-utils.js';
-
-export const tooltipPositions = Object.freeze({
- LEFT: 'left',
- RIGHT: 'right',
- LEFT_BOTTOM: 'left-bottom',
- RIGHT_BOTTOM: 'right-bottom',
- LEFT_TOP: 'left-top',
- RIGHT_TOP: 'right-top',
- TOP: 'top',
- BOTTOM: 'bottom',
-});
-
-export type TooltipSize = {
- +height: number,
- +width: number,
-};
-
-export type TooltipPositionStyle = {
- +anchorPoint: {
- +x: number,
- +y: number,
- },
- +verticalPosition: 'top' | 'bottom',
- +horizontalPosition: 'left' | 'right',
- +alignment: 'left' | 'center' | 'right',
-};
-
-export type TooltipPosition = $Values<typeof tooltipPositions>;
-
-export type MessageTooltipAction = {
- +label: string,
- +onClick: (SyntheticEvent<HTMLDivElement>) => mixed,
- +actionButtonContent: React.Node,
-};
-
-const font =
- '14px "Inter", -apple-system, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", ' +
- '"Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", ui-sans-serif';
-
-type FindTooltipPositionArgs = {
- +sourcePositionInfo: PositionInfo,
- +tooltipSize: TooltipSize,
- +availablePositions: $ReadOnlyArray<TooltipPosition>,
- +defaultPosition: TooltipPosition,
- +preventDisplayingBelowSource?: boolean,
-};
-
-function findTooltipPosition({
- sourcePositionInfo,
- tooltipSize,
- availablePositions,
- defaultPosition,
- preventDisplayingBelowSource,
-}: FindTooltipPositionArgs): TooltipPosition {
- const appContainerPositionInfo = getAppContainerPositionInfo();
-
- if (!appContainerPositionInfo) {
- return defaultPosition;
- }
-
- const pointingTo = sourcePositionInfo;
- const {
- top: containerTop,
- left: containerLeft,
- right: containerRight,
- bottom: containerBottom,
- } = appContainerPositionInfo;
-
- const tooltipWidth = tooltipSize.width;
- const tooltipHeight = tooltipSize.height;
-
- const canBeDisplayedOnLeft = containerLeft + tooltipWidth <= pointingTo.left;
- const canBeDisplayedOnRight =
- tooltipWidth + pointingTo.right <= containerRight;
-
- const willCoverSidebarOnTopSideways =
- preventDisplayingBelowSource &&
- pointingTo.top + tooltipHeight > pointingTo.bottom;
-
- const canBeDisplayedOnTopSideways =
- pointingTo.top >= containerTop &&
- pointingTo.top + tooltipHeight <= containerBottom &&
- !willCoverSidebarOnTopSideways;
-
- const canBeDisplayedOnBottomSideways =
- pointingTo.bottom <= containerBottom &&
- pointingTo.bottom - tooltipHeight >= containerTop;
-
- const verticalCenterOfPointingTo = pointingTo.top + pointingTo.height / 2;
- const horizontalCenterOfPointingTo = pointingTo.left + pointingTo.width / 2;
-
- const willCoverSidebarInTheMiddleSideways =
- preventDisplayingBelowSource &&
- verticalCenterOfPointingTo + tooltipHeight / 2 > pointingTo.bottom;
-
- const canBeDisplayedInTheMiddleSideways =
- verticalCenterOfPointingTo - tooltipHeight / 2 >= containerTop &&
- verticalCenterOfPointingTo + tooltipHeight / 2 <= containerBottom &&
- !willCoverSidebarInTheMiddleSideways;
-
- const canBeDisplayedOnTop =
- pointingTo.top - tooltipHeight >= containerTop &&
- horizontalCenterOfPointingTo - tooltipWidth / 2 >= containerLeft &&
- horizontalCenterOfPointingTo + tooltipWidth / 2 <= containerRight;
-
- const canBeDisplayedOnBottom =
- pointingTo.bottom + tooltipHeight <= containerBottom &&
- horizontalCenterOfPointingTo - tooltipWidth / 2 >= containerLeft &&
- horizontalCenterOfPointingTo + tooltipWidth / 2 <= containerRight &&
- !preventDisplayingBelowSource;
-
- for (const tooltipPosition of availablePositions) {
- if (
- tooltipPosition === tooltipPositions.RIGHT &&
- canBeDisplayedOnRight &&
- canBeDisplayedInTheMiddleSideways
- ) {
- return tooltipPosition;
- } else if (
- tooltipPosition === tooltipPositions.RIGHT_BOTTOM &&
- canBeDisplayedOnRight &&
- canBeDisplayedOnBottomSideways
- ) {
- return tooltipPosition;
- } else if (
- tooltipPosition === tooltipPositions.LEFT &&
- canBeDisplayedOnLeft &&
- canBeDisplayedInTheMiddleSideways
- ) {
- return tooltipPosition;
- } else if (
- tooltipPosition === tooltipPositions.LEFT_BOTTOM &&
- canBeDisplayedOnLeft &&
- canBeDisplayedOnBottomSideways
- ) {
- return tooltipPosition;
- } else if (
- tooltipPosition === tooltipPositions.LEFT_TOP &&
- canBeDisplayedOnLeft &&
- canBeDisplayedOnTopSideways
- ) {
- return tooltipPosition;
- } else if (
- tooltipPosition === tooltipPositions.RIGHT_TOP &&
- canBeDisplayedOnRight &&
- canBeDisplayedOnTopSideways
- ) {
- return tooltipPosition;
- } else if (
- tooltipPosition === tooltipPositions.TOP &&
- canBeDisplayedOnTop
- ) {
- return tooltipPosition;
- } else if (
- tooltipPosition === tooltipPositions.BOTTOM &&
- canBeDisplayedOnBottom
- ) {
- return tooltipPosition;
- }
- }
- return defaultPosition;
-}
-
-type GetMessageActionTooltipStyleParams = {
- +sourcePositionInfo: PositionInfo,
- +tooltipSize: TooltipSize,
- +tooltipPosition: TooltipPosition,
-};
-
-function getMessageActionTooltipStyle({
- sourcePositionInfo,
- tooltipSize,
- tooltipPosition,
-}: GetMessageActionTooltipStyleParams): TooltipPositionStyle {
- if (tooltipPosition === tooltipPositions.RIGHT_TOP) {
- return {
- anchorPoint: {
- x: sourcePositionInfo.right,
- y: sourcePositionInfo.top,
- },
- horizontalPosition: 'right',
- verticalPosition: 'bottom',
- alignment: 'left',
- };
- } else if (tooltipPosition === tooltipPositions.LEFT_TOP) {
- return {
- anchorPoint: {
- x: sourcePositionInfo.left,
- y: sourcePositionInfo.top,
- },
- horizontalPosition: 'left',
- verticalPosition: 'bottom',
- alignment: 'right',
- };
- } else if (tooltipPosition === tooltipPositions.RIGHT_BOTTOM) {
- return {
- anchorPoint: {
- x: sourcePositionInfo.right,
- y: sourcePositionInfo.bottom,
- },
- horizontalPosition: 'right',
- verticalPosition: 'top',
- alignment: 'left',
- };
- } else if (tooltipPosition === tooltipPositions.LEFT_BOTTOM) {
- return {
- anchorPoint: {
- x: sourcePositionInfo.left,
- y: sourcePositionInfo.bottom,
- },
- horizontalPosition: 'left',
- verticalPosition: 'top',
- alignment: 'right',
- };
- } else if (tooltipPosition === tooltipPositions.LEFT) {
- return {
- anchorPoint: {
- x: sourcePositionInfo.left,
- y:
- sourcePositionInfo.top +
- sourcePositionInfo.height / 2 -
- tooltipSize.height / 2,
- },
- horizontalPosition: 'left',
- verticalPosition: 'bottom',
- alignment: 'right',
- };
- } else if (tooltipPosition === tooltipPositions.RIGHT) {
- return {
- anchorPoint: {
- x: sourcePositionInfo.right,
- y:
- sourcePositionInfo.top +
- sourcePositionInfo.height / 2 -
- tooltipSize.height / 2,
- },
- horizontalPosition: 'right',
- verticalPosition: 'bottom',
- alignment: 'left',
- };
- } else if (tooltipPosition === tooltipPositions.TOP) {
- return {
- anchorPoint: {
- x:
- sourcePositionInfo.left +
- sourcePositionInfo.width / 2 -
- tooltipSize.width / 2,
- y: sourcePositionInfo.top,
- },
- horizontalPosition: 'right',
- verticalPosition: 'top',
- alignment: 'center',
- };
- } else if (tooltipPosition === tooltipPositions.BOTTOM) {
- return {
- anchorPoint: {
- x:
- sourcePositionInfo.left +
- sourcePositionInfo.width / 2 -
- tooltipSize.width / 2,
- y: sourcePositionInfo.bottom,
- },
- horizontalPosition: 'right',
- verticalPosition: 'bottom',
- alignment: 'center',
- };
- }
- invariant(false, `Unexpected tooltip position value: ${tooltipPosition}`);
-}
-
-type CalculateTooltipSizeArgs = {
- +tooltipLabels: $ReadOnlyArray<string>,
- +timestamp: string,
-};
-
-function calculateTooltipSize({
- tooltipLabels,
- timestamp,
-}: CalculateTooltipSizeArgs): {
- +width: number,
- +height: number,
-} {
- const textWidth =
- calculateMaxTextWidth([...tooltipLabels, timestamp], font) +
- 2 * tooltipLabelStyle.padding;
- const buttonsWidth =
- tooltipLabels.length *
- (tooltipButtonStyle.width +
- tooltipButtonStyle.paddingLeft +
- tooltipButtonStyle.paddingRight);
- const width =
- Math.max(textWidth, buttonsWidth) +
- tooltipStyle.paddingLeft +
- tooltipStyle.paddingRight;
- const height =
- (tooltipLabelStyle.height + 2 * tooltipLabelStyle.padding) * 2 +
- tooltipStyle.rowGap * 2 +
- tooltipButtonStyle.height;
- return {
- width,
- height,
- };
-}
function useMessageTooltipSidebarAction(
item: ChatMessageInfoItem,
@@ -481,6 +181,38 @@
}, [canCreateReactionFromMessage, setShouldRenderEmojiKeyboard]);
}
+function useMessageTogglePinAction(
+ item: ChatMessageInfoItem,
+ threadInfo: ThreadInfo,
+): ?MessageTooltipAction {
+ const { pushModal } = useModalContext();
+ const { messageInfo, isPinned } = item;
+
+ const canTogglePin =
+ isComposableMessageType(messageInfo.type) &&
+ threadHasPermission(threadInfo, threadPermissions.MANAGE_PINS);
+
+ return React.useMemo(() => {
+ if (!canTogglePin) {
+ return null;
+ }
+
+ const iconName = isPinned ? 'unpin' : 'pin';
+
+ const buttonContent = <CommIcon icon={iconName} size={18} />;
+
+ const onClickTogglePin = () => {
+ pushModal(<TogglePinModal item={item} threadInfo={threadInfo} />);
+ };
+
+ return {
+ actionButtonContent: buttonContent,
+ onClick: onClickTogglePin,
+ label: isPinned ? 'Unpin' : 'Pin',
+ };
+ }, [canTogglePin, isPinned, pushModal, item, threadInfo]);
+}
+
function useMessageTooltipActions(
item: ChatMessageInfoItem,
threadInfo: ThreadInfo,
@@ -489,9 +221,17 @@
const replyAction = useMessageTooltipReplyAction(item, threadInfo);
const copyAction = useMessageCopyAction(item);
const reactAction = useMessageReactAction(item, threadInfo);
+ const togglePinAction = useMessageTogglePinAction(item, threadInfo);
return React.useMemo(
- () => [replyAction, sidebarAction, copyAction, reactAction].filter(Boolean),
- [replyAction, sidebarAction, copyAction, reactAction],
+ () =>
+ [
+ replyAction,
+ sidebarAction,
+ copyAction,
+ reactAction,
+ togglePinAction,
+ ].filter(Boolean),
+ [replyAction, sidebarAction, copyAction, reactAction, togglePinAction],
);
}
@@ -681,9 +421,6 @@
}
export {
- findTooltipPosition,
- calculateTooltipSize,
- getMessageActionTooltipStyle,
useMessageTooltipSidebarAction,
useMessageTooltipReplyAction,
useMessageReactAction,
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
@@ -1,39 +1,15 @@
// @flow
import invariant from 'invariant';
-import _debounce from 'lodash/debounce.js';
import * as React from 'react';
-import type { ChatMessageInfoItem } from 'lib/selectors/chat-selectors.js';
-import { createMessageReply } from 'lib/shared/message-utils.js';
-import { useCanCreateReactionFromMessage } from 'lib/shared/reaction-utils.js';
-import {
- threadHasPermission,
- useSidebarExistsOrCanBeCreated,
-} from 'lib/shared/thread-utils.js';
-import {
- isComposableMessageType,
- messageTypes,
-} from 'lib/types/message-types.js';
-import type { ThreadInfo } from 'lib/types/thread-types.js';
-import { threadPermissions } from 'lib/types/thread-types.js';
-import { longAbsoluteDate } from 'lib/utils/date-utils.js';
-
import { getAppContainerPositionInfo } from './window-utils.js';
import {
tooltipButtonStyle,
tooltipLabelStyle,
tooltipStyle,
} from '../chat/chat-constants.js';
-import MessageTooltip from '../chat/message-tooltip.react.js';
import type { PositionInfo } from '../chat/position-types.js';
-import { useTooltipContext } from '../chat/tooltip-provider.js';
-import CommIcon from '../CommIcon.react.js';
-import { InputStateContext } from '../input/input-state.js';
-import {
- useOnClickPendingSidebar,
- useOnClickThread,
-} from '../selectors/thread-selectors.js';
import { calculateMaxTextWidth } from '../utils/text-utils.js';
export const tooltipPositions = Object.freeze({
@@ -339,354 +315,8 @@
};
}
-function useMessageTooltipSidebarAction(
- item: ChatMessageInfoItem,
- threadInfo: ThreadInfo,
-): ?MessageTooltipAction {
- const { threadCreatedFromMessage, messageInfo } = item;
- const sidebarExists = !!threadCreatedFromMessage;
- const sidebarExistsOrCanBeCreated = useSidebarExistsOrCanBeCreated(
- threadInfo,
- item,
- );
- const openThread = useOnClickThread(threadCreatedFromMessage);
- const openPendingSidebar = useOnClickPendingSidebar(messageInfo, threadInfo);
- return React.useMemo(() => {
- if (!sidebarExistsOrCanBeCreated) {
- return null;
- }
- const buttonContent = <CommIcon icon="sidebar-filled" size={16} />;
- const onClick = (event: SyntheticEvent<HTMLElement>) => {
- if (threadCreatedFromMessage) {
- openThread(event);
- } else {
- openPendingSidebar(event);
- }
- };
- return {
- actionButtonContent: buttonContent,
- onClick,
- label: sidebarExists ? 'Go to thread' : 'Create thread',
- };
- }, [
- openPendingSidebar,
- openThread,
- sidebarExists,
- sidebarExistsOrCanBeCreated,
- threadCreatedFromMessage,
- ]);
-}
-
-function useMessageTooltipReplyAction(
- item: ChatMessageInfoItem,
- threadInfo: ThreadInfo,
-): ?MessageTooltipAction {
- const { messageInfo } = item;
- const inputState = React.useContext(InputStateContext);
- invariant(inputState, 'inputState is required');
- const { addReply } = inputState;
- return React.useMemo(() => {
- if (
- !isComposableMessageType(item.messageInfo.type) ||
- !threadHasPermission(threadInfo, threadPermissions.VOICED)
- ) {
- return null;
- }
- const buttonContent = <CommIcon icon="reply-filled" size={18} />;
- const onClick = () => {
- if (!messageInfo.text) {
- return;
- }
- addReply(createMessageReply(messageInfo.text));
- };
- return {
- actionButtonContent: buttonContent,
- onClick,
- label: 'Reply',
- };
- }, [addReply, item.messageInfo.type, messageInfo, threadInfo]);
-}
-
-const copiedMessageDurationMs = 2000;
-function useMessageCopyAction(
- item: ChatMessageInfoItem,
-): ?MessageTooltipAction {
- const { messageInfo } = item;
-
- const [successful, setSuccessful] = React.useState(false);
- const resetStatusAfterTimeout = React.useRef(
- _debounce(() => setSuccessful(false), copiedMessageDurationMs),
- );
-
- const onSuccess = React.useCallback(() => {
- setSuccessful(true);
- resetStatusAfterTimeout.current();
- }, []);
-
- React.useEffect(() => resetStatusAfterTimeout.current.cancel, []);
-
- return React.useMemo(() => {
- if (messageInfo.type !== messageTypes.TEXT) {
- return null;
- }
- const buttonContent = <CommIcon icon="copy-filled" size={18} />;
- const onClick = async () => {
- try {
- await navigator.clipboard.writeText(messageInfo.text);
- onSuccess();
- } catch (e) {
- setSuccessful(false);
- }
- };
- return {
- actionButtonContent: buttonContent,
- onClick,
- label: successful ? 'Copied!' : 'Copy',
- };
- }, [messageInfo.text, messageInfo.type, onSuccess, successful]);
-}
-
-function useMessageReactAction(
- item: ChatMessageInfoItem,
- threadInfo: ThreadInfo,
-): ?MessageTooltipAction {
- const { messageInfo } = item;
-
- const { setShouldRenderEmojiKeyboard } = useTooltipContext();
-
- const canCreateReactionFromMessage = useCanCreateReactionFromMessage(
- threadInfo,
- messageInfo,
- );
-
- return React.useMemo(() => {
- if (!canCreateReactionFromMessage) {
- return null;
- }
-
- const buttonContent = <CommIcon icon="emote-smile-filled" size={18} />;
-
- const onClickReact = () => {
- if (!setShouldRenderEmojiKeyboard) {
- return;
- }
- setShouldRenderEmojiKeyboard(true);
- };
-
- return {
- actionButtonContent: buttonContent,
- onClick: onClickReact,
- label: 'React',
- };
- }, [canCreateReactionFromMessage, setShouldRenderEmojiKeyboard]);
-}
-
-function useMessageTooltipActions(
- item: ChatMessageInfoItem,
- threadInfo: ThreadInfo,
-): $ReadOnlyArray<MessageTooltipAction> {
- const sidebarAction = useMessageTooltipSidebarAction(item, threadInfo);
- const replyAction = useMessageTooltipReplyAction(item, threadInfo);
- const copyAction = useMessageCopyAction(item);
- const reactAction = useMessageReactAction(item, threadInfo);
- return React.useMemo(
- () => [replyAction, sidebarAction, copyAction, reactAction].filter(Boolean),
- [replyAction, sidebarAction, copyAction, reactAction],
- );
-}
-
-type UseMessageTooltipArgs = {
- +availablePositions: $ReadOnlyArray<TooltipPosition>,
- +item: ChatMessageInfoItem,
- +threadInfo: ThreadInfo,
-};
-
-type UseMessageTooltipResult = {
- onMouseEnter: (event: SyntheticEvent<HTMLElement>) => void,
- onMouseLeave: ?() => mixed,
-};
-
-type CreateTooltipParams = {
- +tooltipMessagePosition: ?PositionInfo,
- +tooltipSize: TooltipSize,
- +availablePositions: $ReadOnlyArray<TooltipPosition>,
- +containsInlineEngagement: boolean,
- +tooltipActions: $ReadOnlyArray<MessageTooltipAction>,
- +messageTimestamp: string,
- +item: ChatMessageInfoItem,
- +threadInfo: ThreadInfo,
-};
-
-function createTooltip(params: CreateTooltipParams) {
- const {
- tooltipMessagePosition,
- tooltipSize,
- availablePositions,
- containsInlineEngagement,
- tooltipActions,
- messageTimestamp,
- item,
- threadInfo,
- } = params;
- if (!tooltipMessagePosition) {
- return;
- }
- const tooltipPosition = findTooltipPosition({
- sourcePositionInfo: tooltipMessagePosition,
- tooltipSize,
- availablePositions,
- defaultPosition: availablePositions[0],
- preventDisplayingBelowSource: containsInlineEngagement,
- });
- if (!tooltipPosition) {
- return;
- }
-
- const tooltipPositionStyle = getMessageActionTooltipStyle({
- tooltipPosition,
- sourcePositionInfo: tooltipMessagePosition,
- tooltipSize,
- });
-
- const tooltip = (
- <MessageTooltip
- actions={tooltipActions}
- messageTimestamp={messageTimestamp}
- tooltipPositionStyle={tooltipPositionStyle}
- tooltipSize={tooltipSize}
- item={item}
- threadInfo={threadInfo}
- />
- );
- return { tooltip, tooltipPositionStyle };
-}
-
-function useMessageTooltip({
- availablePositions,
- item,
- threadInfo,
-}: UseMessageTooltipArgs): UseMessageTooltipResult {
- const [onMouseLeave, setOnMouseLeave] = React.useState<?() => mixed>(null);
-
- const { renderTooltip } = useTooltipContext();
- const tooltipActions = useMessageTooltipActions(item, threadInfo);
-
- const containsInlineEngagement = !!item.threadCreatedFromMessage;
-
- const messageTimestamp = React.useMemo(() => {
- const time = item.messageInfo.time;
- return longAbsoluteDate(time);
- }, [item.messageInfo.time]);
-
- const tooltipSize = React.useMemo(() => {
- if (typeof document === 'undefined') {
- return {
- width: 0,
- height: 0,
- };
- }
- const tooltipLabels = tooltipActions.map(action => action.label);
- return calculateTooltipSize({
- tooltipLabels,
- timestamp: messageTimestamp,
- });
- }, [messageTimestamp, tooltipActions]);
-
- const updateTooltip = React.useRef();
- const [tooltipMessagePosition, setTooltipMessagePosition] = React.useState();
-
- const onMouseEnter = React.useCallback(
- (event: SyntheticEvent<HTMLElement>) => {
- if (!renderTooltip) {
- return;
- }
- const rect = event.currentTarget.getBoundingClientRect();
- const { top, bottom, left, right, height, width } = rect;
- const messagePosition = { top, bottom, left, right, height, width };
- setTooltipMessagePosition(messagePosition);
-
- const tooltipResult = createTooltip({
- tooltipMessagePosition,
- tooltipSize,
- availablePositions,
- containsInlineEngagement,
- tooltipActions,
- messageTimestamp,
- item,
- threadInfo,
- });
- if (!tooltipResult) {
- return;
- }
-
- const { tooltip, tooltipPositionStyle } = tooltipResult;
- const renderTooltipResult = renderTooltip({
- newNode: tooltip,
- tooltipPositionStyle,
- });
- if (renderTooltipResult) {
- const { onMouseLeaveCallback: callback } = renderTooltipResult;
- setOnMouseLeave((() => callback: () => () => mixed));
- updateTooltip.current = renderTooltipResult.updateTooltip;
- }
- },
- [
- availablePositions,
- containsInlineEngagement,
- item,
- messageTimestamp,
- renderTooltip,
- threadInfo,
- tooltipActions,
- tooltipMessagePosition,
- tooltipSize,
- ],
- );
-
- React.useEffect(() => {
- if (!updateTooltip.current) {
- return;
- }
-
- const tooltipResult = createTooltip({
- tooltipMessagePosition,
- tooltipSize,
- availablePositions,
- containsInlineEngagement,
- tooltipActions,
- messageTimestamp,
- item,
- threadInfo,
- });
- if (!tooltipResult) {
- return;
- }
-
- updateTooltip.current?.(tooltipResult.tooltip);
- }, [
- availablePositions,
- containsInlineEngagement,
- item,
- messageTimestamp,
- threadInfo,
- tooltipActions,
- tooltipMessagePosition,
- tooltipSize,
- ]);
-
- return {
- onMouseEnter,
- onMouseLeave,
- };
-}
-
export {
findTooltipPosition,
calculateTooltipSize,
getMessageActionTooltipStyle,
- useMessageTooltipSidebarAction,
- useMessageTooltipReplyAction,
- useMessageReactAction,
- useMessageTooltipActions,
- useMessageTooltip,
};

File Metadata

Mime Type
text/plain
Expires
Thu, Nov 28, 11:43 PM (19 h, 58 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2595181
Default Alt Text
D7308.id25728.diff (25 KB)

Event Timeline