fix: bug
This commit is contained in:
parent
7f84a348a7
commit
6fc87d59de
|
|
@ -25,6 +25,9 @@ import { useTemplateFilter } from '@/hooks/use-template-filter'
|
|||
import { useUserBalance } from '@/hooks/use-user-balance'
|
||||
import { useTemplateLike, useTemplateFavorite } from '@/hooks'
|
||||
import { useTemplateSocialStore } from '@/stores/templateSocialStore'
|
||||
import { root } from '@repo/core'
|
||||
import { TemplateSocialController } from '@repo/sdk'
|
||||
import { handleError } from '@/hooks/use-error'
|
||||
|
||||
const NUM_COLUMNS = 3
|
||||
const HORIZONTAL_PADDING = 16
|
||||
|
|
@ -108,6 +111,21 @@ export default function HomeScreen() {
|
|||
}
|
||||
}, [params.categoryId])
|
||||
|
||||
// 同步模板的点赞数量到 store(用于初始化 store 中的数据)
|
||||
useEffect(() => {
|
||||
if (filteredTemplates.length > 0) {
|
||||
const likeCountMap: Record<string, number> = {}
|
||||
filteredTemplates.forEach(template => {
|
||||
if (template.id && 'likeCount' in template && template.likeCount !== undefined) {
|
||||
likeCountMap[template.id] = template.likeCount
|
||||
}
|
||||
})
|
||||
if (Object.keys(likeCountMap).length > 0) {
|
||||
setLikeCountStates(likeCountMap)
|
||||
}
|
||||
}
|
||||
}, [filteredTemplates, setLikeCountStates])
|
||||
|
||||
// 状态判断 - 使用 useMemo 缓存
|
||||
// 统一 loading 状态:只要有任何一个在加载,就显示 loading
|
||||
const isLoading = useMemo(() =>
|
||||
|
|
@ -154,35 +172,72 @@ export default function HomeScreen() {
|
|||
}), [router])
|
||||
|
||||
// 使用 Store 中的点赞/收藏状态
|
||||
const { setLiked, setFavorited } = useTemplateSocialStore()
|
||||
const { setLiked, setFavorited, incrementLikeCount, decrementLikeCount, setLikeCountStates } = useTemplateSocialStore()
|
||||
|
||||
// 获取 social controller
|
||||
const getSocialController = useCallback(() => {
|
||||
return root.get(TemplateSocialController)
|
||||
}, [])
|
||||
|
||||
// 点赞处理
|
||||
const handleLike = useCallback((id: string) => {
|
||||
const currentState = setLiked(id, true) // 乐观更新
|
||||
// TODO: 调用 API
|
||||
console.log('Like template:', id)
|
||||
}, [setLiked])
|
||||
const handleLike = useCallback(async (id: string) => {
|
||||
setLiked(id, true) // 乐观更新状态
|
||||
incrementLikeCount(id) // 乐观更新数量
|
||||
try {
|
||||
const social = getSocialController()
|
||||
await handleError(() => social.like({ templateId: id }))
|
||||
console.log('Liked template:', id)
|
||||
} catch (e) {
|
||||
// 失败时回滚状态
|
||||
setLiked(id, false)
|
||||
decrementLikeCount(id)
|
||||
console.error('Like failed:', e)
|
||||
}
|
||||
}, [setLiked, incrementLikeCount, decrementLikeCount, getSocialController])
|
||||
|
||||
// 取消点赞处理
|
||||
const handleUnlike = useCallback((id: string) => {
|
||||
const currentState = setLiked(id, false) // 乐观更新
|
||||
// TODO: 调用 API
|
||||
console.log('Unlike template:', id)
|
||||
}, [setLiked])
|
||||
const handleUnlike = useCallback(async (id: string) => {
|
||||
setLiked(id, false) // 乐观更新状态
|
||||
decrementLikeCount(id) // 乐观更新数量
|
||||
try {
|
||||
const social = getSocialController()
|
||||
await handleError(() => social.unlike({ templateId: id }))
|
||||
console.log('Unliked template:', id)
|
||||
} catch (e) {
|
||||
// 失败时回滚状态
|
||||
setLiked(id, true)
|
||||
incrementLikeCount(id)
|
||||
console.error('Unlike failed:', e)
|
||||
}
|
||||
}, [setLiked, incrementLikeCount, decrementLikeCount, getSocialController])
|
||||
|
||||
// 收藏处理
|
||||
const handleFavorite = useCallback((id: string) => {
|
||||
const currentState = setFavorited(id, true) // 乐观更新
|
||||
// TODO: 调用 API
|
||||
console.log('Favorite template:', id)
|
||||
}, [setFavorited])
|
||||
const handleFavorite = useCallback(async (id: string) => {
|
||||
setFavorited(id, true) // 乐观更新
|
||||
try {
|
||||
const social = getSocialController()
|
||||
await handleError(() => social.favorite({ templateId: id }))
|
||||
console.log('Favorited template:', id)
|
||||
} catch (e) {
|
||||
// 失败时回滚状态
|
||||
setFavorited(id, false)
|
||||
console.error('Favorite failed:', e)
|
||||
}
|
||||
}, [setFavorited, getSocialController])
|
||||
|
||||
// 取消收藏处理
|
||||
const handleUnfavorite = useCallback((id: string) => {
|
||||
const currentState = setFavorited(id, false) // 乐观更新
|
||||
// TODO: 调用 API
|
||||
console.log('Unfavorite template:', id)
|
||||
}, [setFavorited])
|
||||
const handleUnfavorite = useCallback(async (id: string) => {
|
||||
setFavorited(id, false) // 乐观更新
|
||||
try {
|
||||
const social = getSocialController()
|
||||
await handleError(() => social.unfavorite({ templateId: id }))
|
||||
console.log('Unfavorited template:', id)
|
||||
} catch (e) {
|
||||
// 失败时回滚状态
|
||||
setFavorited(id, true)
|
||||
console.error('Unfavorite failed:', e)
|
||||
}
|
||||
}, [setFavorited, getSocialController])
|
||||
|
||||
// 渲染模板卡片
|
||||
const renderTemplateItem = useCallback(({ item }: { item: typeof filteredTemplates[0] }) => {
|
||||
|
|
@ -200,6 +255,7 @@ export default function HomeScreen() {
|
|||
onPress={handleTemplatePress}
|
||||
liked={'isLiked' in item ? item.isLiked : undefined}
|
||||
favorited={'isFavorited' in item ? item.isFavorited : undefined}
|
||||
likeCount={'likeCount' in item ? item.likeCount : undefined}
|
||||
onLike={handleLike}
|
||||
onUnlike={handleUnlike}
|
||||
onFavorite={handleFavorite}
|
||||
|
|
|
|||
|
|
@ -18,6 +18,9 @@ import ErrorState from '@/components/ErrorState'
|
|||
import LoadingState from '@/components/LoadingState'
|
||||
import { useUserFavorites } from '@/hooks/use-user-favorites'
|
||||
import { useTemplateSocialStore } from '@/stores/templateSocialStore'
|
||||
import { root } from '@repo/core'
|
||||
import { TemplateSocialController } from '@repo/sdk'
|
||||
import { handleError } from '@/hooks/use-error'
|
||||
|
||||
const NUM_COLUMNS = 2
|
||||
const HORIZONTAL_PADDING = 16
|
||||
|
|
@ -36,7 +39,7 @@ export default function FavoritesScreen() {
|
|||
const router = useRouter()
|
||||
|
||||
// 使用 Store 中的点赞/收藏状态
|
||||
const { setLiked, setFavorited } = useTemplateSocialStore()
|
||||
const { setLiked, setFavorited, incrementLikeCount, decrementLikeCount } = useTemplateSocialStore()
|
||||
|
||||
// 获取收藏列表
|
||||
const {
|
||||
|
|
@ -86,27 +89,56 @@ export default function FavoritesScreen() {
|
|||
})
|
||||
}, [router])
|
||||
|
||||
// 点赞/取消点赞处理
|
||||
const handleLike = useCallback((id: string) => {
|
||||
setLiked(id, true)
|
||||
console.log('Like template:', id)
|
||||
}, [setLiked])
|
||||
// 获取 social controller
|
||||
const getSocialController = useCallback(() => {
|
||||
return root.get(TemplateSocialController)
|
||||
}, [])
|
||||
|
||||
const handleUnlike = useCallback((id: string) => {
|
||||
// 点赞/取消点赞处理
|
||||
const handleLike = useCallback(async (id: string) => {
|
||||
setLiked(id, true)
|
||||
incrementLikeCount(id)
|
||||
try {
|
||||
const social = getSocialController()
|
||||
await handleError(() => social.like({ templateId: id }))
|
||||
} catch (e) {
|
||||
setLiked(id, false)
|
||||
decrementLikeCount(id)
|
||||
}
|
||||
}, [setLiked, incrementLikeCount, decrementLikeCount, getSocialController])
|
||||
|
||||
const handleUnlike = useCallback(async (id: string) => {
|
||||
setLiked(id, false)
|
||||
console.log('Unlike template:', id)
|
||||
}, [setLiked])
|
||||
decrementLikeCount(id)
|
||||
try {
|
||||
const social = getSocialController()
|
||||
await handleError(() => social.unlike({ templateId: id }))
|
||||
} catch (e) {
|
||||
setLiked(id, true)
|
||||
incrementLikeCount(id)
|
||||
}
|
||||
}, [setLiked, incrementLikeCount, decrementLikeCount, getSocialController])
|
||||
|
||||
// 收藏/取消收藏处理
|
||||
const handleFavorite = useCallback((id: string) => {
|
||||
const handleFavorite = useCallback(async (id: string) => {
|
||||
setFavorited(id, true)
|
||||
console.log('Favorite template:', id)
|
||||
}, [setFavorited])
|
||||
try {
|
||||
const social = getSocialController()
|
||||
await handleError(() => social.favorite({ templateId: id }))
|
||||
} catch (e) {
|
||||
setFavorited(id, false)
|
||||
}
|
||||
}, [setFavorited, getSocialController])
|
||||
|
||||
const handleUnfavorite = useCallback((id: string) => {
|
||||
const handleUnfavorite = useCallback(async (id: string) => {
|
||||
setFavorited(id, false)
|
||||
console.log('Unfavorite template:', id)
|
||||
}, [setFavorited])
|
||||
try {
|
||||
const social = getSocialController()
|
||||
await handleError(() => social.unfavorite({ templateId: id }))
|
||||
} catch (e) {
|
||||
setFavorited(id, true)
|
||||
}
|
||||
}, [setFavorited, getSocialController])
|
||||
|
||||
// 状态判断
|
||||
const isLoading = useMemo(() => loading, [loading])
|
||||
|
|
@ -137,6 +169,7 @@ export default function FavoritesScreen() {
|
|||
onPress={handleTemplatePress}
|
||||
liked={template.isLiked}
|
||||
favorited={template.isFavorited}
|
||||
likeCount={template.likeCount}
|
||||
onLike={handleLike}
|
||||
onUnlike={handleUnlike}
|
||||
onFavorite={handleFavorite}
|
||||
|
|
|
|||
|
|
@ -18,6 +18,9 @@ import ErrorState from '@/components/ErrorState'
|
|||
import LoadingState from '@/components/LoadingState'
|
||||
import { useUserLikes } from '@/hooks'
|
||||
import { useTemplateSocialStore } from '@/stores/templateSocialStore'
|
||||
import { root } from '@repo/core'
|
||||
import { TemplateSocialController } from '@repo/sdk'
|
||||
import { handleError } from '@/hooks/use-error'
|
||||
|
||||
const NUM_COLUMNS = 2
|
||||
const HORIZONTAL_PADDING = 16
|
||||
|
|
@ -37,7 +40,7 @@ export default function LikesScreen() {
|
|||
const [refreshing, setRefreshing] = useState(false)
|
||||
|
||||
// 使用 Store 中的点赞/收藏状态
|
||||
const { setLiked, setFavorited } = useTemplateSocialStore()
|
||||
const { setLiked, setFavorited, incrementLikeCount, decrementLikeCount } = useTemplateSocialStore()
|
||||
|
||||
// 获取用户点赞列表
|
||||
const {
|
||||
|
|
@ -78,27 +81,56 @@ export default function LikesScreen() {
|
|||
})
|
||||
}, [router])
|
||||
|
||||
// 点赞/取消点赞处理
|
||||
const handleLike = useCallback((id: string) => {
|
||||
setLiked(id, true)
|
||||
console.log('Like template:', id)
|
||||
}, [setLiked])
|
||||
// 获取 social controller
|
||||
const getSocialController = useCallback(() => {
|
||||
return root.get(TemplateSocialController)
|
||||
}, [])
|
||||
|
||||
const handleUnlike = useCallback((id: string) => {
|
||||
// 点赞/取消点赞处理
|
||||
const handleLike = useCallback(async (id: string) => {
|
||||
setLiked(id, true)
|
||||
incrementLikeCount(id)
|
||||
try {
|
||||
const social = getSocialController()
|
||||
await handleError(() => social.like({ templateId: id }))
|
||||
} catch (e) {
|
||||
setLiked(id, false)
|
||||
decrementLikeCount(id)
|
||||
}
|
||||
}, [setLiked, incrementLikeCount, decrementLikeCount, getSocialController])
|
||||
|
||||
const handleUnlike = useCallback(async (id: string) => {
|
||||
setLiked(id, false)
|
||||
console.log('Unlike template:', id)
|
||||
}, [setLiked])
|
||||
decrementLikeCount(id)
|
||||
try {
|
||||
const social = getSocialController()
|
||||
await handleError(() => social.unlike({ templateId: id }))
|
||||
} catch (e) {
|
||||
setLiked(id, true)
|
||||
incrementLikeCount(id)
|
||||
}
|
||||
}, [setLiked, incrementLikeCount, decrementLikeCount, getSocialController])
|
||||
|
||||
// 收藏/取消收藏处理
|
||||
const handleFavorite = useCallback((id: string) => {
|
||||
const handleFavorite = useCallback(async (id: string) => {
|
||||
setFavorited(id, true)
|
||||
console.log('Favorite template:', id)
|
||||
}, [setFavorited])
|
||||
try {
|
||||
const social = getSocialController()
|
||||
await handleError(() => social.favorite({ templateId: id }))
|
||||
} catch (e) {
|
||||
setFavorited(id, false)
|
||||
}
|
||||
}, [setFavorited, getSocialController])
|
||||
|
||||
const handleUnfavorite = useCallback((id: string) => {
|
||||
const handleUnfavorite = useCallback(async (id: string) => {
|
||||
setFavorited(id, false)
|
||||
console.log('Unfavorite template:', id)
|
||||
}, [setFavorited])
|
||||
try {
|
||||
const social = getSocialController()
|
||||
await handleError(() => social.unfavorite({ templateId: id }))
|
||||
} catch (e) {
|
||||
setFavorited(id, true)
|
||||
}
|
||||
}, [setFavorited, getSocialController])
|
||||
|
||||
// 状态判断
|
||||
const showEmptyState = useMemo(() =>
|
||||
|
|
@ -133,6 +165,7 @@ export default function LikesScreen() {
|
|||
onPress={handleTemplatePress}
|
||||
liked={item.template.isLiked}
|
||||
favorited={item.template.isFavorited}
|
||||
likeCount={item.template.likeCount}
|
||||
onLike={handleLike}
|
||||
onUnlike={handleUnlike}
|
||||
onFavorite={handleFavorite}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import { Image } from 'expo-image'
|
|||
import { LinearGradient } from 'expo-linear-gradient'
|
||||
import { Ionicons } from '@expo/vector-icons'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useTemplateSocialStore } from '@/stores/templateSocialStore'
|
||||
import { useTemplateSocialStore, useTemplateLiked, useTemplateFavorited, useTemplateLikeCount } from '@/stores/templateSocialStore'
|
||||
|
||||
export interface TemplateCardProps {
|
||||
id?: string
|
||||
|
|
@ -18,6 +18,7 @@ export interface TemplateCardProps {
|
|||
onPress: (id: string) => void
|
||||
liked?: boolean
|
||||
favorited?: boolean
|
||||
likeCount?: number
|
||||
onLike?: (id: string) => void
|
||||
onUnlike?: (id: string) => void
|
||||
onFavorite?: (id: string) => void
|
||||
|
|
@ -51,6 +52,23 @@ export function getImageUri(
|
|||
return webpPreviewUrl || previewUrl || coverImageUrl
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化数字显示
|
||||
* 1000以下: 显示原数字
|
||||
* 1000-9999: 1.2k
|
||||
* 10000-99999: 1w
|
||||
* 100000以上: 10w
|
||||
*/
|
||||
export function formatCount(count: number): string {
|
||||
if (count < 1000) {
|
||||
return count.toString()
|
||||
}
|
||||
if (count < 10000) {
|
||||
return `${(count / 1000).toFixed(1).replace(/\.0$/, '')}k`
|
||||
}
|
||||
return `${(count / 10000).toFixed(1).replace(/\.0$/, '')}w`
|
||||
}
|
||||
|
||||
// 渐变颜色常量,避免每次渲染创建新数组
|
||||
const GRADIENT_COLORS = ['rgba(17, 17, 17, 0)', 'rgba(17, 17, 17, 0.9)'] as const
|
||||
const GRADIENT_START = { x: 0, y: 0 }
|
||||
|
|
@ -68,6 +86,7 @@ const TemplateCardComponent: React.FC<TemplateCardProps> = ({
|
|||
onPress,
|
||||
liked: likedProp,
|
||||
favorited: favoritedProp,
|
||||
likeCount: likeCountProp,
|
||||
onLike,
|
||||
onUnlike,
|
||||
onFavorite,
|
||||
|
|
@ -76,12 +95,16 @@ const TemplateCardComponent: React.FC<TemplateCardProps> = ({
|
|||
}) => {
|
||||
const { i18n } = useTranslation()
|
||||
|
||||
// 获取 Store 中的状态(用于本地状态覆盖)
|
||||
const { isLiked: isLikedInStore, isFavorited: isFavoritedInStore } = useTemplateSocialStore()
|
||||
// 订阅特定模板的点赞/收藏状态和点赞数量
|
||||
// 当该模板的状态变化时才会触发重新渲染,不影响其他卡片
|
||||
const storeLiked = useTemplateLiked(id)
|
||||
const storeFavorited = useTemplateFavorited(id)
|
||||
const storeLikeCount = useTemplateLikeCount(id)
|
||||
|
||||
// 合并 props 状态和 store 状态:store 优先(乐观更新)
|
||||
const liked = id !== undefined ? isLikedInStore(id) ?? likedProp : likedProp
|
||||
const favorited = id !== undefined ? isFavoritedInStore(id) ?? favoritedProp : favoritedProp
|
||||
const liked = storeLiked ?? likedProp
|
||||
const favorited = storeFavorited ?? favoritedProp
|
||||
const likeCount = storeLikeCount ?? likeCountProp
|
||||
|
||||
const aspectRatio = useMemo(() => parseAspectRatio(aspectRatioString), [aspectRatioString])
|
||||
const imageUri = useMemo(() => getImageUri(webpPreviewUrl, previewUrl, coverImageUrl), [webpPreviewUrl, previewUrl, coverImageUrl])
|
||||
|
|
@ -179,7 +202,12 @@ const TemplateCardComponent: React.FC<TemplateCardProps> = ({
|
|||
hitSlop={{ top: 8, bottom: 8, left: 8, right: 8 }}
|
||||
testID={`${testID}-like-button`}
|
||||
>
|
||||
<Ionicons name={likeIconName} size={16} color={likeIconColor} style={styles.icon} />
|
||||
<View style={styles.likeButtonContainer}>
|
||||
<Ionicons name={likeIconName} size={16} color={likeIconColor} style={styles.icon} />
|
||||
{likeCount !== undefined && likeCount > 0 && (
|
||||
<Text style={styles.likeCount}>{formatCount(likeCount)}</Text>
|
||||
)}
|
||||
</View>
|
||||
</Pressable>
|
||||
<Pressable
|
||||
onPress={(e) => {
|
||||
|
|
@ -196,7 +224,12 @@ const TemplateCardComponent: React.FC<TemplateCardProps> = ({
|
|||
) : (
|
||||
// 没有回调时显示为静态图标
|
||||
<View style={styles.iconsContainer}>
|
||||
<Ionicons name={likeIconName} size={16} color={likeIconColor} style={styles.icon} />
|
||||
<View style={styles.likeButtonContainer}>
|
||||
<Ionicons name={likeIconName} size={16} color={likeIconColor} style={styles.icon} />
|
||||
{likeCount !== undefined && likeCount > 0 && (
|
||||
<Text style={styles.likeCount}>{formatCount(likeCount)}</Text>
|
||||
)}
|
||||
</View>
|
||||
<Ionicons name={favoriteIconName} size={16} color={favoriteIconColor} style={styles.icon} />
|
||||
</View>
|
||||
)}
|
||||
|
|
@ -238,6 +271,11 @@ const styles = StyleSheet.create({
|
|||
flexDirection: 'row',
|
||||
gap: 4,
|
||||
},
|
||||
likeButtonContainer: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
gap: 2,
|
||||
},
|
||||
iconButton: {
|
||||
padding: 4,
|
||||
},
|
||||
|
|
@ -248,6 +286,15 @@ const styles = StyleSheet.create({
|
|||
shadowRadius: 2,
|
||||
elevation: 2,
|
||||
},
|
||||
likeCount: {
|
||||
fontSize: 10,
|
||||
fontWeight: '600',
|
||||
color: '#F5F5F5',
|
||||
textShadowColor: 'rgba(0, 0, 0, 0.5)',
|
||||
textShadowOffset: { width: 0, height: 1 },
|
||||
textShadowRadius: 2,
|
||||
minWidth: 12,
|
||||
},
|
||||
cardTitle: {
|
||||
position: 'absolute',
|
||||
bottom: 8,
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import { create } from 'zustand'
|
||||
import { devtools } from 'zustand/middleware'
|
||||
|
||||
interface TemplateSocialState {
|
||||
// 点赞状态缓存: templateId -> boolean
|
||||
|
|
@ -7,70 +8,166 @@ interface TemplateSocialState {
|
|||
// 收藏状态缓存: templateId -> boolean
|
||||
favoritedMap: Record<string, boolean>
|
||||
|
||||
// 点赞数量缓存: templateId -> number
|
||||
likeCountMap: Record<string, number>
|
||||
|
||||
// 批量更新点赞状态
|
||||
setLikedStates: (states: Record<string, boolean>) => void
|
||||
|
||||
// 批量更新收藏状态
|
||||
setFavoritedStates: (states: Record<string, boolean>) => void
|
||||
|
||||
// 批量更新点赞数量
|
||||
setLikeCountStates: (states: Record<string, number>) => void
|
||||
|
||||
// 更新单个点赞状态
|
||||
setLiked: (templateId: string, liked: boolean) => void
|
||||
|
||||
// 更新单个收藏状态
|
||||
setFavorited: (templateId: string, favorited: boolean) => void
|
||||
|
||||
// 获取点赞状态
|
||||
// 更新单个点赞数量
|
||||
setLikeCount: (templateId: string, count: number) => void
|
||||
|
||||
// 增加点赞数量(乐观更新)
|
||||
incrementLikeCount: (templateId: string) => void
|
||||
|
||||
// 减少点赞数量(乐观更新)
|
||||
decrementLikeCount: (templateId: string) => void
|
||||
|
||||
// 获取点赞状态(如果不存在返回 undefined)
|
||||
getLiked: (templateId: string) => boolean | undefined
|
||||
|
||||
// 获取收藏状态(如果不存在返回 undefined)
|
||||
getFavorited: (templateId: string) => boolean | undefined
|
||||
|
||||
// 获取点赞数量(如果不存在返回 undefined)
|
||||
getLikeCount: (templateId: string) => number | undefined
|
||||
|
||||
// 获取点赞状态(如果不存在返回 false)
|
||||
isLiked: (templateId: string) => boolean
|
||||
|
||||
// 获取收藏状态
|
||||
// 获取收藏状态(如果不存在返回 false)
|
||||
isFavorited: (templateId: string) => boolean
|
||||
|
||||
// 清空所有缓存
|
||||
clear: () => void
|
||||
}
|
||||
|
||||
export const useTemplateSocialStore = create<TemplateSocialState>((set, get) => ({
|
||||
// State
|
||||
likedMap: {},
|
||||
favoritedMap: {},
|
||||
|
||||
// Actions
|
||||
setLikedStates: (states) => {
|
||||
set((state) => ({
|
||||
likedMap: { ...state.likedMap, ...states },
|
||||
}))
|
||||
},
|
||||
|
||||
setFavoritedStates: (states) => {
|
||||
set((state) => ({
|
||||
favoritedMap: { ...state.favoritedMap, ...states },
|
||||
}))
|
||||
},
|
||||
|
||||
setLiked: (templateId, liked) => {
|
||||
set((state) => ({
|
||||
likedMap: { ...state.likedMap, [templateId]: liked },
|
||||
}))
|
||||
},
|
||||
|
||||
setFavorited: (templateId, favorited) => {
|
||||
set((state) => ({
|
||||
favoritedMap: { ...state.favoritedMap, [templateId]: favorited },
|
||||
}))
|
||||
},
|
||||
|
||||
isLiked: (templateId) => {
|
||||
return get().likedMap[templateId] || false
|
||||
},
|
||||
|
||||
isFavorited: (templateId) => {
|
||||
return get().favoritedMap[templateId] || false
|
||||
},
|
||||
|
||||
clear: () => {
|
||||
set({
|
||||
export const useTemplateSocialStore = create<TemplateSocialState>()(
|
||||
devtools(
|
||||
(set, get) => ({
|
||||
// State
|
||||
likedMap: {},
|
||||
favoritedMap: {},
|
||||
})
|
||||
},
|
||||
}))
|
||||
likeCountMap: {},
|
||||
|
||||
// Actions
|
||||
setLikedStates: (states) => {
|
||||
set((state) => ({
|
||||
likedMap: { ...state.likedMap, ...states },
|
||||
}))
|
||||
},
|
||||
|
||||
setFavoritedStates: (states) => {
|
||||
set((state) => ({
|
||||
favoritedMap: { ...state.favoritedMap, ...states },
|
||||
}))
|
||||
},
|
||||
|
||||
setLikeCountStates: (states) => {
|
||||
set((state) => ({
|
||||
likeCountMap: { ...state.likeCountMap, ...states },
|
||||
}))
|
||||
},
|
||||
|
||||
setLiked: (templateId, liked) => {
|
||||
set((state) => ({
|
||||
likedMap: { ...state.likedMap, [templateId]: liked },
|
||||
}))
|
||||
},
|
||||
|
||||
setFavorited: (templateId, favorited) => {
|
||||
set((state) => ({
|
||||
favoritedMap: { ...state.favoritedMap, [templateId]: favorited },
|
||||
}))
|
||||
},
|
||||
|
||||
setLikeCount: (templateId, count) => {
|
||||
set((state) => ({
|
||||
likeCountMap: { ...state.likeCountMap, [templateId]: count },
|
||||
}))
|
||||
},
|
||||
|
||||
incrementLikeCount: (templateId) => {
|
||||
set((state) => ({
|
||||
likeCountMap: {
|
||||
...state.likeCountMap,
|
||||
[templateId]: (state.likeCountMap[templateId] || 0) + 1,
|
||||
},
|
||||
}))
|
||||
},
|
||||
|
||||
decrementLikeCount: (templateId) => {
|
||||
set((state) => {
|
||||
const currentCount = state.likeCountMap[templateId] || 0
|
||||
return {
|
||||
likeCountMap: {
|
||||
...state.likeCountMap,
|
||||
[templateId]: Math.max(0, currentCount - 1),
|
||||
},
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
getLiked: (templateId) => {
|
||||
return get().likedMap[templateId]
|
||||
},
|
||||
|
||||
getFavorited: (templateId) => {
|
||||
return get().favoritedMap[templateId]
|
||||
},
|
||||
|
||||
getLikeCount: (templateId) => {
|
||||
return get().likeCountMap[templateId]
|
||||
},
|
||||
|
||||
isLiked: (templateId) => {
|
||||
return get().likedMap[templateId] || false
|
||||
},
|
||||
|
||||
isFavorited: (templateId) => {
|
||||
return get().favoritedMap[templateId] || false
|
||||
},
|
||||
|
||||
clear: () => {
|
||||
set({
|
||||
likedMap: {},
|
||||
favoritedMap: {},
|
||||
likeCountMap: {},
|
||||
})
|
||||
},
|
||||
}),
|
||||
{ name: 'TemplateSocialStore' }
|
||||
)
|
||||
)
|
||||
|
||||
// 选择器 hook:只订阅特定模板的状态
|
||||
// 当该模板的状态变化时才会触发重新渲染
|
||||
export function useTemplateLiked(templateId: string | undefined) {
|
||||
return useTemplateSocialStore((state) =>
|
||||
templateId ? state.likedMap[templateId] : undefined
|
||||
)
|
||||
}
|
||||
|
||||
export function useTemplateFavorited(templateId: string | undefined) {
|
||||
return useTemplateSocialStore((state) =>
|
||||
templateId ? state.favoritedMap[templateId] : undefined
|
||||
)
|
||||
}
|
||||
|
||||
export function useTemplateLikeCount(templateId: string | undefined) {
|
||||
return useTemplateSocialStore((state) =>
|
||||
templateId ? state.likeCountMap[templateId] : undefined
|
||||
)
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue