diff --git a/app/profile.tsx b/app/profile.tsx index 8b31215..6155044 100644 --- a/app/profile.tsx +++ b/app/profile.tsx @@ -37,7 +37,12 @@ const BOOKMAKERS = [ export default function ProfileScreen() { const { theme, toggleTheme, setTheme, isSystemTheme, useSystemTheme } = useTheme(); - const { state, updateOddsSettings, updateCardsSettings } = useAppState(); + const { + state, + updateOddsSettings, + updateCardsSettings, + updateCornerSettings, + } = useAppState(); const { t, i18n } = useTranslation(); const router = useRouter(); const isDark = theme === "dark"; @@ -62,6 +67,13 @@ export default function ProfileScreen() { }); }; + const toggleCorners = () => { + updateCornerSettings({ + ...state.cornerSettings, + enabled: !state.cornerSettings.enabled, + }); + }; + const selectBookmaker = (name: string) => { const current = state.oddsSettings.selectedBookmakers; let next: string[]; @@ -468,6 +480,38 @@ export default function ProfileScreen() { + + {t("settings.corner_title")} + + + + + + + {t("settings.corner_show")} + + + + + {state.cornerSettings.enabled + ? t("settings.corner_enabled") + : t("settings.corner_disabled")} + + + + + + {/* 登录 { if ( @@ -59,9 +60,13 @@ export function MatchCard({ match.odds, ]); - // Fetch live score detail for cards info + // Fetch live score detail for cards and corners info useEffect(() => { - if (cardsSettings.enabled && isLive && match.leagueKey) { + if ( + (cardsSettings.enabled || cornerSettings.enabled) && + isLive && + match.leagueKey + ) { fetchLiveScore(match.sportId || 1, Number(match.leagueKey)) .then((matches) => { const detail = matches.find((m) => String(m.event_key) === match.id); @@ -71,7 +76,13 @@ export function MatchCard({ }) .catch((err) => console.log("Fetch live detail for cards error:", err)); } - }, [cardsSettings.enabled, match.id, match.leagueKey, match.sportId]); + }, [ + cardsSettings.enabled, + cornerSettings.enabled, + match.id, + match.leagueKey, + match.sportId, + ]); // 当外部传入的 match.fav 改变时,更新内部状态 useEffect(() => { @@ -158,6 +169,26 @@ export function MatchCard({ return { homeYellow, homeRed, awayYellow, awayRed }; }, [liveDetail, cardsSettings.enabled]); + const extraStats = React.useMemo(() => { + if (!liveDetail?.statistics || !cornerSettings.enabled) { + return { home: "", away: "" }; + } + + const corners = liveDetail.statistics.find((s) => s.type === "Corners"); + if (corners) { + return { home: corners.home, away: corners.away }; + } + + const dangerousAttacks = liveDetail.statistics.find( + (s) => s.type === "Dangerous Attacks", + ); + if (dangerousAttacks) { + return { home: dangerousAttacks.home, away: dangerousAttacks.away }; + } + + return { home: "", away: "" }; + }, [liveDetail, cornerSettings.enabled]); + const handlePress = () => { if (onPress) { onPress(match); @@ -384,6 +415,17 @@ export function MatchCard({ )} + {(extraStats.home !== "" || extraStats.away !== "") && ( + + + {extraStats.home} + + + {extraStats.away} + + + )} + { e.stopPropagation(); @@ -539,6 +581,17 @@ const styles = StyleSheet.create({ cardBadgeRed: { backgroundColor: "#FF3B30", }, + extraStatsColumn: { + alignItems: "center", + justifyContent: "space-between", + height: 48, + paddingVertical: 2, + }, + extraStatText: { + fontSize: 12, + fontWeight: "500", + opacity: 0.6, + }, cardBadgeText: { fontSize: 10, fontWeight: "900", diff --git a/context/AppStateContext.tsx b/context/AppStateContext.tsx index 08d30e4..a86f622 100644 --- a/context/AppStateContext.tsx +++ b/context/AppStateContext.tsx @@ -1,4 +1,9 @@ -import { CardsSettings, OddsSettings, storage } from "@/lib/storage"; +import { + CardsSettings, + CornerSettings, + OddsSettings, + storage, +} from "@/lib/storage"; import React, { createContext, ReactNode, @@ -14,6 +19,7 @@ interface AppState { timezone: string; oddsSettings: OddsSettings; cardsSettings: CardsSettings; + cornerSettings: CornerSettings; } interface AppStateContextType { @@ -24,6 +30,7 @@ interface AppStateContextType { updateTimezone: (timezone: string) => void; updateOddsSettings: (settings: OddsSettings) => void; updateCardsSettings: (settings: CardsSettings) => void; + updateCornerSettings: (settings: CornerSettings) => void; } const AppStateContext = createContext( @@ -38,6 +45,7 @@ export function AppStateProvider({ children }: { children: ReactNode }) { timezone: "UTC", oddsSettings: { enabled: false, selectedBookmakers: [] }, cardsSettings: { enabled: false }, + cornerSettings: { enabled: false }, }); useEffect(() => { @@ -48,6 +56,9 @@ export function AppStateProvider({ children }: { children: ReactNode }) { storage.getCardsSettings().then((settings) => { setState((prev) => ({ ...prev, cardsSettings: settings })); }); + storage.getCornerSettings().then((settings) => { + setState((prev) => ({ ...prev, cornerSettings: settings })); + }); }, []); const updateSportId = (sportId: number | null) => { @@ -76,6 +87,11 @@ export function AppStateProvider({ children }: { children: ReactNode }) { storage.setCardsSettings(settings); }; + const updateCornerSettings = (settings: CornerSettings) => { + setState((prev) => ({ ...prev, cornerSettings: settings })); + storage.setCornerSettings(settings); + }; + return ( {children} diff --git a/i18n/locales/en.json b/i18n/locales/en.json index 8f6d80e..ae9a09d 100644 --- a/i18n/locales/en.json +++ b/i18n/locales/en.json @@ -36,6 +36,10 @@ "cards_show": "Show Cards", "cards_enabled": "On", "cards_disabled": "Off", + "corner_title": "Corner Settings", + "corner_show": "Show Corners", + "corner_enabled": "On", + "corner_disabled": "Off", "login": "Login", "click_to_login": "Click to login", "logout": "Logout", diff --git a/i18n/locales/zh.json b/i18n/locales/zh.json index 87b72ff..3539495 100644 --- a/i18n/locales/zh.json +++ b/i18n/locales/zh.json @@ -36,6 +36,10 @@ "cards_show": "显示红黄牌", "cards_enabled": "开启", "cards_disabled": "关闭", + "corner_title": "角球设置", + "corner_show": "显示角球", + "corner_enabled": "开启", + "corner_disabled": "关闭", "login": "登录", "click_to_login": "点击登录", "logout": "登出", diff --git a/lib/storage.ts b/lib/storage.ts index 5dda9f2..283ad71 100644 --- a/lib/storage.ts +++ b/lib/storage.ts @@ -7,6 +7,7 @@ const STORAGE_KEYS = { USER: "user", ODDS_SETTINGS: "odds_settings", CARDS_SETTINGS: "cards_settings", + CORNER_SETTINGS: "corner_settings", }; export interface OddsSettings { @@ -18,6 +19,10 @@ export interface CardsSettings { enabled: boolean; } +export interface CornerSettings { + enabled: boolean; +} + export const storage = { async setAccessToken(token: string): Promise { await AsyncStorage.setItem(STORAGE_KEYS.ACCESS_TOKEN, token); @@ -83,6 +88,25 @@ export const storage = { } }, + async setCornerSettings(settings: CornerSettings): Promise { + await AsyncStorage.setItem( + STORAGE_KEYS.CORNER_SETTINGS, + JSON.stringify(settings), + ); + }, + + async getCornerSettings(): Promise { + const settingsStr = await AsyncStorage.getItem( + STORAGE_KEYS.CORNER_SETTINGS, + ); + if (!settingsStr) return { enabled: false }; + try { + return JSON.parse(settingsStr) as CornerSettings; + } catch { + return { enabled: false }; + } + }, + async clear(): Promise { await AsyncStorage.multiRemove([ STORAGE_KEYS.ACCESS_TOKEN,