diff --git a/assets/empty/country_dark.svg b/assets/empty/country_dark.svg new file mode 100644 index 0000000..0a6a8f1 --- /dev/null +++ b/assets/empty/country_dark.svg @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/assets/empty/country_light.svg b/assets/empty/country_light.svg new file mode 100644 index 0000000..cb93f82 --- /dev/null +++ b/assets/empty/country_light.svg @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/assets/empty/league_dark.svg b/assets/empty/league_dark.svg new file mode 100644 index 0000000..7ed3cdd --- /dev/null +++ b/assets/empty/league_dark.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/assets/empty/league_light.svg b/assets/empty/league_light.svg new file mode 100644 index 0000000..933632e --- /dev/null +++ b/assets/empty/league_light.svg @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/assets/empty/player_dark.svg b/assets/empty/player_dark.svg new file mode 100644 index 0000000..e96d625 --- /dev/null +++ b/assets/empty/player_dark.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/assets/empty/player_light.svg b/assets/empty/player_light.svg new file mode 100644 index 0000000..cca3a47 --- /dev/null +++ b/assets/empty/player_light.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/assets/empty/team_dark.svg b/assets/empty/team_dark.svg new file mode 100644 index 0000000..fe15a8b --- /dev/null +++ b/assets/empty/team_dark.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/assets/empty/team_light.svg b/assets/empty/team_light.svg new file mode 100644 index 0000000..f7c166c --- /dev/null +++ b/assets/empty/team_light.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/assets/league_dark.svg b/assets/league_dark.svg new file mode 100644 index 0000000..9937644 --- /dev/null +++ b/assets/league_dark.svg @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/components/empty-placeholder.tsx b/components/empty-placeholder.tsx new file mode 100644 index 0000000..e6b51e9 --- /dev/null +++ b/components/empty-placeholder.tsx @@ -0,0 +1,34 @@ +import { useTheme } from "@/context/ThemeContext"; +import { Image } from "expo-image"; +import React from "react"; + +interface EmptyPlaceholderProps { + type: "team" | "league" | "player" | "country"; + size?: number; +} + +const imageMap: { [key: string]: any } = { + team_light: require("@/assets/empty/team_light.svg"), + team_dark: require("@/assets/empty/team_dark.svg"), + league_light: require("@/assets/empty/league_light.svg"), + league_dark: require("@/assets/empty/league_dark.svg"), + player_light: require("@/assets/empty/player_light.svg"), + player_dark: require("@/assets/empty/player_dark.svg"), + country_light: require("@/assets/empty/country_light.svg"), + country_dark: require("@/assets/empty/country_dark.svg"), +}; + +export function EmptyPlaceholder({ type, size = 64 }: EmptyPlaceholderProps) { + const { theme } = useTheme(); + const isDark = theme === "dark"; + const suffix = isDark ? "_dark" : "_light"; + const imageKey = `${type}${suffix}`; + + return ( + + ); +} diff --git a/components/league-modal.tsx b/components/league-modal.tsx index 2e113cf..f08196f 100644 --- a/components/league-modal.tsx +++ b/components/league-modal.tsx @@ -1,3 +1,4 @@ +import { EmptyPlaceholder } from "@/components/empty-placeholder"; import { ThemedText } from "@/components/themed-text"; import { IconSymbol } from "@/components/ui/icon-symbol"; import { Colors } from "@/constants/theme"; @@ -47,14 +48,14 @@ export function LeagueModal({ > {/* 左侧图标 */} - {league.logo ? ( + {league.logo && league.logo.trim() !== "" && !league.logo.includes("placehold") ? ( ) : ( - + )} diff --git a/components/live-detail/live-league-info.tsx b/components/live-detail/live-league-info.tsx index 74bb8af..36a4d35 100644 --- a/components/live-detail/live-league-info.tsx +++ b/components/live-detail/live-league-info.tsx @@ -1,3 +1,4 @@ +import { EmptyPlaceholder } from "@/components/empty-placeholder"; import { ThemedText } from "@/components/themed-text"; import { IconSymbol } from "@/components/ui/icon-symbol"; import { LiveScoreMatch } from "@/types/api"; @@ -23,15 +24,13 @@ export function LiveLeagueInfo({ match }: LiveLeagueInfoProps) { activeOpacity={0.7} > - {match.league_logo ? ( + {match.league_logo && match.league_logo.trim() !== "" && !match.league_logo.includes("placehold") ? ( ) : ( - - - + )} {match.league_name} diff --git a/components/live-detail/live-score-header.tsx b/components/live-detail/live-score-header.tsx index 4b06f97..b46d980 100644 --- a/components/live-detail/live-score-header.tsx +++ b/components/live-detail/live-score-header.tsx @@ -1,3 +1,4 @@ +import { EmptyPlaceholder } from "@/components/empty-placeholder"; import { ThemedText } from "@/components/themed-text"; import { IconSymbol } from "@/components/ui/icon-symbol"; import { addFavorite, checkFavorite, removeFavorite } from "@/lib/api"; @@ -265,10 +266,14 @@ export function LiveScoreHeader({ match, topInset }: LiveScoreHeaderProps) { /> - + {homeLogo && homeLogo.trim() !== "" && !homeLogo.includes("placehold") ? ( + + ) : ( + + )} @@ -318,10 +323,14 @@ export function LiveScoreHeader({ match, topInset }: LiveScoreHeaderProps) { - + {awayLogo && awayLogo.trim() !== "" && !awayLogo.includes("placehold") ? ( + + ) : ( + + )} toggleTeamFavorite(match.away_team_key, false)} diff --git a/components/match-card-league.tsx b/components/match-card-league.tsx index b0ff3b9..549d031 100644 --- a/components/match-card-league.tsx +++ b/components/match-card-league.tsx @@ -1,12 +1,11 @@ +import { EmptyPlaceholder } from "@/components/empty-placeholder"; import { ThemedText } from "@/components/themed-text"; import { IconSymbol } from "@/components/ui/icon-symbol"; import { Colors } from "@/constants/theme"; import { useAppState } from "@/context/AppStateContext"; import { useTheme } from "@/context/ThemeContext"; import { addFavorite, removeFavorite } from "@/lib/api"; -import { getInitials, getLogoGradient } from "@/lib/avatar-utils"; import { Match } from "@/types/api"; -import { LinearGradient } from "expo-linear-gradient"; import { useRouter } from "expo-router"; import React, { useState } from "react"; import { Image, Pressable, StyleSheet, TouchableOpacity, View } from "react-native"; @@ -182,13 +181,10 @@ export function MatchCardLeague({ {(() => { - const teamName = isTennis ? (match as any).eventFirstPlayer : (match.home || match.homeTeamName); const logoUri = isTennis ? (match as any).eventFirstPlayerLogo : ((match as any).homeLogo || match.homeTeamLogo); const hasLogo = logoUri && logoUri.trim() !== "" && !logoUri.includes("placehold"); - const gradient = getLogoGradient(teamName || ""); - const initials = getInitials(teamName || ""); return hasLogo ? ( ) : ( - - {initials} - + ); })()} @@ -217,13 +206,10 @@ export function MatchCardLeague({ {(() => { - const teamName = isTennis ? (match as any).eventSecondPlayer : (match.away || match.awayTeamName); const logoUri = isTennis ? (match as any).eventSecondPlayerLogo : ((match as any).awayLogo || match.awayTeamLogo); const hasLogo = logoUri && logoUri.trim() !== "" && !logoUri.includes("placehold"); - const gradient = getLogoGradient(teamName || ""); - const initials = getInitials(teamName || ""); return hasLogo ? ( ) : ( - - {initials} - + ); })()} diff --git a/components/match-card.tsx b/components/match-card.tsx index 0e1d3bb..808b675 100644 --- a/components/match-card.tsx +++ b/components/match-card.tsx @@ -1,3 +1,4 @@ +import { EmptyPlaceholder } from "@/components/empty-placeholder"; import { ThemedText } from "@/components/themed-text"; import { IconSymbol } from "@/components/ui/icon-symbol"; import { Colors } from "@/constants/theme"; @@ -467,13 +468,16 @@ export function MatchCard({ - + {homeLogo && homeLogo.trim() !== "" && !homeLogo.includes("placehold") ? ( + {}} + /> + ) : ( + + )} - + {awayLogo && awayLogo.trim() !== "" && !awayLogo.includes("placehold") ? ( + {}} + /> + ) : ( + + )} {row.logo && row.logo.trim() !== "" && !row.logo.includes("placehold") ? ( - ) : null} + ) : ( + + )} {row.name} diff --git a/components/match-detail/basketball/basketball-stats.tsx b/components/match-detail/basketball/basketball-stats.tsx index 8dfc759..a8c269c 100644 --- a/components/match-detail/basketball/basketball-stats.tsx +++ b/components/match-detail/basketball/basketball-stats.tsx @@ -1,9 +1,8 @@ +import { EmptyPlaceholder } from "@/components/empty-placeholder"; import { ThemedText } from "@/components/themed-text"; import { IconSymbol } from "@/components/ui/icon-symbol"; -import { getInitials, getLogoGradient } from "@/lib/avatar-utils"; import { MatchDetailData } from "@/types/api"; import { Image } from "expo-image"; -import { LinearGradient } from "expo-linear-gradient"; import React, { useMemo, useState } from "react"; import { ScrollView, @@ -161,10 +160,6 @@ export function BasketballStats({ data, isDark }: BasketballStatsProps) { const awayTeamLogo = match.awayTeamLogo || ""; const hasHomeLogo = homeTeamLogo && homeTeamLogo.trim() !== "" && !homeTeamLogo.includes("placehold"); const hasAwayLogo = awayTeamLogo && awayTeamLogo.trim() !== "" && !awayTeamLogo.includes("placehold"); - const homeGradient = getLogoGradient(homeTeamName); - const awayGradient = getLogoGradient(awayTeamName); - const homeInitials = getInitials(homeTeamName); - const awayInitials = getInitials(awayTeamName); return ( @@ -199,12 +194,7 @@ export function BasketballStats({ data, isDark }: BasketballStatsProps) { {hasHomeLogo ? ( ) : ( - - {homeInitials} - + )} ) : ( - - {awayInitials} - + )} diff --git a/components/match-detail/football/football-score-table.tsx b/components/match-detail/football/football-score-table.tsx index a3714a2..06d93fe 100644 --- a/components/match-detail/football/football-score-table.tsx +++ b/components/match-detail/football/football-score-table.tsx @@ -1,3 +1,4 @@ +import { EmptyPlaceholder } from "@/components/empty-placeholder"; import { ThemedText } from "@/components/themed-text"; import { MatchDetailData } from "@/types/api"; import React from "react"; @@ -89,7 +90,11 @@ export function FootballScoreTable({ data, isDark }: FootballScoreTableProps) { {rows.map((row, idx) => ( - + {row.logo && row.logo.trim() !== "" && !row.logo.includes("placehold") ? ( + + ) : ( + + )} {row.name} diff --git a/components/match-detail/league-info.tsx b/components/match-detail/league-info.tsx index 4416b0d..2339b9a 100644 --- a/components/match-detail/league-info.tsx +++ b/components/match-detail/league-info.tsx @@ -1,3 +1,4 @@ +import { EmptyPlaceholder } from "@/components/empty-placeholder"; import { ThemedText } from "@/components/themed-text"; import { IconSymbol } from "@/components/ui/icon-symbol"; import { MatchDetailData } from "@/types/api"; @@ -25,12 +26,10 @@ export function LeagueInfo({ data, isDark }: LeagueInfoProps) { activeOpacity={0.7} > - {match.leagueLogo ? ( + {match.leagueLogo && match.leagueLogo.trim() !== "" && !match.leagueLogo.includes("placehold") ? ( ) : ( - - - + )} {match.leagueName} diff --git a/components/match-detail/score-header.tsx b/components/match-detail/score-header.tsx index 4c68a7e..dac928b 100644 --- a/components/match-detail/score-header.tsx +++ b/components/match-detail/score-header.tsx @@ -1,7 +1,7 @@ +import { EmptyPlaceholder } from "@/components/empty-placeholder"; import { ThemedText } from "@/components/themed-text"; import { IconSymbol } from "@/components/ui/icon-symbol"; import { addFavorite, checkFavorite, removeFavorite } from "@/lib/api"; -import { getInitials, getLogoGradient } from "@/lib/avatar-utils"; import { storage } from "@/lib/storage"; import { MatchDetailData } from "@/types/api"; import { LinearGradient } from "expo-linear-gradient"; @@ -170,10 +170,6 @@ export function ScoreHeader({ data, isDark, topInset }: ScoreHeaderProps) { const hasFirstLogo = firstPlayerLogo && firstPlayerLogo.trim() !== "" && !firstPlayerLogo.includes("placehold"); const hasSecondLogo = secondPlayerLogo && secondPlayerLogo.trim() !== "" && !secondPlayerLogo.includes("placehold"); - const firstGradient = getLogoGradient(firstPlayerName || ""); - const secondGradient = getLogoGradient(secondPlayerName || ""); - const firstInitials = getInitials(firstPlayerName || ""); - const secondInitials = getInitials(secondPlayerName || ""); return ( ) : ( - - {firstInitials} - + )} @@ -283,14 +272,7 @@ export function ScoreHeader({ data, isDark, topInset }: ScoreHeaderProps) { style={styles.teamLogo} /> ) : ( - - {secondInitials} - + )} {(() => { const hasLogo = league.logo && league.logo.trim() !== "" && !league.logo.includes("placehold"); - const gradient = getLogoGradient(league.name || ""); - const initials = getInitials(league.name || ""); return hasLogo ? ( ) : ( - - {initials} - + ); })()} diff --git a/components/upcoming-match-card.tsx b/components/upcoming-match-card.tsx index fd23993..70a0bc6 100644 --- a/components/upcoming-match-card.tsx +++ b/components/upcoming-match-card.tsx @@ -1,3 +1,4 @@ +import { EmptyPlaceholder } from "@/components/empty-placeholder"; import { ThemedText } from "@/components/themed-text"; import { IconSymbol } from "@/components/ui/icon-symbol"; import { Colors } from "@/constants/theme"; @@ -122,12 +123,14 @@ export function UpcomingMatchCard({ - {match.homeTeamLogo && ( + {match.homeTeamLogo && match.homeTeamLogo.trim() !== "" && !match.homeTeamLogo.includes("placehold") ? ( + ) : ( + )} - {match.awayTeamLogo && ( + {match.awayTeamLogo && match.awayTeamLogo.trim() !== "" && !match.awayTeamLogo.includes("placehold") ? ( + ) : ( + )}