expo-popcore-app/components/blocks/ui/VideoSocialButton.tsx

140 lines
3.4 KiB
TypeScript

import React, { memo, useCallback } from 'react'
import { View, StyleSheet, Text, Pressable } from 'react-native'
import { Ionicons } from '@expo/vector-icons'
export interface VideoSocialButtonProps {
templateId: string
liked?: boolean
favorited?: boolean
likeCount?: number
favoriteCount?: number
loading?: boolean
onLike?: () => void
onUnlike?: () => void
onFavorite?: () => void
onUnfavorite?: () => void
testID?: string
}
const VideoSocialButtonComponent: React.FC<VideoSocialButtonProps> = ({
templateId,
liked = false,
favorited = false,
likeCount,
favoriteCount,
loading = false,
onLike,
onUnlike,
onFavorite,
onUnfavorite,
testID,
}) => {
// 处理点赞按钮点击
const handleLikePress = useCallback(() => {
if (!loading) {
if (liked) {
onUnlike?.()
} else {
onLike?.()
}
}
}, [loading, liked, onLike, onUnlike])
// 处理收藏按钮点击
const handleFavoritePress = useCallback(() => {
if (!loading) {
if (favorited) {
onUnfavorite?.()
} else {
onFavorite?.()
}
}
}, [loading, favorited, onFavorite, onUnfavorite])
// 格式化数量显示
const formatCount = (count?: number): string => {
if (count === undefined || count === null) return '0'
if (count >= 10000) {
return `${(count / 10000).toFixed(1)}w`
}
if (count >= 1000) {
return `${(count / 1000).toFixed(1)}k`
}
return count.toString()
}
return (
<View style={styles.container} testID={testID}>
{/* 点赞按钮 */}
<Pressable
style={styles.buttonWrapper}
onPress={handleLikePress}
disabled={loading}
testID={testID ? `${testID}-like-button` : undefined}
>
<View style={[styles.iconContainer, liked && styles.iconContainerActive]}>
<Ionicons
name={liked ? 'heart' : 'heart-outline'}
size={28}
color={liked ? '#FF3B30' : '#FFFFFF'}
/>
</View>
<Text style={styles.count}>{formatCount(likeCount)}</Text>
</Pressable>
{/* 收藏按钮 */}
<Pressable
style={styles.buttonWrapper}
onPress={handleFavoritePress}
disabled={loading}
testID={testID ? `${testID}-favorite-button` : undefined}
>
<View style={[styles.iconContainer, favorited && styles.iconContainerActive]}>
<Ionicons
name={favorited ? 'star' : 'star-outline'}
size={28}
color={favorited ? '#FFD700' : '#FFFFFF'}
/>
</View>
<Text style={styles.count}>{formatCount(favoriteCount)}</Text>
</Pressable>
</View>
)
}
export const VideoSocialButton = memo(VideoSocialButtonComponent)
const styles = StyleSheet.create({
container: {
position: 'absolute',
right: 12,
bottom: 180,
flexDirection: 'column',
alignItems: 'center',
gap: 20,
},
buttonWrapper: {
alignItems: 'center',
gap: 4,
},
iconContainer: {
width: 52,
height: 52,
borderRadius: 26,
backgroundColor: 'rgba(0, 0, 0, 0.3)',
justifyContent: 'center',
alignItems: 'center',
},
iconContainerActive: {
backgroundColor: 'rgba(255, 255, 255, 0.15)',
},
count: {
color: '#FFFFFF',
fontSize: 12,
fontWeight: '600',
textShadowColor: 'rgba(0, 0, 0, 0.5)',
textShadowOffset: { width: 0, height: 1 },
textShadowRadius: 2,
},
})