import { HomeHeader } from "@/components/home-header"; import { MatchCard } from "@/components/match-card"; import { ThemedText } from "@/components/themed-text"; import { ThemedView } from "@/components/themed-view"; import { Colors } from "@/constants/theme"; import { useAppState } from "@/context/AppStateContext"; import { useTheme } from "@/context/ThemeContext"; import { checkFavorite, fetchLiveScore } from "@/lib/api"; import { storage } from "@/lib/storage"; import { LiveScoreMatch, Match } from "@/types/api"; import { useRouter } from "expo-router"; import React, { useEffect, useState } from "react"; import { useTranslation } from "react-i18next"; import { ActivityIndicator, FlatList, StyleSheet, View } from "react-native"; export default function LiveScreen() { const router = useRouter(); const { theme } = useTheme(); const { t } = useTranslation(); const isDark = theme === "dark"; const { state } = useAppState(); const [matches, setMatches] = useState([]); const [loading, setLoading] = useState(true); useEffect(() => { loadLiveMatches(); // 每30秒自动刷新一次实时比分 const interval = setInterval(loadLiveMatches, 30000); return () => clearInterval(interval); }, [state.selectedSportId, state.selectedLeagueKey, state.timezone]); const loadLiveMatches = async () => { if (!state.selectedSportId) { setLoading(false); return; } setLoading(true); try { const liveData = await fetchLiveScore( state.selectedSportId, state.selectedLeagueKey ? parseInt(state.selectedLeagueKey) : undefined, state.timezone, ); // 检查返回的数据是否为空或无效 if (!liveData || !Array.isArray(liveData)) { console.warn("LiveScore returned invalid data:", liveData); setMatches([]); return; } // 将 LiveScoreMatch 转换为 Match 格式 const converted: Match[] = liveData.map((item: LiveScoreMatch) => ({ id: item.event_key.toString(), league: item.league_name, leagueName: item.league_name, leagueLogo: item.league_logo, time: item.event_time, home: item.event_home_team, away: item.event_away_team, homeTeamName: item.event_home_team, awayTeamName: item.event_away_team, homeTeamLogo: item.home_team_logo, awayTeamLogo: item.away_team_logo, meta: item.event_status, scoreText: item.event_final_result || item.event_halftime_result || "0 - 0", fav: false, leagueId: item.league_key, sportId: state.selectedSportId ?? undefined, isLive: true, date: item.event_date, // Tennis specific mapping eventFirstPlayer: item.event_first_player, eventSecondPlayer: item.event_second_player, eventFirstPlayerLogo: item.event_first_player_logo, eventSecondPlayerLogo: item.event_second_player_logo, eventServe: item.event_serve, scores: item.scores ? JSON.stringify(item.scores) : undefined, })); const token = await storage.getAccessToken(); let listWithFavStatus = converted; if (token) { // 直接传递 match.id 查询是否收藏,并更新列表状态 listWithFavStatus = await Promise.all( converted.map(async (m) => { try { const favRes = await checkFavorite("match", m.id); return { ...m, fav: favRes.isFavorite }; } catch (error) { console.error(`Check favorite failed for match ${m.id}:`, error); return m; } }), ); } // 将收藏的比赛置顶 const sortedList = [...listWithFavStatus].sort((a, b) => { if (a.fav === b.fav) return 0; return a.fav ? -1 : 1; }); setMatches(sortedList); } catch (error) { console.error("Load live matches error:", error); setMatches([]); } finally { setLoading(false); } }; const handleFavoriteToggle = (matchId: string, isFav: boolean) => { setMatches((prev) => { const updated = prev.map((m) => m.id === matchId ? { ...m, fav: isFav } : m, ); return [...updated].sort((a, b) => { if (a.fav === b.fav) return 0; return a.fav ? -1 : 1; }); }); }; return ( {loading ? ( {t("home.loading")} ) : ( item.id} renderItem={({ item }) => ( { router.push({ pathname: "/live-detail/[id]", params: { id: m.id, league_id: m.leagueId?.toString() || "", sport_id: m.sportId?.toString() || "", }, }); }} /> )} contentContainerStyle={styles.listContent} ListEmptyComponent={ {t("home.no_matches_live")} } /> )} ); } const styles = StyleSheet.create({ container: { flex: 1, }, center: { flex: 1, justifyContent: "center", alignItems: "center", paddingTop: 50, }, listContent: { padding: 16, paddingTop: 8, }, });