fix(feed): card spacing, action-row distribution, tab strip, detail inset

- PostCard rows got cramped paddings and a near-invisible divider.
  Increased paddingTop 12→16, paddingBottom 12→18, paddingHorizontal
  14→16; divider colour #141414→#222222 so the seam between posts is
  legible on OLED blacks.
- Action row (chat / ❤ / view / share) used a fixed gap:32 + spacer.
  Reworked to four flex:1 cells with justifyContent: space-between,
  so the first three icons distribute evenly across the row and share
  pins to the right edge. Matches Twitter's layout where each action
  occupies a quarter of the row regardless of label width.
- Feed tab strip (Подписки / Для вас / В тренде) used flex:1 +
  gap:10 which bunched the three labels together visually. Switched
  to justifyContent: space-between + paddingHorizontal:20 so each
  tab hugs its label and the three labels spread to the edges with
  full horizontal breathing room.
- Post detail screen (/feed/[id]) and hashtag feed (/feed/tag/[tag])
  were missing the safe-area top inset — their headers butted right
  against the status bar / notch. Added useSafeAreaInsets().top as
  paddingTop on the outer View, matching the rest of the app.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
vsecoder
2026-04-18 20:20:18 +03:00
parent 93040a0684
commit 51bc0a1850
4 changed files with 86 additions and 71 deletions

View File

@@ -173,11 +173,12 @@ function PostCardInner({ post, likedByMe, onStatsChanged, onDeleted, compact }:
onLongPress={onLongPress}
style={({ pressed }) => ({
flexDirection: 'row',
paddingHorizontal: 14,
paddingVertical: compact ? 10 : 12,
paddingHorizontal: 16,
paddingTop: compact ? 12 : 16,
paddingBottom: compact ? 14 : 18,
backgroundColor: pressed ? '#080808' : 'transparent',
borderBottomWidth: 1,
borderBottomColor: '#141414',
borderBottomColor: '#222222',
})}
>
{/* Avatar column */}
@@ -246,58 +247,69 @@ function PostCardInner({ post, likedByMe, onStatsChanged, onDeleted, compact }:
</View>
)}
{/* Action row */}
{/* Action row — 4 evenly-spaced buttons (Twitter-style). Each is
wrapped in a flex: 1 container so even if one label is
wider than another, visual spacing between centres stays
balanced. */}
<View
style={{
flexDirection: 'row',
alignItems: 'center',
marginTop: 8,
gap: 32,
justifyContent: 'space-between',
marginTop: 12,
paddingRight: 4,
}}
>
<ActionButton
icon="chatbubble-outline"
label={formatCount(0) /* replies count — not implemented yet */}
onPress={onOpenDetail}
/>
<Pressable
onPress={onToggleLike}
disabled={busy}
hitSlop={8}
style={({ pressed }) => ({
flexDirection: 'row', alignItems: 'center', gap: 6,
opacity: pressed ? 0.5 : 1,
})}
>
<Animated.View style={{ transform: [{ scale: heartScale }] }}>
<Ionicons
name={localLiked ? 'heart' : 'heart-outline'}
size={16}
color={localLiked ? '#e0245e' : '#6a6a6a'}
/>
</Animated.View>
<Text
style={{
color: localLiked ? '#e0245e' : '#6a6a6a',
fontSize: 12,
fontWeight: localLiked ? '600' : '400',
}}
<View style={{ flex: 1, alignItems: 'flex-start' }}>
<ActionButton
icon="chatbubble-outline"
label={formatCount(0) /* replies count — not implemented yet */}
onPress={onOpenDetail}
/>
</View>
<View style={{ flex: 1, alignItems: 'flex-start' }}>
<Pressable
onPress={onToggleLike}
disabled={busy}
hitSlop={8}
style={({ pressed }) => ({
flexDirection: 'row', alignItems: 'center', gap: 6,
opacity: pressed ? 0.5 : 1,
})}
>
{formatCount(localLikeCount)}
</Text>
</Pressable>
<ActionButton
icon="eye-outline"
label={formatCount(post.views)}
/>
<View style={{ flex: 1 }} />
<ActionButton
icon="share-outline"
onPress={() => {
// Placeholder — copy postID to clipboard in a future PR.
Alert.alert('Ссылка', `dchain://post/${post.post_id}`);
}}
/>
<Animated.View style={{ transform: [{ scale: heartScale }] }}>
<Ionicons
name={localLiked ? 'heart' : 'heart-outline'}
size={16}
color={localLiked ? '#e0245e' : '#6a6a6a'}
/>
</Animated.View>
<Text
style={{
color: localLiked ? '#e0245e' : '#6a6a6a',
fontSize: 12,
fontWeight: localLiked ? '600' : '400',
}}
>
{formatCount(localLikeCount)}
</Text>
</Pressable>
</View>
<View style={{ flex: 1, alignItems: 'flex-start' }}>
<ActionButton
icon="eye-outline"
label={formatCount(post.views)}
/>
</View>
<View style={{ alignItems: 'flex-end' }}>
<ActionButton
icon="share-outline"
onPress={() => {
// Placeholder — copy postID to clipboard in a future PR.
Alert.alert('Ссылка', `dchain://post/${post.post_id}`);
}}
/>
</View>
</View>
</View>
</Pressable>