Page MenuHomePhabricator

D7067.id24006.diff
No OneTemporary

D7067.id24006.diff

diff --git a/native/chat/chat-constants.js b/native/chat/chat-constants.js
--- a/native/chat/chat-constants.js
+++ b/native/chat/chat-constants.js
@@ -24,3 +24,5 @@
};
export const clusterEndHeight = 7;
+
+export const avatarOffset = 32;
diff --git a/native/chat/composed-message-width.js b/native/chat/composed-message-width.js
--- a/native/chat/composed-message-width.js
+++ b/native/chat/composed-message-width.js
@@ -1,6 +1,8 @@
// @flow
+import { avatarOffset } from './chat-constants.js';
import { useSelector } from '../redux/redux-utils.js';
+import { useShouldRenderAvatars } from '../utils/avatar-utils.js';
function useMessageListScreenWidth(): number {
return useSelector(state => {
@@ -12,6 +14,12 @@
// Keep sorta synced with styles.alignment/styles.messageBox in ComposedMessage
function useComposedMessageMaxWidth(): number {
const messageListScreenWidth = useMessageListScreenWidth();
+ const shouldRenderAvatars = useShouldRenderAvatars();
+
+ if (shouldRenderAvatars) {
+ return (messageListScreenWidth - 24 - avatarOffset) * 0.8;
+ }
+
return (messageListScreenWidth - 24) * 0.8;
}
diff --git a/native/chat/composed-message.react.js b/native/chat/composed-message.react.js
--- a/native/chat/composed-message.react.js
+++ b/native/chat/composed-message.react.js
@@ -6,6 +6,7 @@
import { StyleSheet, View } from 'react-native';
import Animated from 'react-native-reanimated';
+import { getAvatarForUser } from 'lib/shared/avatar-utils.js';
import { createMessageReply } from 'lib/shared/message-utils.js';
import { assertComposableMessageType } from 'lib/types/message-types.js';
@@ -15,6 +16,7 @@
inlineEngagementLeftStyle,
inlineEngagementRightStyle,
composedMessageStyle,
+ avatarOffset,
} from './chat-constants.js';
import { useComposedMessageMaxWidth } from './composed-message-width.js';
import { FailedSend } from './failed-send.react.js';
@@ -23,10 +25,12 @@
import { useNavigateToSidebar } from './sidebar-navigation.js';
import SwipeableMessage from './swipeable-message.react.js';
import { useContentAndHeaderOpacity, useDeliveryIconOpacity } from './utils.js';
+import Avatar from '../components/avatar.react.js';
import { type InputState, InputStateContext } from '../input/input-state.js';
import { type Colors, useColors } from '../themes/colors.js';
import type { ChatMessageInfoItemWithHeight } from '../types/chat-types.js';
import { type AnimatedStyleObj, AnimatedView } from '../types/styles.js';
+import { useShouldRenderAvatars } from '../utils/avatar-utils.js';
/* eslint-disable import/no-named-as-default-member */
const { Node } = Animated;
@@ -51,6 +55,7 @@
// withInputState
+inputState: ?InputState,
+navigateToSidebar: () => mixed,
+ +shouldRenderAvatars: boolean,
};
class ComposedMessage extends React.PureComponent<Props> {
render() {
@@ -67,6 +72,7 @@
navigateToSidebar,
contentAndHeaderOpacity,
deliveryIconOpacity,
+ shouldRenderAvatars,
...viewProps
} = this.props;
const { id, creator } = item.messageInfo;
@@ -85,7 +91,19 @@
styles.alignment,
{ marginBottom: containerMarginBottom },
];
- const messageBoxStyle = { maxWidth: composedMessageMaxWidth };
+ const messageBoxStyle = [{ maxWidth: composedMessageMaxWidth }];
+ if (shouldRenderAvatars) {
+ messageBoxStyle.push(styles.swipeableContainer);
+ }
+ const messageBoxStyleContainerStyle = [styles.messageBox];
+ if (shouldRenderAvatars) {
+ messageBoxStyleContainerStyle.push({ flex: 1 });
+
+ const positioningStyle = isViewer
+ ? { alignItems: 'flex-end' }
+ : { alignItems: 'flex-start' };
+ messageBoxStyleContainerStyle.push(positioningStyle);
+ }
let deliveryIcon = null;
let failedSendInfo = null;
@@ -121,8 +139,21 @@
swipeOptions === 'sidebar' || swipeOptions === 'both'
? navigateToSidebar
: undefined;
+
+ let avatar;
+ if (!isViewer && item.endsCluster && shouldRenderAvatars) {
+ const avatarInfo = getAvatarForUser(item.messageInfo.creator);
+ avatar = (
+ <View style={styles.avatarContainer}>
+ <Avatar size="small" avatarInfo={avatarInfo} />
+ </View>
+ );
+ } else if (!isViewer && shouldRenderAvatars) {
+ avatar = <View style={styles.avatarOffset} />;
+ }
+
const messageBox = (
- <View style={styles.messageBox}>
+ <View style={messageBoxStyleContainerStyle}>
<SwipeableMessage
triggerReply={triggerReply}
triggerSidebar={triggerSidebar}
@@ -130,6 +161,7 @@
messageBoxStyle={messageBoxStyle}
threadColor={item.threadInfo.color}
>
+ {avatar}
<AnimatedView style={{ opacity: contentAndHeaderOpacity }}>
{children}
</AnimatedView>
@@ -143,10 +175,17 @@
Object.keys(item.reactions).length > 0
) {
const positioning = isViewer ? 'right' : 'left';
- const inlineEngagementPositionStyle =
- positioning === 'left'
- ? styles.leftInlineEngagement
- : styles.rightInlineEngagement;
+
+ const inlineEngagementPositionStyle = [];
+ if (positioning === 'left') {
+ inlineEngagementPositionStyle.push(styles.leftInlineEngagement);
+ } else {
+ inlineEngagementPositionStyle.push(styles.rightInlineEngagement);
+ }
+ if (this.props.shouldRenderAvatars) {
+ inlineEngagementPositionStyle.push({ marginLeft: avatarOffset });
+ }
+
inlineEngagement = (
<View style={[styles.inlineEngagement, inlineEngagementPositionStyle]}>
<InlineEngagement
@@ -187,6 +226,12 @@
marginLeft: composedMessageStyle.marginLeft,
marginRight: composedMessageStyle.marginRight,
},
+ avatarContainer: {
+ marginRight: 8,
+ },
+ avatarOffset: {
+ width: avatarOffset,
+ },
content: {
alignItems: 'center',
flexDirection: 'row-reverse',
@@ -223,6 +268,10 @@
right: inlineEngagementRightStyle.marginRight,
top: inlineEngagementRightStyle.topOffset,
},
+ swipeableContainer: {
+ alignItems: 'flex-end',
+ flexDirection: 'row',
+ },
});
const ConnectedComposedMessage: React.ComponentType<BaseProps> =
@@ -233,6 +282,8 @@
const navigateToSidebar = useNavigateToSidebar(props.item);
const contentAndHeaderOpacity = useContentAndHeaderOpacity(props.item);
const deliveryIconOpacity = useDeliveryIconOpacity(props.item);
+ const shouldRenderAvatars = useShouldRenderAvatars();
+
return (
<ComposedMessage
{...props}
@@ -242,6 +293,7 @@
navigateToSidebar={navigateToSidebar}
contentAndHeaderOpacity={contentAndHeaderOpacity}
deliveryIconOpacity={deliveryIconOpacity}
+ shouldRenderAvatars={shouldRenderAvatars}
/>
);
});
diff --git a/native/chat/message-header.react.js b/native/chat/message-header.react.js
--- a/native/chat/message-header.react.js
+++ b/native/chat/message-header.react.js
@@ -5,12 +5,13 @@
import { useStringForUser } from 'lib/hooks/ens-cache.js';
-import { clusterEndHeight } from './chat-constants.js';
+import { clusterEndHeight, avatarOffset } from './chat-constants.js';
import type { DisplayType } from './timestamp.react.js';
import { Timestamp, timestampHeight } from './timestamp.react.js';
import { SingleLine } from '../components/single-line.react.js';
import { useStyles } from '../themes/colors.js';
import type { ChatMessageInfoItemWithHeight } from '../types/chat-types.js';
+import { useShouldRenderAvatars } from '../utils/avatar-utils.js';
type Props = {
+item: ChatMessageInfoItemWithHeight,
@@ -27,12 +28,21 @@
const shouldShowUsername = !isViewer && (modalDisplay || item.startsCluster);
const stringForUser = useStringForUser(shouldShowUsername ? creator : null);
+ const shouldRenderAvatars = useShouldRenderAvatars();
+
let authorName = null;
if (stringForUser) {
const style = [styles.authorName];
if (modalDisplay) {
style.push(styles.modal);
}
+
+ if (shouldRenderAvatars) {
+ style.push({ marginLeft: 12 + avatarOffset });
+ } else {
+ style.push({ marginLeft: 12 });
+ }
+
authorName = <SingleLine style={style}>{stringForUser}</SingleLine>;
}
@@ -69,7 +79,6 @@
color: 'listBackgroundSecondaryLabel',
fontSize: 14,
height: authorNameHeight,
- marginLeft: 12,
marginRight: 7,
paddingHorizontal: 12,
paddingVertical: 4,
diff --git a/native/chat/multimedia-message-tooltip-button.react.js b/native/chat/multimedia-message-tooltip-button.react.js
--- a/native/chat/multimedia-message-tooltip-button.react.js
+++ b/native/chat/multimedia-message-tooltip-button.react.js
@@ -1,12 +1,15 @@
// @flow
import * as React from 'react';
+import { StyleSheet, View } from 'react-native';
import Animated from 'react-native-reanimated';
import EmojiPicker from 'rn-emoji-keyboard';
+import { getAvatarForUser } from 'lib/shared/avatar-utils.js';
import { localIDPrefix } from 'lib/shared/message-utils.js';
import { useCanCreateReactionFromMessage } from 'lib/shared/reaction-utils.js';
+import { avatarOffset } from './chat-constants.js';
import { TooltipInlineEngagement } from './inline-engagement.react.js';
import { InnerMultimediaMessage } from './inner-multimedia-message.react.js';
import { MessageHeader } from './message-header.react.js';
@@ -14,10 +17,12 @@
import ReactionSelectionPopover from './reaction-selection-popover.react.js';
import SidebarInputBarHeightMeasurer from './sidebar-input-bar-height-measurer.react.js';
import { useAnimatedMessageTooltipButton } from './utils.js';
+import Avatar from '../components/avatar.react.js';
import type { AppNavigationProp } from '../navigation/app-navigator.react.js';
import { useSelector } from '../redux/redux-utils.js';
import { useTooltipActions } from '../tooltip/tooltip-hooks.js';
import type { TooltipRoute } from '../tooltip/tooltip.react.js';
+import { useShouldRenderAvatars } from '../utils/avatar-utils.js';
/* eslint-disable import/no-named-as-default-member */
const { Node, Extrapolate, interpolateNode } = Animated;
@@ -151,6 +156,23 @@
[sendReaction, dismissTooltip],
);
+ const avatarInfo = React.useMemo(
+ () => getAvatarForUser(item.messageInfo.creator),
+ [item.messageInfo.creator],
+ );
+ const shouldRenderAvatars = useShouldRenderAvatars();
+
+ const avatar = React.useMemo(() => {
+ if (item.messageInfo.creator.isViewer || !shouldRenderAvatars) {
+ return null;
+ }
+ return (
+ <View style={styles.avatarContainer}>
+ <Avatar size="small" avatarInfo={avatarInfo} />
+ </View>
+ );
+ }, [avatarInfo, item.messageInfo.creator.isViewer, shouldRenderAvatars]);
+
return (
<>
<Animated.View style={messageContainerStyle}>
@@ -161,6 +183,7 @@
<Animated.View style={headerStyle}>
<MessageHeader item={item} focused={true} display="modal" />
</Animated.View>
+ {avatar}
{reactionSelectionPopover}
{innerMultimediaMessage}
{inlineEngagement}
@@ -174,4 +197,12 @@
);
}
+const styles = StyleSheet.create({
+ avatarContainer: {
+ bottom: 0,
+ left: -avatarOffset,
+ position: 'absolute',
+ },
+});
+
export default MultimediaMessageTooltipButton;
diff --git a/native/chat/text-message-tooltip-button.react.js b/native/chat/text-message-tooltip-button.react.js
--- a/native/chat/text-message-tooltip-button.react.js
+++ b/native/chat/text-message-tooltip-button.react.js
@@ -1,12 +1,15 @@
// @flow
import * as React from 'react';
+import { StyleSheet, View } from 'react-native';
import Animated from 'react-native-reanimated';
import EmojiPicker from 'rn-emoji-keyboard';
+import { getAvatarForUser } from 'lib/shared/avatar-utils.js';
import { localIDPrefix } from 'lib/shared/message-utils.js';
import { useCanCreateReactionFromMessage } from 'lib/shared/reaction-utils.js';
+import { avatarOffset } from './chat-constants.js';
import { TooltipInlineEngagement } from './inline-engagement.react.js';
import { InnerTextMessage } from './inner-text-message.react.js';
import { MessageHeader } from './message-header.react.js';
@@ -16,10 +19,12 @@
import ReactionSelectionPopover from './reaction-selection-popover.react.js';
import SidebarInputBarHeightMeasurer from './sidebar-input-bar-height-measurer.react.js';
import { useAnimatedMessageTooltipButton } from './utils.js';
+import Avatar from '../components/avatar.react.js';
import type { AppNavigationProp } from '../navigation/app-navigator.react.js';
import { useSelector } from '../redux/redux-utils.js';
import { useTooltipActions } from '../tooltip/tooltip-hooks.js';
import type { TooltipRoute } from '../tooltip/tooltip.react.js';
+import { useShouldRenderAvatars } from '../utils/avatar-utils.js';
/* eslint-disable import/no-named-as-default-member */
const { Node, interpolateNode, Extrapolate } = Animated;
@@ -148,6 +153,23 @@
[sendReaction, dismissTooltip],
);
+ const avatarInfo = React.useMemo(
+ () => getAvatarForUser(item.messageInfo.creator),
+ [item.messageInfo.creator],
+ );
+ const shouldRenderAvatars = useShouldRenderAvatars();
+
+ const avatar = React.useMemo(() => {
+ if (item.messageInfo.creator.isViewer || !shouldRenderAvatars) {
+ return null;
+ }
+ return (
+ <View style={styles.avatarContainer}>
+ <Avatar size="small" avatarInfo={avatarInfo} />
+ </View>
+ );
+ }, [avatarInfo, item.messageInfo.creator.isViewer, shouldRenderAvatars]);
+
return (
<MessageListContextProvider threadInfo={threadInfo}>
<SidebarInputBarHeightMeasurer
@@ -158,6 +180,7 @@
<Animated.View style={headerStyle}>
<MessageHeader item={item} focused={true} display="modal" />
</Animated.View>
+ {avatar}
{reactionSelectionPopover}
<MessagePressResponderContext.Provider
value={messagePressResponderContext}
@@ -180,4 +203,12 @@
);
}
+const styles = StyleSheet.create({
+ avatarContainer: {
+ bottom: 0,
+ left: -avatarOffset,
+ position: 'absolute',
+ },
+});
+
export default TextMessageTooltipButton;

File Metadata

Mime Type
text/plain
Expires
Mon, Nov 25, 12:33 PM (22 h, 5 s)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2579733
Default Alt Text
D7067.id24006.diff (13 KB)

Event Timeline