diff --git a/native/chat/inline-engagement.react.js b/native/chat/inline-engagement.react.js
index 3181f22b7..ea8d4ca78 100644
--- a/native/chat/inline-engagement.react.js
+++ b/native/chat/inline-engagement.react.js
@@ -1,350 +1,333 @@
// @flow
import { useNavigation } from '@react-navigation/native';
import invariant from 'invariant';
import * as React from 'react';
import { Text, View } from 'react-native';
import Animated, {
Extrapolate,
interpolateNode,
} from 'react-native-reanimated';
import useInlineEngagementText from 'lib/hooks/inline-engagement-text.react.js';
import type { ReactionInfo } from 'lib/selectors/chat-selectors.js';
import { stringForReactionList } from 'lib/shared/reaction-utils.js';
import type { ThreadInfo } from 'lib/types/thread-types.js';
import {
inlineEngagementLabelStyle,
inlineEngagementStyle,
inlineEngagementCenterStyle,
inlineEngagementRightStyle,
inlineEngagementLeftStyle,
composedMessageStyle,
avatarOffset,
} from './chat-constants.js';
import { useNavigateToThread } from './message-list-types.js';
import CommIcon from '../components/comm-icon.react.js';
import GestureTouchableOpacity from '../components/gesture-touchable-opacity.react.js';
import { MessageReactionsModalRouteName } from '../navigation/route-names.js';
import { useStyles } from '../themes/colors.js';
import type { ChatMessageInfoItemWithHeight } from '../types/chat-types.js';
type Props = {
+sidebarThreadInfo: ?ThreadInfo,
+reactions?: ReactionInfo,
+disabled?: boolean,
+positioning?: 'left' | 'right',
+label?: ?string,
};
function InlineEngagement(props: Props): React.Node {
const {
disabled = false,
reactions,
sidebarThreadInfo,
positioning,
label,
} = props;
const repliesText = useInlineEngagementText(sidebarThreadInfo);
const navigateToThread = useNavigateToThread();
const { navigate } = useNavigation();
const styles = useStyles(unboundStyles);
const unreadStyle = sidebarThreadInfo?.currentUser.unread
? styles.unread
: null;
const repliesStyles = React.useMemo(
() => [styles.repliesText, unreadStyle],
[styles.repliesText, unreadStyle],
);
const onPressSidebar = React.useCallback(() => {
if (sidebarThreadInfo && !disabled) {
navigateToThread({ threadInfo: sidebarThreadInfo });
}
}, [disabled, navigateToThread, sidebarThreadInfo]);
const sidebarItem = React.useMemo(() => {
if (!sidebarThreadInfo) {
return null;
}
return (
{repliesText}
);
}, [
sidebarThreadInfo,
onPressSidebar,
styles.sidebar,
styles.icon,
repliesStyles,
repliesText,
]);
const onPressReactions = React.useCallback(() => {
navigate<'MessageReactionsModal'>({
name: MessageReactionsModalRouteName,
params: { reactions },
});
}, [navigate, reactions]);
const marginLeft = React.useMemo(
() => (sidebarItem ? styles.reactionMarginLeft : null),
[sidebarItem, styles.reactionMarginLeft],
);
const reactionList = React.useMemo(() => {
if (!reactions || Object.keys(reactions).length === 0) {
return null;
}
const reactionText = stringForReactionList(reactions);
const reactionItems = {reactionText};
return (
{reactionItems}
);
}, [
marginLeft,
onPressReactions,
reactions,
styles.reaction,
styles.reactionsContainer,
]);
const isLeft = positioning === 'left';
const editedLabel = React.useMemo(() => {
if (!label) {
return null;
}
const labelLeftRight = isLeft
? styles.messageLabelLeft
: styles.messageLabelRight;
return {label};
}, [isLeft, label, styles]);
- const container = React.useMemo(() => {
- if (!sidebarItem && !reactionList) {
- return null;
+ const inlineEngagementPositionStyle = React.useMemo(() => {
+ const styleResult = [styles.inlineEngagement];
+ if (!isLeft) {
+ styleResult.push(styles.rightInlineEngagement);
}
- return (
-
- {sidebarItem}
- {reactionList}
-
- );
- }, [reactionList, sidebarItem, styles.container]);
-
- const inlineEngagementPositionStyle = [styles.inlineEngagement];
- if (isLeft) {
- inlineEngagementPositionStyle.push(styles.leftInlineEngagement);
- } else {
- inlineEngagementPositionStyle.push(styles.rightInlineEngagement);
- }
+ return styleResult;
+ }, [isLeft, styles.inlineEngagement, styles.rightInlineEngagement]);
let body;
if (isLeft) {
body = (
<>
{editedLabel}
- {container}
+ {sidebarItem}
+ {reactionList}
>
);
} else {
body = (
<>
- {container}
+ {sidebarItem}
+ {reactionList}
{editedLabel}
>
);
}
return {body};
}
const unboundStyles = {
inlineEngagement: {
flexDirection: 'row',
marginBottom: inlineEngagementStyle.marginBottom,
marginTop: inlineEngagementStyle.marginTop,
- alignItems: 'center',
marginLeft: avatarOffset,
- },
- leftInlineEngagement: {
- justifyContent: 'flex-start',
- position: 'relative',
top: inlineEngagementLeftStyle.topOffset,
},
rightInlineEngagement: {
alignSelf: 'flex-end',
- position: 'relative',
right: inlineEngagementRightStyle.marginRight,
- top: inlineEngagementRightStyle.topOffset,
- },
- container: {
- flexDirection: 'row',
- height: inlineEngagementStyle.height,
- borderRadius: 16,
- backgroundColor: 'inlineEngagementBackground',
- alignSelf: 'baseline',
- alignItems: 'center',
- padding: 8,
},
sidebar: {
flexDirection: 'row',
alignItems: 'center',
+ backgroundColor: 'inlineEngagementBackground',
+ paddingHorizontal: 8,
+ paddingVertical: 4,
+ borderRadius: 8,
},
icon: {
color: 'inlineEngagementLabel',
marginRight: 4,
},
repliesText: {
color: 'inlineEngagementLabel',
fontSize: 14,
lineHeight: 22,
},
unread: {
color: 'listForegroundLabel',
fontWeight: 'bold',
},
reactionsContainer: {
display: 'flex',
flexDirection: 'row',
alignItems: 'center',
+ backgroundColor: 'inlineEngagementBackground',
+ paddingHorizontal: 8,
+ paddingVertical: 4,
+ borderRadius: 8,
},
reaction: {
color: 'inlineEngagementLabel',
fontSize: 14,
lineHeight: 22,
},
reactionMarginLeft: {
marginLeft: 12,
},
messageLabel: {
color: 'messageLabel',
paddingHorizontal: 3,
fontSize: 13,
top: inlineEngagementLabelStyle.topOffset,
height: inlineEngagementLabelStyle.height,
},
messageLabelLeft: {
marginLeft: 9,
marginRight: 4,
},
messageLabelRight: {
marginRight: 10,
marginLeft: 4,
},
avatarOffset: {
width: avatarOffset,
},
};
type TooltipInlineEngagementProps = {
+item: ChatMessageInfoItemWithHeight,
+isOpeningSidebar: boolean,
+progress: Animated.Node,
+windowWidth: number,
+positioning: 'left' | 'right' | 'center',
+initialCoordinates: {
+x: number,
+y: number,
+width: number,
+height: number,
},
};
function TooltipInlineEngagement(
props: TooltipInlineEngagementProps,
): React.Node {
const {
item,
isOpeningSidebar,
progress,
windowWidth,
initialCoordinates,
positioning,
} = props;
// ESLint doesn't recognize that invariant always throws
// eslint-disable-next-line consistent-return
const inlineEngagementStyles = React.useMemo(() => {
if (positioning === 'left') {
return {
position: 'absolute',
top:
inlineEngagementStyle.marginTop + inlineEngagementLeftStyle.topOffset,
left: composedMessageStyle.marginLeft,
};
} else if (positioning === 'right') {
return {
position: 'absolute',
right:
inlineEngagementRightStyle.marginRight +
composedMessageStyle.marginRight,
top:
inlineEngagementStyle.marginTop +
inlineEngagementRightStyle.topOffset,
};
} else if (positioning === 'center') {
return {
alignSelf: 'center',
top: inlineEngagementCenterStyle.topOffset,
};
}
invariant(
false,
`${positioning} is not a valid positioning value for InlineEngagement`,
);
}, [positioning]);
const inlineEngagementContainer = React.useMemo(() => {
const opacity = isOpeningSidebar
? 0
: interpolateNode(progress, {
inputRange: [0, 1],
outputRange: [1, 0],
extrapolate: Extrapolate.CLAMP,
});
return {
position: 'absolute',
width: windowWidth,
top: initialCoordinates.height,
left: -initialCoordinates.x,
opacity,
};
}, [
initialCoordinates.height,
initialCoordinates.x,
isOpeningSidebar,
progress,
windowWidth,
]);
return (
);
}
export { InlineEngagement, TooltipInlineEngagement };