diff --git a/native/chat/message-header.react.js b/native/chat/message-header.react.js
index c791666e4..1efb3b5a7 100644
--- a/native/chat/message-header.react.js
+++ b/native/chat/message-header.react.js
@@ -1,82 +1,83 @@
// @flow
import * as React from 'react';
import { View } from 'react-native';
-import { stringForUser } from 'lib/shared/user-utils';
+import { useStringForUser } from 'lib/hooks/ens-cache';
import { SingleLine } from '../components/single-line.react';
import { useStyles } from '../themes/colors';
import type { ChatMessageInfoItemWithHeight } from '../types/chat-types';
import { clusterEndHeight } from './chat-constants';
import type { DisplayType } from './timestamp.react';
import { Timestamp, timestampHeight } from './timestamp.react';
type Props = {
+item: ChatMessageInfoItemWithHeight,
+focused: boolean,
+display: DisplayType,
};
function MessageHeader(props: Props): React.Node {
const styles = useStyles(unboundStyles);
const { item, focused, display } = props;
const { creator, time } = item.messageInfo;
const { isViewer } = creator;
const modalDisplay = display === 'modal';
+ const shouldShowUsername = !isViewer && (modalDisplay || item.startsCluster);
+ const stringForUser = useStringForUser(shouldShowUsername ? creator : null);
+
let authorName = null;
- if (!isViewer && (modalDisplay || item.startsCluster)) {
+ if (stringForUser) {
const style = [styles.authorName];
if (modalDisplay) {
style.push(styles.modal);
}
- authorName = (
- {stringForUser(creator)}
- );
+ authorName = {stringForUser};
}
const timestamp =
modalDisplay || item.startsConversation ? (
) : null;
let style = null;
if (focused && !modalDisplay) {
let topMargin = 0;
if (!item.startsCluster && !item.messageInfo.creator.isViewer) {
topMargin += authorNameHeight + clusterEndHeight;
}
if (!item.startsConversation) {
topMargin += timestampHeight;
}
style = { marginTop: topMargin };
}
return (
{timestamp}
{authorName}
);
}
const authorNameHeight = 25;
const unboundStyles = {
authorName: {
bottom: 0,
color: 'listBackgroundSecondaryLabel',
fontSize: 14,
height: authorNameHeight,
marginLeft: 12,
marginRight: 7,
paddingHorizontal: 12,
paddingVertical: 4,
},
modal: {
// high contrast framed against OverlayNavigator-dimmed background
color: 'white',
},
};
export { MessageHeader, authorNameHeight };
diff --git a/web/chat/composed-message.react.js b/web/chat/composed-message.react.js
index 0bd0f4e78..4889dfc3e 100644
--- a/web/chat/composed-message.react.js
+++ b/web/chat/composed-message.react.js
@@ -1,194 +1,199 @@
// @flow
import classNames from 'classnames';
import * as React from 'react';
import {
Circle as CircleIcon,
CheckCircle as CheckCircleIcon,
XCircle as XCircleIcon,
} from 'react-feather';
+import { useStringForUser } from 'lib/hooks/ens-cache';
import { type ChatMessageInfoItem } from 'lib/selectors/chat-selectors';
-import { stringForUser } from 'lib/shared/user-utils';
import { assertComposableMessageType } from 'lib/types/message-types';
import { type ThreadInfo } from 'lib/types/thread-types';
import { type InputState, InputStateContext } from '../input/input-state';
import { tooltipPositions, useMessageTooltip } from '../utils/tooltip-utils';
import css from './chat-message-list.css';
import FailedSend from './failed-send.react';
import InlineEngagement from './inline-engagement.react';
const availableTooltipPositionsForViewerMessage = [
tooltipPositions.LEFT,
tooltipPositions.LEFT_BOTTOM,
tooltipPositions.LEFT_TOP,
tooltipPositions.RIGHT,
tooltipPositions.RIGHT_BOTTOM,
tooltipPositions.RIGHT_TOP,
tooltipPositions.BOTTOM,
tooltipPositions.TOP,
];
const availableTooltipPositionsForNonViewerMessage = [
tooltipPositions.RIGHT,
tooltipPositions.RIGHT_BOTTOM,
tooltipPositions.RIGHT_TOP,
tooltipPositions.LEFT,
tooltipPositions.LEFT_BOTTOM,
tooltipPositions.LEFT_TOP,
tooltipPositions.BOTTOM,
tooltipPositions.TOP,
];
type BaseProps = {
+item: ChatMessageInfoItem,
+threadInfo: ThreadInfo,
+sendFailed: boolean,
+children: React.Node,
+fixedWidth?: boolean,
+borderRadius: number,
};
type BaseConfig = React.Config;
type Props = {
...BaseProps,
// withInputState
+inputState: ?InputState,
+onMouseLeave: ?() => mixed,
+onMouseEnter: (event: SyntheticEvent) => mixed,
+containsInlineEngagement: boolean,
+ +stringForUser: ?string,
};
class ComposedMessage extends React.PureComponent {
static defaultProps: { +borderRadius: number } = {
borderRadius: 8,
};
render(): React.Node {
assertComposableMessageType(this.props.item.messageInfo.type);
const { borderRadius, item, threadInfo } = this.props;
const { id, creator } = item.messageInfo;
const threadColor = threadInfo.color;
const { isViewer } = creator;
const contentClassName = classNames({
[css.content]: true,
[css.viewerContent]: isViewer,
[css.nonViewerContent]: !isViewer,
});
const messageBoxContainerClassName = classNames({
[css.messageBoxContainer]: true,
[css.fixedWidthMessageBoxContainer]: this.props.fixedWidth,
});
const messageBoxClassName = classNames({
[css.messageBox]: true,
[css.fixedWidthMessageBox]: this.props.fixedWidth,
});
const messageBoxStyle = {
borderTopRightRadius: isViewer && !item.startsCluster ? 0 : borderRadius,
borderBottomRightRadius: isViewer && !item.endsCluster ? 0 : borderRadius,
borderTopLeftRadius: !isViewer && !item.startsCluster ? 0 : borderRadius,
borderBottomLeftRadius: !isViewer && !item.endsCluster ? 0 : borderRadius,
};
let authorName = null;
- if (!isViewer && item.startsCluster) {
- authorName = (
- {stringForUser(creator)}
- );
+ const { stringForUser } = this.props;
+ if (stringForUser) {
+ authorName = {stringForUser};
}
let deliveryIcon = null;
let failedSendInfo = null;
if (isViewer) {
let deliveryIconSpan;
let deliveryIconColor = threadColor;
if (id !== null && id !== undefined) {
deliveryIconSpan = ;
} else if (this.props.sendFailed) {
deliveryIconSpan = ;
deliveryIconColor = 'FF0000';
failedSendInfo = ;
} else {
deliveryIconSpan = ;
}
deliveryIcon = (
{deliveryIconSpan}
);
}
let inlineEngagement = null;
if (
(this.props.containsInlineEngagement && item.threadCreatedFromMessage) ||
item.reactions.size > 0
) {
const positioning = isViewer ? 'right' : 'left';
inlineEngagement = (
);
}
return (
{authorName}
{failedSendInfo}
{inlineEngagement}
);
}
}
type ConnectedConfig = React.Config<
BaseProps,
typeof ComposedMessage.defaultProps,
>;
const ConnectedComposedMessage: React.ComponentType = React.memo(
function ConnectedComposedMessage(props) {
const { item, threadInfo } = props;
const inputState = React.useContext(InputStateContext);
- const isViewer = props.item.messageInfo.creator.isViewer;
+ const { creator } = props.item.messageInfo;
+ const { isViewer } = creator;
const availablePositions = isViewer
? availableTooltipPositionsForViewerMessage
: availableTooltipPositionsForNonViewerMessage;
const containsInlineEngagement = !!item.threadCreatedFromMessage;
const { onMouseLeave, onMouseEnter } = useMessageTooltip({
item,
threadInfo,
availablePositions,
});
+ const shouldShowUsername = !isViewer && item.startsCluster;
+ const stringForUser = useStringForUser(shouldShowUsername ? creator : null);
+
return (
);
},
);
export default ConnectedComposedMessage;