import { StatusBar } from 'expo-status-bar' import React, { useCallback, useEffect, useMemo, useState } from 'react' import { FlatList, StyleSheet, StatusBar as RNStatusBar, View, ActivityIndicator, RefreshControl, Dimensions, } from 'react-native' import { SafeAreaView, useSafeAreaInsets } from 'react-native-safe-area-context' import { useFocusEffect } from '@react-navigation/native' import { useRouter } from 'expo-router' import { TitleBar, TemplateCard } from '@/components/blocks/home' 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 const CARD_GAP = 8 const SCREEN_WIDTH = Dimensions.get('window').width // 计算卡片宽度 const calculateCardWidth = () => { return (SCREEN_WIDTH - HORIZONTAL_PADDING * 2 - CARD_GAP * (NUM_COLUMNS - 1)) / NUM_COLUMNS } const CARD_WIDTH = calculateCardWidth() export default function FavoritesScreen() { const insets = useSafeAreaInsets() const router = useRouter() // 使用 Store 中的点赞/收藏状态 const { setLiked, setFavorited, incrementLikeCount, decrementLikeCount } = useTemplateSocialStore() // 获取收藏列表 const { favorites, loading, loadingMore, error, execute, refetch, loadMore, hasMore, } = useUserFavorites() // 页面聚焦时刷新数据 useFocusEffect( useCallback(() => { refetch() }, [refetch]) ) // 初始加载 useEffect(() => { execute() }, []) const [refreshing, setRefreshing] = useState(false) // 下拉刷新处理 const handleRefresh = useCallback(async () => { setRefreshing(true) await refetch() setRefreshing(false) }, [refetch]) // 加载更多处理 const handleEndReached = useCallback(() => { if (!loadingMore && hasMore && !loading) { loadMore() } }, [loadingMore, hasMore, loading, loadMore]) // 导航处理 const handleTemplatePress = useCallback((id: string) => { router.push({ pathname: '/templateDetail' as any, params: { id }, }) }, [router]) // 获取 social controller const getSocialController = useCallback(() => { return root.get(TemplateSocialController) }, []) // 点赞/取消点赞处理 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) 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(async (id: string) => { setFavorited(id, true) try { const social = getSocialController() await handleError(() => social.favorite({ templateId: id })) } catch (e) { setFavorited(id, false) } }, [setFavorited, getSocialController]) const handleUnfavorite = useCallback(async (id: string) => { setFavorited(id, false) try { const social = getSocialController() await handleError(() => social.unfavorite({ templateId: id })) } catch (e) { setFavorited(id, true) } }, [setFavorited, getSocialController]) // 状态判断 const isLoading = useMemo(() => loading, [loading]) const showEmptyState = useMemo(() => !isLoading && favorites.length === 0 && !error, [isLoading, favorites.length, error] ) const showErrorState = useMemo(() => !isLoading && error, [isLoading, error] ) // 渲染模板卡片 const renderTemplateItem = useCallback(({ item }: { item: typeof favorites[0] }) => { if (!item.template?.id) return null const template = item.template return ( ) }, [handleTemplatePress, handleLike, handleUnlike, handleFavorite, handleUnfavorite]) // 提取 key const keyExtractor = useCallback((item: typeof favorites[0]) => item.id, []) // 列表头部组件 const ListHeaderComponent = useMemo(() => { if (isLoading) { return } if (showErrorState) { return ( execute()} variant="error" /> ) } if (showEmptyState) { return ( execute()} variant="empty" /> ) } return null }, [isLoading, showErrorState, showEmptyState, execute]) // 列表底部组件 const ListFooterComponent = useMemo(() => { if (loadingMore) { return ( ) } return null }, [loadingMore]) // 只有在非加载状态且有数据时才显示列表 const showTemplateList = !isLoading && !showEmptyState && !showErrorState return ( {/* 标题栏 */} {}} onSearchPress={() => {}} /> } /> ) } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: '#090A0B', }, scrollView: { flex: 1, backgroundColor: '#090A0B', }, scrollContent: { paddingHorizontal: HORIZONTAL_PADDING, paddingBottom: 20, backgroundColor: '#090A0B', }, columnWrapper: { gap: CARD_GAP, marginBottom: CARD_GAP, }, loadingMoreContainer: { paddingVertical: 20, alignItems: 'center', justifyContent: 'center', }, })