fix(feed): move card layout off Pressable style-fn so paddings stick

Same Pressable-dynamic-style-function bug that bit the FAB: on some
RN versions the style function is re-evaluated mid-render in a way
that drops properties — here we lost paddingLeft:16 and sometimes
flexDirection:'row' on the outer PostCard Pressable, which is why
the avatar ended up flush against the left edge and the header/body
sometimes stacked into a column instead of row.

Fix: move layout to a plain <View> wrapper (static styles, can never
be dropped). Tap handling stays on two Pressables:
  - the avatar wrapper (opens author profile),
  - the content column (opens post detail + long-press for menu).

The card area visually covered by these two Pressables is ~100% —
tap anywhere on a post still navigates to detail, tap on the avatar
still goes to the author. No interaction regression.

Also paired opacity press-state on the content-column Pressable so
the feedback visual matches what the old bg-colour press gave.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
vsecoder
2026-04-18 21:28:34 +03:00
parent 0bb5780a5d
commit 9be1b60ef1

View File

@@ -183,16 +183,20 @@ function PostCardInner({ post, likedByMe, onStatsChanged, onDeleted, compact }:
return ( return (
<> <>
<Pressable {/* Outer container is a plain View so layout styles (padding, row
onPress={onOpenDetail} direction) are static and always applied. Pressable's dynamic
onLongPress={onLongPress} style-function has been observed to drop properties between
style={({ pressed }) => ({ renders on some RN versions — we hit that with the FAB, so
we're not relying on it here either. Tap handling lives on the
content-column Pressable (covers ~90% of the card area) plus a
separate Pressable around the avatar. */}
<View
style={{
flexDirection: 'row', flexDirection: 'row',
paddingLeft: 16, paddingLeft: 16,
paddingRight: 16, paddingRight: 16,
paddingVertical: compact ? 10 : 12, paddingVertical: compact ? 10 : 12,
backgroundColor: pressed ? '#080808' : 'transparent', }}
})}
> >
{/* Avatar — own tap target (opens author profile). Explicit width {/* Avatar — own tap target (opens author profile). Explicit width
on the wrapper (width:44) so the flex-row sibling below computes on the wrapper (width:44) so the flex-row sibling below computes
@@ -201,9 +205,21 @@ function PostCardInner({ post, likedByMe, onStatsChanged, onDeleted, compact }:
<Avatar name={displayName} address={post.author} size={44} /> <Avatar name={displayName} address={post.author} size={44} />
</Pressable> </Pressable>
{/* Content column. overflow:'hidden' prevents unbreakable tokens {/* Content column. Pressable so the card body is tappable →
from drawing past the right edge of the card. */} detail; onLongPress routes to the context menu. overflow:
<View style={{ flex: 1, marginLeft: 10, minWidth: 0, overflow: 'hidden' }}> 'hidden' prevents unbreakable tokens from drawing past the
right edge. */}
<Pressable
onPress={onOpenDetail}
onLongPress={onLongPress}
style={({ pressed }) => ({
flex: 1,
marginLeft: 10,
minWidth: 0,
overflow: 'hidden',
opacity: pressed ? 0.85 : 1,
})}
>
{/* Header row — name + time on ONE line. {/* Header row — name + time on ONE line.
Two siblings: the author-link Pressable (flex:1, row, so it Two siblings: the author-link Pressable (flex:1, row, so it
expands; name inside gets numberOfLines:1 + flexShrink:1 so expands; name inside gets numberOfLines:1 + flexShrink:1 so
@@ -361,8 +377,8 @@ function PostCardInner({ post, likedByMe, onStatsChanged, onDeleted, compact }:
/> />
</View> </View>
</View> </View>
</View> </Pressable>
</Pressable> </View>
<ShareSheet <ShareSheet
visible={shareOpen} visible={shareOpen}
post={post} post={post}