Update context menu presentation (#10426)

This commit is contained in:
DS Boyce
2026-05-07 13:24:55 -07:00
committed by GitHub
parent 10cb0dbf21
commit 9a2cabf64c
12 changed files with 115 additions and 153 deletions
+10 -41
View File
@@ -1,7 +1,6 @@
import {memo, useEffect, useMemo, useRef} from 'react'
import {memo, useEffect, useMemo} from 'react'
import {
type GestureResponderEvent,
LayoutAnimation,
Pressable,
type StyleProp,
type TextStyle,
@@ -43,7 +42,6 @@ import * as ProfileCard from '#/components/ProfileCard'
import {RichText} from '#/components/RichText'
import {Text} from '#/components/Typography'
import {DateDivider} from './DateDivider'
import {useDateDividerToggle} from './DateDividerToggle'
import {MessageItemEmbed} from './MessageItemEmbed'
import {ReactionsDialog} from './ReactionsDialog'
@@ -56,8 +54,6 @@ const DISPLAY_NAME_INSET = 22
const CLUSTERED_MESSAGE_THRESHOLD_MS = 5 * 60 * 1000
const MESSAGE_GAP_THRESHOLD_MS = 60 * 60 * 1000
const TAP_AND_DRAG_DELAY_MS = 100
function isWithinClusterBoundary({
isPending,
adjacentMessage,
@@ -104,7 +100,6 @@ let MessageItem = ({
const profile = item.relatedProfiles.get(item.message.sender.did)
const reactionsControl = useDialogControl()
const reactionTapRef = useRef(false)
const {message, nextMessage, prevMessage} = item
const isPending = item.type === 'pending-message'
@@ -148,16 +143,9 @@ let MessageItem = ({
new Date(prevMessage.sentAt).getTime() >
MESSAGE_GAP_THRESHOLD_MS
const {isDividerToggled, toggleDivider} = useDateDividerToggle()
const isDateDividerToggled = isDividerToggled(message.id)
const isNextDateDividerToggled =
nextMessage != null && isDividerToggled(nextMessage.id)
const effectiveFirstInCluster = isFirstInCluster || isDateDividerToggled
const effectiveLastInCluster = isLastInCluster || isNextDateDividerToggled
const isInCluster = !(effectiveFirstInCluster && effectiveLastInCluster)
const isInCluster = !(isFirstInCluster && isLastInCluster)
const isInMiddleOfCluster =
isInCluster && !effectiveFirstInCluster && !effectiveLastInCluster
isInCluster && !isFirstInCluster && !isLastInCluster
const hasReactions = message.reactions && message.reactions.length > 0
const prevHasReactions =
@@ -168,12 +156,12 @@ let MessageItem = ({
!hasReactions &&
!isNextEmojiOnly &&
isInCluster &&
(isInMiddleOfCluster || effectiveFirstInCluster)
(isInMiddleOfCluster || isFirstInCluster)
const squaredTopCorner =
!prevHasReactions &&
!isPrevEmojiOnly &&
isInCluster &&
(isInMiddleOfCluster || effectiveLastInCluster)
(isInMiddleOfCluster || isLastInCluster)
const pendingColor = t.palette.primary_300
@@ -336,16 +324,6 @@ let MessageItem = ({
transform: [{translateY: -8}],
},
]}
onPressIn={() => {
// Don't toggle the date divider when tapping a reaction.
reactionTapRef.current = true
}}
onPressOut={() => {
// Include a delay here to account for tap-and-drag before release.
setTimeout(() => {
reactionTapRef.current = false
}, TAP_AND_DRAG_DELAY_MS)
}}
onPress={isGroupChat ? reactionsControl.open : undefined}>
{groupedReactions.map(group => (
<Animated.View
@@ -407,13 +385,13 @@ let MessageItem = ({
return (
<>
<LayoutAnimationConfig skipExiting skipEntering>
{(hasLargeGapFromPrev || isDateDividerToggled) && (
{hasLargeGapFromPrev && (
<Animated.View entering={native(FadeIn)} exiting={native(FadeOut)}>
<DateDivider date={message.sentAt} />
</Animated.View>
)}
</LayoutAnimationConfig>
<View style={[messageInset, effectiveFirstInCluster && a.mt_md]}>
<View style={[messageInset, isFirstInCluster && a.mt_md]}>
<View style={[a.relative]}>
{showAvatar ? (
<View
@@ -450,16 +428,7 @@ let MessageItem = ({
hasReactions={hasReactions}
isFromSelf={isFromSelf}
message={message}
senderProfile={profile}
onTap={() => {
if (reactionTapRef.current) return
if (!hasLargeGapFromPrev) {
LayoutAnimation.configureNext(
LayoutAnimation.Presets.easeInEaseOut,
)
toggleDivider(message.id)
}
}}>
senderProfile={profile}>
{AppBskyEmbedRecord.isView(message.embed) && (
<MessageItemEmbed
embed={message.embed}
@@ -480,7 +449,7 @@ let MessageItem = ({
a.py_sm,
a.px_md,
{
marginTop: effectiveFirstInCluster
marginTop: isFirstInCluster
? 0
: CLUSTERED_MESSAGE_GAP,
backgroundColor: isFromSelf
@@ -523,7 +492,7 @@ let MessageItem = ({
</ActionsWrapper>
</View>
</View>
{effectiveLastInCluster && (
{isLastInCluster && (
<MessageItemMetadata
item={item}
style={[isFromSelf ? a.text_right : a.text_left]}