Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F32548558
D4912.1767184577.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
16 KB
Referenced Files
None
Subscribers
None
D4912.1767184577.diff
View Options
diff --git a/web/chat/chat-constants.js b/web/chat/chat-constants.js
new file mode 100644
--- /dev/null
+++ b/web/chat/chat-constants.js
@@ -0,0 +1,18 @@
+// @flow
+
+export const tooltipStyle = {
+ paddingLeft: 5,
+ paddingRight: 5,
+ rowGap: 3,
+};
+
+export const tooltipLabelStyle = {
+ padding: 6,
+ height: 20,
+};
+export const tooltipButtonStyle = {
+ paddingLeft: 6,
+ paddingRight: 6,
+ width: 30,
+ height: 38,
+};
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
@@ -124,31 +124,12 @@
this.props.mouseOverMessagePosition.item.messageInfo.id === id &&
(this.props.sidebarExistsOrCanBeCreated || this.props.canReply)
) {
+ // eslint-disable-next-line no-unused-vars
const availableTooltipPositions = isViewer
? availableTooltipPositionsForViewerMessage
: availableTooltipPositionsForNonViewerMessage;
- const messageTooltipProps = {
- threadInfo,
- item,
- availableTooltipPositions,
- mouseOverMessagePosition: this.props.mouseOverMessagePosition,
- };
-
- if (this.props.canReply) {
- messageTooltip = (
- <MessageTooltip
- {...messageTooltipProps}
- canReply={true}
- setMouseOverMessagePosition={this.props.setMouseOverMessagePosition}
- inputState={this.props.inputState}
- />
- );
- } else {
- messageTooltip = (
- <MessageTooltip {...messageTooltipProps} canReply={false} />
- );
- }
+ messageTooltip = <MessageTooltip messageTimestamp="" actions={[]} />;
}
let messageTooltipLinks;
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,9 +1,15 @@
+div.messageTooltipContainer {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ font-size: var(--s-font-14);
+}
+
div.messageActionContainer {
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
- padding: 0 6px;
background-color: var(--message-action-tooltip-bg);
border-radius: 8px;
width: fit-content;
@@ -17,66 +23,38 @@
padding: 10px 6px 6px;
color: var(--color-disabled);
}
+
div.messageActionButtons svg:hover {
cursor: pointer;
color: var(--fg);
}
-div.messageActionButtonsViewer {
- flex-direction: row;
- margin-left: auto;
- margin-right: 0;
-}
-div.messageActionButtonsNonViewer {
- flex-direction: row-reverse;
- margin-left: 0;
- margin-right: auto;
-}
-div.messageActionLinkIcon {
- margin: 0 3px;
- position: relative;
-}
-div.messageActionExtraAreaTop:before {
- height: 15px;
- width: 55px;
- content: '';
- position: absolute;
- bottom: -15px;
-}
-div.messageActionExtraAreaTopRight:before {
- right: 0;
-}
-div.messageActionExtraAreaTopLeft:before {
- left: 0;
-}
-div.messageActionExtraArea:before {
- height: 30px;
- width: 20px;
- content: '';
- position: absolute;
-}
-div.messageActionExtraAreaRight:before {
- left: -20px;
-}
-div.messageActionExtraAreaLeft:before {
- right: -20px;
+
+div.messageTooltipButton {
+ display: flex;
+ align-items: center;
+ justify-content: center;
}
-div.messageActionTopRightTooltip {
- bottom: 100%;
- margin-bottom: 1px;
- right: 0;
+
+div.messageTooltipLabel {
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ justify-content: center;
+ background-color: var(--message-action-tooltip-bg);
+ color: var(--tool-tip-color);
+ border-radius: 8px;
+ overflow: auto;
+ white-space: nowrap;
}
-div.messageActionTopLeftTooltip {
- bottom: 100%;
- margin-bottom: 1px;
- left: 0;
+
+div.leftTooltipAlign {
+ align-items: flex-start;
}
-div.messageActionLeftTooltip {
- top: 50%;
- right: 100%;
- margin-right: 7px;
+
+div.centerTooltipAlign {
+ align-items: center;
}
-div.messageActionRightTooltip {
- top: 50%;
- left: 100%;
- margin-left: 7px;
+
+div.rightTooltipAlign {
+ align-items: flex-end;
}
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
@@ -1,269 +1,115 @@
// @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 MessageReplyButton from './message-reply-button.react';
+ tooltipButtonStyle,
+ tooltipLabelStyle,
+ tooltipStyle,
+} from './chat-constants';
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';
+import { type MessageTooltipAction } from './tooltip-utils';
-type BaseMessageTooltipProps = {
- +threadInfo: ThreadInfo,
- +item: ChatMessageInfoItem,
- +availableTooltipPositions: $ReadOnlyArray<TooltipPosition>,
- +mouseOverMessagePosition: OnMessagePositionWithContainerInfo,
+type MessageTooltipProps = {
+ +actions: $ReadOnlyArray<MessageTooltipAction>,
+ +messageTimestamp: string,
+ +alignment?: 'left' | 'center' | 'right',
};
-type MessageTooltipProps =
- | {
- ...BaseMessageTooltipProps,
- +canReply: false,
- }
- | {
- ...BaseMessageTooltipProps,
- +canReply: true,
- +inputState: ?InputState,
- +setMouseOverMessagePosition: (
- messagePositionInfo: MessagePositionInfo,
- ) => void,
- };
function MessageTooltip(props: MessageTooltipProps): React.Node {
- const {
- threadInfo,
- item,
- availableTooltipPositions,
- mouseOverMessagePosition,
- canReply,
- } = props;
-
- const { containerPosition } = mouseOverMessagePosition;
-
- const [activeTooltip, setActiveTooltip] = React.useState<?TooltipType>();
- const [pointingTo, setPointingTo] = React.useState();
-
- const showTooltip = React.useCallback(
- (tooltipType: TooltipType, iconPosition: ItemAndContainerPositionInfo) => {
- if (activeTooltip) {
- return;
- }
- setActiveTooltip(tooltipType);
- setPointingTo(iconPosition);
- },
- [activeTooltip],
+ const { actions, messageTimestamp, alignment = 'left' } = props;
+ const [activeTooltipLabel, setActiveTooltipLabel] = React.useState<?string>();
+ const messageActionButtonsContainerClassName = classNames(
+ css.messageActionContainer,
+ css.messageActionButtons,
);
- const hideTooltip = React.useCallback(() => {
- setActiveTooltip(null);
- }, []);
+ const messageTooltipButtonStyle = React.useMemo(() => tooltipButtonStyle, []);
- const showSidebarTooltip = React.useCallback(
- (event: SyntheticEvent<HTMLDivElement>) => {
- const rect = event.currentTarget.getBoundingClientRect();
- const iconPosition = getIconPosition(rect, containerPosition);
- showTooltip('sidebar', iconPosition);
- },
- [containerPosition, showTooltip],
- );
-
- const showReplyTooltip = React.useCallback(
- (event: SyntheticEvent<HTMLDivElement>) => {
- 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<HTMLButtonElement>) => {
- if (threadCreatedFromMessage) {
- onThreadOpen(event);
- } else {
- onPendingSidebarOpen(event);
- }
- },
- [onPendingSidebarOpen, onThreadOpen, threadCreatedFromMessage],
- );
-
- const setMouseOverMessagePosition = props.canReply
- ? props.setMouseOverMessagePosition
- : null;
-
- const onReplyButtonClick = React.useCallback(() => {
- setMouseOverMessagePosition?.({
- type: 'off',
- item: item,
+ const tooltipButtons = React.useMemo(() => {
+ if (!actions || actions.length === 0) {
+ return null;
+ }
+ const buttons = actions.map(({ label, onClick, actionButtonContent }) => {
+ const onMouseEnter = () => {
+ setActiveTooltipLabel(label);
+ };
+ const onMouseLeave = () =>
+ setActiveTooltipLabel(oldLabel =>
+ label === oldLabel ? null : oldLabel,
+ );
+
+ return (
+ <div
+ onMouseEnter={onMouseEnter}
+ onMouseLeave={onMouseLeave}
+ key={label}
+ onClick={onClick}
+ style={messageTooltipButtonStyle}
+ className={css.messageTooltipButton}
+ >
+ {actionButtonContent}
+ </div>
+ );
});
- }, [item, setMouseOverMessagePosition]);
-
- let tooltipText = '';
- if (activeTooltip === 'reply') {
- tooltipText = 'Reply';
- } else if (activeTooltip === 'sidebar') {
- tooltipText = threadCreatedFromMessage
- ? openSidebarText
- : createSidebarText;
- }
-
- let tooltipMenu = null;
- if (pointingTo && activeTooltip) {
- tooltipMenu = (
- <TooltipMenu
- availableTooltipPositions={availableTooltipPositions}
- targetPositionInfo={pointingTo}
- layoutPosition="relative"
- getStyle={getMessageActionTooltipStyle}
- >
- <TooltipTextItem text={tooltipText} />
- </TooltipMenu>
+ return (
+ <div className={messageActionButtonsContainerClassName}>{buttons}</div>
);
- }
+ }, [
+ actions,
+ messageActionButtonsContainerClassName,
+ messageTooltipButtonStyle,
+ ]);
+
+ const messageTooltipLabelStyle = React.useMemo(() => tooltipLabelStyle, []);
+ const messageTooltipTopLabelStyle = React.useMemo(
+ () => ({
+ height: `${tooltipLabelStyle.height + 2 * tooltipLabelStyle.padding}px`,
+ }),
+ [],
+ );
- let replyButton;
- if (canReply) {
- invariant(props.inputState, 'inputState must be set if replyButton exists');
- replyButton = (
- <div
- className={css.messageActionLinkIcon}
- onMouseEnter={showReplyTooltip}
- onMouseLeave={hideTooltip}
- >
- <MessageReplyButton
- messagePositionInfo={mouseOverMessagePosition}
- onReplyClick={onReplyButtonClick}
- inputState={props.inputState}
- />
- {activeTooltip === 'reply' ? tooltipMenu : null}
+ const tooltipLabel = React.useMemo(() => {
+ if (!activeTooltipLabel) {
+ return null;
+ }
+ return (
+ <div className={css.messageTooltipLabel} style={messageTooltipLabelStyle}>
+ {activeTooltipLabel}
</div>
);
- }
+ }, [activeTooltipLabel, messageTooltipLabelStyle]);
- const sidebarExistsOrCanBeCreated = useSidebarExistsOrCanBeCreated(
- threadInfo,
- item,
- );
-
- let sidebarButton;
- if (sidebarExistsOrCanBeCreated) {
- sidebarButton = (
- <div
- className={css.messageActionLinkIcon}
- onMouseEnter={showSidebarTooltip}
- onMouseLeave={hideTooltip}
- onClick={onSidebarButtonClick}
- >
- <CommIcon icon="sidebar-filled" size={16} />
- {activeTooltip === 'sidebar' ? tooltipMenu : null}
+ const tooltipTimestamp = React.useMemo(() => {
+ if (!messageTimestamp) {
+ return null;
+ }
+ return (
+ <div className={css.messageTooltipLabel} style={messageTooltipLabelStyle}>
+ {messageTimestamp}
</div>
);
- }
+ }, [messageTimestamp, messageTooltipLabelStyle]);
+
+ const messageTooltipContainerStyle = React.useMemo(() => tooltipStyle, []);
+
+ const containerClassNames = React.useMemo(
+ () =>
+ classNames(css.messageTooltipContainer, {
+ [css.leftTooltipAlign]: alignment === 'left',
+ [css.centerTooltipAlign]: alignment === 'center',
+ [css.rightTooltipAlign]: alignment === 'right',
+ }),
+ [alignment],
+ );
- const { isViewer } = messageInfo.creator;
- const messageActionButtonsContainerClassName = classNames({
- [css.messageActionContainer]: true,
- [css.messageActionButtons]: true,
- [css.messageActionButtonsViewer]: isViewer,
- [css.messageActionButtonsNonViewer]: !isViewer,
- });
return (
- <div>
- <div className={messageActionButtonsContainerClassName}>
- {sidebarButton}
- {replyButton}
- </div>
+ <div className={containerClassNames} style={messageTooltipContainerStyle}>
+ <div style={messageTooltipTopLabelStyle}>{tooltipLabel}</div>
+ {tooltipButtons}
+ {tooltipTimestamp}
</div>
);
}
-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;
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
@@ -24,6 +24,7 @@
import css from './robotext-message.css';
import { tooltipPositions } from './tooltip-utils';
+// eslint-disable-next-line no-unused-vars
const availableTooltipPositionsForRobotext = [
tooltipPositions.TOP_RIGHT,
tooltipPositions.RIGHT,
@@ -57,7 +58,7 @@
);
}
- const { item, threadInfo, sidebarExistsOrCanBeCreated } = this.props;
+ const { item, sidebarExistsOrCanBeCreated } = this.props;
const { id } = item.messageInfo;
let messageTooltip;
if (
@@ -65,15 +66,7 @@
this.props.mouseOverMessagePosition.item.messageInfo.id === id &&
sidebarExistsOrCanBeCreated
) {
- messageTooltip = (
- <MessageTooltip
- threadInfo={threadInfo}
- item={item}
- mouseOverMessagePosition={this.props.mouseOverMessagePosition}
- availableTooltipPositions={availableTooltipPositionsForRobotext}
- canReply={false}
- />
- );
+ messageTooltip = <MessageTooltip messageTimestamp="" actions={[]} />;
}
let messageTooltipLinks;
diff --git a/web/chat/tooltip-utils.js b/web/chat/tooltip-utils.js
--- a/web/chat/tooltip-utils.js
+++ b/web/chat/tooltip-utils.js
@@ -1,6 +1,7 @@
// @flow
import invariant from 'invariant';
+import * as React from 'react';
import { calculateMaxTextWidth } from '../utils/text-utils';
import type { ItemAndContainerPositionInfo } from './position-types';
@@ -24,6 +25,12 @@
export type TooltipPosition = $Values<typeof tooltipPositions>;
+export type MessageTooltipAction = {
+ +label: string,
+ +onClick: (SyntheticEvent<HTMLDivElement>) => mixed,
+ +actionButtonContent: React.Node,
+};
+
const sizeOfTooltipArrow = 10; // 7px arrow + 3px extra
const tooltipMenuItemHeight = 22; // 17px line-height + 5px padding bottom
const tooltipInnerTopPadding = 5; // 5px bottom is included in last item
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Wed, Dec 31, 12:36 PM (2 h, 42 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
5873497
Default Alt Text
D4912.1767184577.diff (16 KB)
Attached To
Mode
D4912: [web] Refactor `MessageTooltip` component
Attached
Detach File
Event Timeline
Log In to Comment