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:
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user