Page MenuHomePhabricator

D7067.id23772.diff
No OneTemporary

D7067.id23772.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/chat-item-height-measurer.react.js b/native/chat/chat-item-height-measurer.react.js
--- a/native/chat/chat-item-height-measurer.react.js
+++ b/native/chat/chat-item-height-measurer.react.js
@@ -8,6 +8,7 @@
import { messageTypes, type MessageType } from 'lib/types/message-types.js';
import { entityTextToRawString } from 'lib/utils/entity-text.js';
+import { avatarOffset } from './chat-constants.js';
import type { MeasurementTask } from './chat-context-provider.react.js';
import { useComposedMessageMaxWidth } from './composed-message-width.js';
import { dummyNodeForRobotextMessageHeightMeasurement } from './inner-robotext-message.react.js';
@@ -54,7 +55,7 @@
};
function ChatItemHeightMeasurer(props: Props) {
- const composedMessageMaxWidth = useComposedMessageMaxWidth();
+ const composedMessageMaxWidth = useComposedMessageMaxWidth() - avatarOffset;
const inputState = React.useContext(InputStateContext);
const inputStatePendingUploads = inputState?.pendingUploads;
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,6 +25,7 @@
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';
@@ -121,6 +124,19 @@
swipeOptions === 'sidebar' || swipeOptions === 'both'
? navigateToSidebar
: undefined;
+
+ let avatar;
+ if (!isViewer && item.endsCluster) {
+ const avatarInfo = getAvatarForUser(item.messageInfo.creator);
+ avatar = (
+ <View style={styles.avatarContainer}>
+ <Avatar size="small" avatarInfo={avatarInfo} />
+ </View>
+ );
+ } else if (!isViewer) {
+ avatar = <View style={styles.avatarOffset} />;
+ }
+
const messageBox = (
<View style={styles.messageBox}>
<SwipeableMessage
@@ -130,9 +146,12 @@
messageBoxStyle={messageBoxStyle}
threadColor={item.threadInfo.color}
>
- <AnimatedView style={{ opacity: contentAndHeaderOpacity }}>
- {children}
- </AnimatedView>
+ <View style={styles.swipeableContainer}>
+ {avatar}
+ <AnimatedView style={{ opacity: contentAndHeaderOpacity }}>
+ {children}
+ </AnimatedView>
+ </View>
</SwipeableMessage>
</View>
);
@@ -187,6 +206,12 @@
marginLeft: composedMessageStyle.marginLeft,
marginRight: composedMessageStyle.marginRight,
},
+ avatarContainer: {
+ marginRight: 8,
+ },
+ avatarOffset: {
+ width: avatarOffset,
+ },
content: {
alignItems: 'center',
flexDirection: 'row-reverse',
@@ -208,6 +233,7 @@
},
leftInlineEngagement: {
justifyContent: 'flex-start',
+ marginLeft: 32,
position: 'relative',
top: inlineEngagementLeftStyle.topOffset,
},
@@ -223,6 +249,10 @@
right: inlineEngagementRightStyle.marginRight,
top: inlineEngagementRightStyle.topOffset,
},
+ swipeableContainer: {
+ alignItems: 'flex-end',
+ flexDirection: 'row',
+ },
});
const ConnectedComposedMessage: React.ComponentType<BaseProps> =
diff --git a/native/chat/inner-text-message.react.js b/native/chat/inner-text-message.react.js
--- a/native/chat/inner-text-message.react.js
+++ b/native/chat/inner-text-message.react.js
@@ -6,6 +6,7 @@
import { colorIsDark } from 'lib/shared/thread-utils.js';
+import { avatarOffset } from './chat-constants.js';
import { useComposedMessageMaxWidth } from './composed-message-width.js';
import { useTextMessageMarkdownRules } from './message-list-types.js';
import {
@@ -39,7 +40,7 @@
};
function DummyTextNode(props: DummyTextNodeProps): React.Node {
const { children, style, ...rest } = props;
- const maxWidth = useComposedMessageMaxWidth();
+ const maxWidth = useComposedMessageMaxWidth() - avatarOffset;
const viewStyle = [props.style, styles.dummyMessage, { maxWidth }];
const rules = useTextMessageMarkdownRules(false);
return (
@@ -99,6 +100,9 @@
return [styles.text, textStyle];
}, [darkColor]);
+ const maxWidth = useComposedMessageMaxWidth() - avatarOffset;
+ const maxWidthStyle = React.useMemo(() => ({ maxWidth }), [maxWidth]);
+
// If we need to render a Text with an onPress prop inside, we're going to
// have an issue: the GestureTouchableOpacity below will trigger too when the
// the onPress is pressed. We have to use a GestureTouchableOpacity in order
@@ -131,7 +135,7 @@
onPress={props.onPress}
onLongPress={props.onPress}
activeOpacity={0.6}
- style={[styles.message, cornerStyle]}
+ style={[styles.message, cornerStyle, maxWidthStyle]}
animatedStyle={messageStyle}
>
<Markdown style={markdownStyles} rules={rules}>
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
@@ -69,7 +69,7 @@
color: 'listBackgroundSecondaryLabel',
fontSize: 14,
height: authorNameHeight,
- marginLeft: 12,
+ marginLeft: 44,
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,6 +17,7 @@
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';
@@ -151,6 +155,22 @@
[sendReaction, dismissTooltip],
);
+ const avatarInfo = React.useMemo(
+ () => getAvatarForUser(item.messageInfo.creator),
+ [item.messageInfo.creator],
+ );
+
+ const avatar = React.useMemo(() => {
+ if (item.messageInfo.creator.isViewer) {
+ return null;
+ }
+ return (
+ <View style={styles.avatarContainer}>
+ <Avatar size="small" avatarInfo={avatarInfo} />
+ </View>
+ );
+ }, [avatarInfo, item.messageInfo.creator.isViewer]);
+
return (
<>
<Animated.View style={messageContainerStyle}>
@@ -161,6 +181,7 @@
<Animated.View style={headerStyle}>
<MessageHeader item={item} focused={true} display="modal" />
</Animated.View>
+ {avatar}
{reactionSelectionPopover}
{innerMultimediaMessage}
{inlineEngagement}
@@ -174,4 +195,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,6 +19,7 @@
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';
@@ -148,6 +152,22 @@
[sendReaction, dismissTooltip],
);
+ const avatarInfo = React.useMemo(
+ () => getAvatarForUser(item.messageInfo.creator),
+ [item.messageInfo.creator],
+ );
+
+ const avatar = React.useMemo(() => {
+ if (item.messageInfo.creator.isViewer) {
+ return null;
+ }
+ return (
+ <View style={styles.avatarContainer}>
+ <Avatar size="small" avatarInfo={avatarInfo} />
+ </View>
+ );
+ }, [avatarInfo, item.messageInfo.creator.isViewer]);
+
return (
<MessageListContextProvider threadInfo={threadInfo}>
<SidebarInputBarHeightMeasurer
@@ -158,6 +178,7 @@
<Animated.View style={headerStyle}>
<MessageHeader item={item} focused={true} display="modal" />
</Animated.View>
+ {avatar}
{reactionSelectionPopover}
<MessagePressResponderContext.Provider
value={messagePressResponderContext}
@@ -180,4 +201,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:29 PM (21 h, 34 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2579701
Default Alt Text
D7067.id23772.diff (11 KB)

Event Timeline