Merge branch 'main' into app-2119

This commit is contained in:
vineyardbovines
2026-05-06 12:43:18 -04:00
2 changed files with 49 additions and 53 deletions
+14 -17
View File
@@ -182,13 +182,11 @@ let MessageItem = ({
const hasEmbedAndText = const hasEmbedAndText =
AppBskyEmbedRecord.isView(message.embed) && rt.text.length > 0 AppBskyEmbedRecord.isView(message.embed) && rt.text.length > 0
const targetBottomRadius = const targetBottomRadius = squaredBottomCorner
squaredBottomCorner || hasEmbedAndText
? SQUARED_BORDER_RADIUS
: BORDER_RADIUS
const targetTopRadius = squaredTopCorner
? SQUARED_BORDER_RADIUS ? SQUARED_BORDER_RADIUS
: BORDER_RADIUS : BORDER_RADIUS
const targetTopRadius =
squaredTopCorner || hasEmbedAndText ? SQUARED_BORDER_RADIUS : BORDER_RADIUS
const bottomRadiusSV = useSharedValue(targetBottomRadius) const bottomRadiusSV = useSharedValue(targetBottomRadius)
const topRadiusSV = useSharedValue(targetTopRadius) const topRadiusSV = useSharedValue(targetTopRadius)
@@ -442,10 +440,9 @@ let MessageItem = ({
t.atoms.text_contrast_medium, t.atoms.text_contrast_medium,
a.pt_xs, a.pt_xs,
a.pb_2xs, a.pb_2xs,
{ {paddingLeft: DISPLAY_NAME_INSET},
paddingLeft: DISPLAY_NAME_INSET, ]}
}, emoji>
]}>
{displayName} {displayName}
</Text> </Text>
) : null} ) : null}
@@ -463,6 +460,14 @@ let MessageItem = ({
toggleDivider(message.id) toggleDivider(message.id)
} }
}}> }}>
{AppBskyEmbedRecord.isView(message.embed) && (
<MessageItemEmbed
embed={message.embed}
isFromSelf={isFromSelf}
squaredBottomCorner={squaredBottomCorner || hasEmbedAndText}
squaredTopCorner={squaredTopCorner}
/>
)}
{rt.text.length > 0 && ( {rt.text.length > 0 && (
<Animated.View <Animated.View
accessibilityHint={l`Double tap or long press the message to add a reaction`} accessibilityHint={l`Double tap or long press the message to add a reaction`}
@@ -514,14 +519,6 @@ let MessageItem = ({
/> />
</Animated.View> </Animated.View>
)} )}
{AppBskyEmbedRecord.isView(message.embed) && (
<MessageItemEmbed
embed={message.embed}
isFromSelf={isFromSelf}
squaredBottomCorner={squaredBottomCorner}
squaredTopCorner={squaredTopCorner || hasEmbedAndText}
/>
)}
{appliedReactions} {appliedReactions}
</ActionsWrapper> </ActionsWrapper>
</View> </View>
+35 -36
View File
@@ -6,7 +6,6 @@ import {
useWindowDimensions, useWindowDimensions,
View, View,
} from 'react-native' } from 'react-native'
import Animated from 'react-native-reanimated'
import {type ChatBskyActorDefs, type ChatBskyConvoDefs} from '@atproto/api' import {type ChatBskyActorDefs, type ChatBskyConvoDefs} from '@atproto/api'
import {Trans, useLingui} from '@lingui/react/macro' import {Trans, useLingui} from '@lingui/react/macro'
@@ -15,6 +14,7 @@ import {createSanitizedDisplayName} from '#/lib/moderation/create-sanitized-disp
import {sanitizeHandle} from '#/lib/strings/handles' import {sanitizeHandle} from '#/lib/strings/handles'
import {type ActiveConvoStates, useConvoActive} from '#/state/messages/convo' import {type ActiveConvoStates, useConvoActive} from '#/state/messages/convo'
import {useSession} from '#/state/session' import {useSession} from '#/state/session'
import {type SessionAccount} from '#/state/session/types'
import {DraggableScrollView} from '#/view/com/pager/DraggableScrollView' import {DraggableScrollView} from '#/view/com/pager/DraggableScrollView'
import {UserAvatar} from '#/view/com/util/UserAvatar' import {UserAvatar} from '#/view/com/util/UserAvatar'
import {atoms as a, useTheme, web} from '#/alf' import {atoms as a, useTheme, web} from '#/alf'
@@ -31,6 +31,8 @@ type Reaction = {
count: number count: number
} }
type Tab = Omit<Reaction, 'senders'>
export function ReactionsDialog({ export function ReactionsDialog({
control, control,
relatedProfiles, relatedProfiles,
@@ -52,10 +54,6 @@ export function ReactionsDialog({
const [selected, setSelected] = useState('all') const [selected, setSelected] = useState('all')
const handleFilter = (value: string) => {
setSelected(value)
}
const filteredReactions = reactions?.filter( const filteredReactions = reactions?.filter(
r => selected === 'all' || r.value === selected, r => selected === 'all' || r.value === selected,
) )
@@ -71,7 +69,7 @@ export function ReactionsDialog({
groupedReactions={groupedReactions} groupedReactions={groupedReactions}
selected={selected} selected={selected}
totalReactions={reactions?.length ?? 0} totalReactions={reactions?.length ?? 0}
onFilter={handleFilter} onFilter={setSelected}
/> />
<Dialog.Close /> <Dialog.Close />
</> </>
@@ -135,7 +133,7 @@ function ReactionRow({
}: { }: {
control: Dialog.DialogControlProps control: Dialog.DialogControlProps
convo: ActiveConvoStates convo: ActiveConvoStates
currentAccount?: bsky.profile.AnyProfileView currentAccount?: SessionAccount
message: ChatBskyConvoDefs.MessageView message: ChatBskyConvoDefs.MessageView
profile: bsky.profile.AnyProfileView profile: bsky.profile.AnyProfileView
reaction: ChatBskyConvoDefs.ReactionView reaction: ChatBskyConvoDefs.ReactionView
@@ -149,14 +147,13 @@ function ReactionRow({
const isFromSelf = currentAccount?.did === profile.did const isFromSelf = currentAccount?.did === profile.did
const displayName = createSanitizedDisplayName(profile, true) const displayName = createSanitizedDisplayName(profile, true)
const handle = sanitizeHandle(profile?.handle ?? '', '@') const handle = sanitizeHandle(profile.handle, '@')
const handleOnPress = () => { const handleOnPress = () => {
const remainingReactions = const remainingReactions = allReactions.filter(
allReactions?.filter( r =>
r => !(r.value === reaction.value && r.sender.did === currentAccount?.did),
!(r.value === reaction.value && r.sender.did === currentAccount?.did), )
) ?? []
if (remainingReactions.length === 0) { if (remainingReactions.length === 0) {
control.close() control.close()
@@ -283,18 +280,13 @@ function ReactionTabs({
tabLayouts.current.set(key, layout) tabLayouts.current.set(key, layout)
} }
const tabs = [ const tabs: Tab[] = [
{ {key: 'all', value: l`All`, count: totalReactions},
key: 'all',
value: l`All`,
senders: [],
count: totalReactions,
} as Reaction,
...(groupedReactions ?? []), ...(groupedReactions ?? []),
] ]
return ( return (
<View accessibilityRole="list" style={[t.atoms.bg]}> <View accessibilityRole="tablist" style={[t.atoms.bg]}>
<DraggableScrollView <DraggableScrollView
ref={scrollViewRef} ref={scrollViewRef}
horizontal={true} horizontal={true}
@@ -309,7 +301,7 @@ function ReactionTabs({
onLayout={e => { onLayout={e => {
scrollState.current.width = e.nativeEvent.layout.width scrollState.current.width = e.nativeEvent.layout.width
}}> }}>
<Animated.View <View
style={[ style={[
a.flex_row, a.flex_row,
a.flex_grow, a.flex_grow,
@@ -317,18 +309,18 @@ function ReactionTabs({
a.align_center, a.align_center,
a.justify_start, a.justify_start,
]}> ]}>
{tabs?.map((reaction, index) => ( {tabs.map((tab, index) => (
<ReactionTab <ReactionTab
key={reaction.value} key={tab.key}
index={index} index={index}
reaction={reaction} tab={tab}
selected={selected} selected={selected}
total={tabs.length} total={tabs.length}
onPress={handlePress} onPress={handlePress}
onTabLayout={handleTabLayout} onTabLayout={handleTabLayout}
/> />
))} ))}
</Animated.View> </View>
</DraggableScrollView> </DraggableScrollView>
</View> </View>
) )
@@ -336,14 +328,14 @@ function ReactionTabs({
function ReactionTab({ function ReactionTab({
index, index,
reaction, tab,
selected, selected,
total, total,
onPress, onPress,
onTabLayout, onTabLayout,
}: { }: {
index: number index: number
reaction: Reaction tab: Tab
selected: string selected: string
total: number total: number
onPress: (value: string) => void onPress: (value: string) => void
@@ -354,11 +346,12 @@ function ReactionTab({
return ( return (
<Pressable <Pressable
accessibilityRole="button" accessibilityRole="tab"
accessibilityState={{selected: selected === tab.key}}
accessibilityHint={ accessibilityHint={
reaction.key === 'all' tab.key === 'all'
? l`Tap to show all reactions` ? l`Tap to show all reactions`
: l`Tap to show ${reaction.value} reactions` : l`Tap to show ${tab.value} reactions`
} }
hitSlop={HITSLOP_10} hitSlop={HITSLOP_10}
style={[ style={[
@@ -370,21 +363,27 @@ function ReactionTab({
a.px_md, a.px_md,
a.py_sm, a.py_sm,
a.mb_sm, a.mb_sm,
selected === reaction.key selected === tab.key
? t.atoms.border_contrast_low ? t.atoms.border_contrast_low
: {borderColor: t.palette.contrast_50}, : {borderColor: t.palette.contrast_50},
selected === reaction.key ? t.atoms.bg_contrast_50 : t.atoms.bg, selected === tab.key ? t.atoms.bg_contrast_50 : t.atoms.bg,
index === 0 ? a.ml_2xl : index === total - 1 ? a.mr_2xl : null, index === 0 ? a.ml_2xl : index === total - 1 ? a.mr_2xl : null,
]} ]}
onLayout={e => { onLayout={e => {
onTabLayout(reaction.key, { onTabLayout(tab.key, {
x: e.nativeEvent.layout.x, x: e.nativeEvent.layout.x,
width: e.nativeEvent.layout.width, width: e.nativeEvent.layout.width,
}) })
}} }}
onPress={() => onPress(reaction.key)}> onPress={() => onPress(tab.key)}>
<Text emoji style={[a.text_sm]}> <Text emoji style={[a.text_sm]}>
{l`${reaction.value} ${reaction.count}`} {tab.key === 'all'
? l({
message: `All ${tab.count}`,
comment:
'Tab label showing the total count of reactions on a chat message.',
})
: `${tab.value} ${tab.count}`}
</Text> </Text>
</Pressable> </Pressable>
) )