添加角球设置功能,更新状态管理和界面显示逻辑
This commit is contained in:
@@ -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() {
|
||||
</View>
|
||||
</View>
|
||||
|
||||
<ThemedText style={styles.sectionTitle}>
|
||||
{t("settings.corner_title")}
|
||||
</ThemedText>
|
||||
|
||||
<View
|
||||
style={[
|
||||
styles.section,
|
||||
{ backgroundColor: isDark ? "#1c1c1e" : "#fff" },
|
||||
]}
|
||||
>
|
||||
<View style={styles.settingItem}>
|
||||
<View style={styles.settingLabel}>
|
||||
<IconSymbol
|
||||
name="flag"
|
||||
size={20}
|
||||
color={iconColor}
|
||||
style={{ marginRight: 10 }}
|
||||
/>
|
||||
<ThemedText>{t("settings.corner_show")}</ThemedText>
|
||||
</View>
|
||||
<View style={styles.settingControl}>
|
||||
<TouchableOpacity onPress={toggleCorners} style={styles.button}>
|
||||
<ThemedText>
|
||||
{state.cornerSettings.enabled
|
||||
? t("settings.corner_enabled")
|
||||
: t("settings.corner_disabled")}
|
||||
</ThemedText>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
{/* <ThemedText style={styles.sectionTitle}>登录</ThemedText>
|
||||
|
||||
<View
|
||||
|
||||
@@ -38,6 +38,7 @@ export function MatchCard({
|
||||
|
||||
const oddsSettings = state.oddsSettings;
|
||||
const cardsSettings = state.cardsSettings;
|
||||
const cornerSettings = state.cornerSettings;
|
||||
|
||||
useEffect(() => {
|
||||
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({
|
||||
<View style={styles.scoreBoxPlaceholder} />
|
||||
)}
|
||||
|
||||
{(extraStats.home !== "" || extraStats.away !== "") && (
|
||||
<View style={styles.extraStatsColumn}>
|
||||
<ThemedText style={styles.extraStatText}>
|
||||
{extraStats.home}
|
||||
</ThemedText>
|
||||
<ThemedText style={styles.extraStatText}>
|
||||
{extraStats.away}
|
||||
</ThemedText>
|
||||
</View>
|
||||
)}
|
||||
|
||||
<TouchableOpacity
|
||||
onPress={(e) => {
|
||||
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",
|
||||
|
||||
@@ -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<AppStateContextType | undefined>(
|
||||
@@ -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 (
|
||||
<AppStateContext.Provider
|
||||
value={{
|
||||
@@ -86,6 +102,7 @@ export function AppStateProvider({ children }: { children: ReactNode }) {
|
||||
updateTimezone,
|
||||
updateOddsSettings,
|
||||
updateCardsSettings,
|
||||
updateCornerSettings,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -36,6 +36,10 @@
|
||||
"cards_show": "显示红黄牌",
|
||||
"cards_enabled": "开启",
|
||||
"cards_disabled": "关闭",
|
||||
"corner_title": "角球设置",
|
||||
"corner_show": "显示角球",
|
||||
"corner_enabled": "开启",
|
||||
"corner_disabled": "关闭",
|
||||
"login": "登录",
|
||||
"click_to_login": "点击登录",
|
||||
"logout": "登出",
|
||||
|
||||
@@ -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<void> {
|
||||
await AsyncStorage.setItem(STORAGE_KEYS.ACCESS_TOKEN, token);
|
||||
@@ -83,6 +88,25 @@ export const storage = {
|
||||
}
|
||||
},
|
||||
|
||||
async setCornerSettings(settings: CornerSettings): Promise<void> {
|
||||
await AsyncStorage.setItem(
|
||||
STORAGE_KEYS.CORNER_SETTINGS,
|
||||
JSON.stringify(settings),
|
||||
);
|
||||
},
|
||||
|
||||
async getCornerSettings(): Promise<CornerSettings> {
|
||||
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<void> {
|
||||
await AsyncStorage.multiRemove([
|
||||
STORAGE_KEYS.ACCESS_TOKEN,
|
||||
|
||||
Reference in New Issue
Block a user