添加角球设置功能,更新状态管理和界面显示逻辑
This commit is contained in:
@@ -37,7 +37,12 @@ const BOOKMAKERS = [
|
|||||||
export default function ProfileScreen() {
|
export default function ProfileScreen() {
|
||||||
const { theme, toggleTheme, setTheme, isSystemTheme, useSystemTheme } =
|
const { theme, toggleTheme, setTheme, isSystemTheme, useSystemTheme } =
|
||||||
useTheme();
|
useTheme();
|
||||||
const { state, updateOddsSettings, updateCardsSettings } = useAppState();
|
const {
|
||||||
|
state,
|
||||||
|
updateOddsSettings,
|
||||||
|
updateCardsSettings,
|
||||||
|
updateCornerSettings,
|
||||||
|
} = useAppState();
|
||||||
const { t, i18n } = useTranslation();
|
const { t, i18n } = useTranslation();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const isDark = theme === "dark";
|
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 selectBookmaker = (name: string) => {
|
||||||
const current = state.oddsSettings.selectedBookmakers;
|
const current = state.oddsSettings.selectedBookmakers;
|
||||||
let next: string[];
|
let next: string[];
|
||||||
@@ -468,6 +480,38 @@ export default function ProfileScreen() {
|
|||||||
</View>
|
</View>
|
||||||
</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>
|
{/* <ThemedText style={styles.sectionTitle}>登录</ThemedText>
|
||||||
|
|
||||||
<View
|
<View
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ export function MatchCard({
|
|||||||
|
|
||||||
const oddsSettings = state.oddsSettings;
|
const oddsSettings = state.oddsSettings;
|
||||||
const cardsSettings = state.cardsSettings;
|
const cardsSettings = state.cardsSettings;
|
||||||
|
const cornerSettings = state.cornerSettings;
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (
|
if (
|
||||||
@@ -59,9 +60,13 @@ export function MatchCard({
|
|||||||
match.odds,
|
match.odds,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// Fetch live score detail for cards info
|
// Fetch live score detail for cards and corners info
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (cardsSettings.enabled && isLive && match.leagueKey) {
|
if (
|
||||||
|
(cardsSettings.enabled || cornerSettings.enabled) &&
|
||||||
|
isLive &&
|
||||||
|
match.leagueKey
|
||||||
|
) {
|
||||||
fetchLiveScore(match.sportId || 1, Number(match.leagueKey))
|
fetchLiveScore(match.sportId || 1, Number(match.leagueKey))
|
||||||
.then((matches) => {
|
.then((matches) => {
|
||||||
const detail = matches.find((m) => String(m.event_key) === match.id);
|
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));
|
.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 改变时,更新内部状态
|
// 当外部传入的 match.fav 改变时,更新内部状态
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -158,6 +169,26 @@ export function MatchCard({
|
|||||||
return { homeYellow, homeRed, awayYellow, awayRed };
|
return { homeYellow, homeRed, awayYellow, awayRed };
|
||||||
}, [liveDetail, cardsSettings.enabled]);
|
}, [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 = () => {
|
const handlePress = () => {
|
||||||
if (onPress) {
|
if (onPress) {
|
||||||
onPress(match);
|
onPress(match);
|
||||||
@@ -384,6 +415,17 @@ export function MatchCard({
|
|||||||
<View style={styles.scoreBoxPlaceholder} />
|
<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
|
<TouchableOpacity
|
||||||
onPress={(e) => {
|
onPress={(e) => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
@@ -539,6 +581,17 @@ const styles = StyleSheet.create({
|
|||||||
cardBadgeRed: {
|
cardBadgeRed: {
|
||||||
backgroundColor: "#FF3B30",
|
backgroundColor: "#FF3B30",
|
||||||
},
|
},
|
||||||
|
extraStatsColumn: {
|
||||||
|
alignItems: "center",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
height: 48,
|
||||||
|
paddingVertical: 2,
|
||||||
|
},
|
||||||
|
extraStatText: {
|
||||||
|
fontSize: 12,
|
||||||
|
fontWeight: "500",
|
||||||
|
opacity: 0.6,
|
||||||
|
},
|
||||||
cardBadgeText: {
|
cardBadgeText: {
|
||||||
fontSize: 10,
|
fontSize: 10,
|
||||||
fontWeight: "900",
|
fontWeight: "900",
|
||||||
|
|||||||
@@ -1,4 +1,9 @@
|
|||||||
import { CardsSettings, OddsSettings, storage } from "@/lib/storage";
|
import {
|
||||||
|
CardsSettings,
|
||||||
|
CornerSettings,
|
||||||
|
OddsSettings,
|
||||||
|
storage,
|
||||||
|
} from "@/lib/storage";
|
||||||
import React, {
|
import React, {
|
||||||
createContext,
|
createContext,
|
||||||
ReactNode,
|
ReactNode,
|
||||||
@@ -14,6 +19,7 @@ interface AppState {
|
|||||||
timezone: string;
|
timezone: string;
|
||||||
oddsSettings: OddsSettings;
|
oddsSettings: OddsSettings;
|
||||||
cardsSettings: CardsSettings;
|
cardsSettings: CardsSettings;
|
||||||
|
cornerSettings: CornerSettings;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface AppStateContextType {
|
interface AppStateContextType {
|
||||||
@@ -24,6 +30,7 @@ interface AppStateContextType {
|
|||||||
updateTimezone: (timezone: string) => void;
|
updateTimezone: (timezone: string) => void;
|
||||||
updateOddsSettings: (settings: OddsSettings) => void;
|
updateOddsSettings: (settings: OddsSettings) => void;
|
||||||
updateCardsSettings: (settings: CardsSettings) => void;
|
updateCardsSettings: (settings: CardsSettings) => void;
|
||||||
|
updateCornerSettings: (settings: CornerSettings) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const AppStateContext = createContext<AppStateContextType | undefined>(
|
const AppStateContext = createContext<AppStateContextType | undefined>(
|
||||||
@@ -38,6 +45,7 @@ export function AppStateProvider({ children }: { children: ReactNode }) {
|
|||||||
timezone: "UTC",
|
timezone: "UTC",
|
||||||
oddsSettings: { enabled: false, selectedBookmakers: [] },
|
oddsSettings: { enabled: false, selectedBookmakers: [] },
|
||||||
cardsSettings: { enabled: false },
|
cardsSettings: { enabled: false },
|
||||||
|
cornerSettings: { enabled: false },
|
||||||
});
|
});
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -48,6 +56,9 @@ export function AppStateProvider({ children }: { children: ReactNode }) {
|
|||||||
storage.getCardsSettings().then((settings) => {
|
storage.getCardsSettings().then((settings) => {
|
||||||
setState((prev) => ({ ...prev, cardsSettings: settings }));
|
setState((prev) => ({ ...prev, cardsSettings: settings }));
|
||||||
});
|
});
|
||||||
|
storage.getCornerSettings().then((settings) => {
|
||||||
|
setState((prev) => ({ ...prev, cornerSettings: settings }));
|
||||||
|
});
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const updateSportId = (sportId: number | null) => {
|
const updateSportId = (sportId: number | null) => {
|
||||||
@@ -76,6 +87,11 @@ export function AppStateProvider({ children }: { children: ReactNode }) {
|
|||||||
storage.setCardsSettings(settings);
|
storage.setCardsSettings(settings);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const updateCornerSettings = (settings: CornerSettings) => {
|
||||||
|
setState((prev) => ({ ...prev, cornerSettings: settings }));
|
||||||
|
storage.setCornerSettings(settings);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<AppStateContext.Provider
|
<AppStateContext.Provider
|
||||||
value={{
|
value={{
|
||||||
@@ -86,6 +102,7 @@ export function AppStateProvider({ children }: { children: ReactNode }) {
|
|||||||
updateTimezone,
|
updateTimezone,
|
||||||
updateOddsSettings,
|
updateOddsSettings,
|
||||||
updateCardsSettings,
|
updateCardsSettings,
|
||||||
|
updateCornerSettings,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
|
|||||||
@@ -36,6 +36,10 @@
|
|||||||
"cards_show": "Show Cards",
|
"cards_show": "Show Cards",
|
||||||
"cards_enabled": "On",
|
"cards_enabled": "On",
|
||||||
"cards_disabled": "Off",
|
"cards_disabled": "Off",
|
||||||
|
"corner_title": "Corner Settings",
|
||||||
|
"corner_show": "Show Corners",
|
||||||
|
"corner_enabled": "On",
|
||||||
|
"corner_disabled": "Off",
|
||||||
"login": "Login",
|
"login": "Login",
|
||||||
"click_to_login": "Click to login",
|
"click_to_login": "Click to login",
|
||||||
"logout": "Logout",
|
"logout": "Logout",
|
||||||
|
|||||||
@@ -36,6 +36,10 @@
|
|||||||
"cards_show": "显示红黄牌",
|
"cards_show": "显示红黄牌",
|
||||||
"cards_enabled": "开启",
|
"cards_enabled": "开启",
|
||||||
"cards_disabled": "关闭",
|
"cards_disabled": "关闭",
|
||||||
|
"corner_title": "角球设置",
|
||||||
|
"corner_show": "显示角球",
|
||||||
|
"corner_enabled": "开启",
|
||||||
|
"corner_disabled": "关闭",
|
||||||
"login": "登录",
|
"login": "登录",
|
||||||
"click_to_login": "点击登录",
|
"click_to_login": "点击登录",
|
||||||
"logout": "登出",
|
"logout": "登出",
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ const STORAGE_KEYS = {
|
|||||||
USER: "user",
|
USER: "user",
|
||||||
ODDS_SETTINGS: "odds_settings",
|
ODDS_SETTINGS: "odds_settings",
|
||||||
CARDS_SETTINGS: "cards_settings",
|
CARDS_SETTINGS: "cards_settings",
|
||||||
|
CORNER_SETTINGS: "corner_settings",
|
||||||
};
|
};
|
||||||
|
|
||||||
export interface OddsSettings {
|
export interface OddsSettings {
|
||||||
@@ -18,6 +19,10 @@ export interface CardsSettings {
|
|||||||
enabled: boolean;
|
enabled: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface CornerSettings {
|
||||||
|
enabled: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
export const storage = {
|
export const storage = {
|
||||||
async setAccessToken(token: string): Promise<void> {
|
async setAccessToken(token: string): Promise<void> {
|
||||||
await AsyncStorage.setItem(STORAGE_KEYS.ACCESS_TOKEN, token);
|
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> {
|
async clear(): Promise<void> {
|
||||||
await AsyncStorage.multiRemove([
|
await AsyncStorage.multiRemove([
|
||||||
STORAGE_KEYS.ACCESS_TOKEN,
|
STORAGE_KEYS.ACCESS_TOKEN,
|
||||||
|
|||||||
Reference in New Issue
Block a user