From 89857818653a4720df6601da6eea3403e38156b5 Mon Sep 17 00:00:00 2001 From: zimplexing Date: Tue, 15 Jul 2025 15:49:46 +0800 Subject: [PATCH] refactor: enhance LoginModal and StyledButton components for improved functionality --- .gitignore | 2 +- components/LoginModal.tsx | 21 +++- components/StyledButton.tsx | 235 ++++++++++++++++++------------------ services/api.ts | 5 +- services/storage.ts | 4 +- 5 files changed, 140 insertions(+), 127 deletions(-) diff --git a/.gitignore b/.gitignore index b628640..704dd47 100644 --- a/.gitignore +++ b/.gitignore @@ -23,5 +23,5 @@ expo-env.d.ts web/** .bmad-core .kilocodemodes -.roomode +.roomodes yarn-errors.log \ No newline at end of file diff --git a/components/LoginModal.tsx b/components/LoginModal.tsx index 3374036..c7a182d 100644 --- a/components/LoginModal.tsx +++ b/components/LoginModal.tsx @@ -1,5 +1,5 @@ -import React, { useState } from "react"; -import { Modal, View, Text, TextInput, StyleSheet, ActivityIndicator } from "react-native"; +import React, { useState, useRef } from "react"; +import { Modal, View, TextInput, StyleSheet, ActivityIndicator } from "react-native"; import Toast from "react-native-toast-message"; import useAuthStore from "@/stores/authStore"; import { useSettingsStore } from "@/stores/settingsStore"; @@ -16,6 +16,8 @@ const LoginModal = () => { const [username, setUsername] = useState(""); const [password, setPassword] = useState(""); const [isLoading, setIsLoading] = useState(false); + const passwordInputRef = useRef(null); + const loginButtonRef = useRef(null); const handleLogin = async () => { const isLocalStorage = serverConfig?.StorageType === "localstorage"; @@ -32,7 +34,7 @@ const LoginModal = () => { hideLoginModal(); setUsername(""); setPassword(""); - } catch (error) { + } catch { Toast.show({ type: "error", text1: "登录失败", text2: "用户名或密码错误" }); } finally { setIsLoading(false); @@ -53,17 +55,28 @@ const LoginModal = () => { value={username} onChangeText={setUsername} autoFocus + returnKeyType="next" + onSubmitEditing={() => passwordInputRef.current?.focus()} /> )} loginButtonRef.current?.focus()} /> - + {isLoading && } diff --git a/components/StyledButton.tsx b/components/StyledButton.tsx index 61b0abd..19af513 100644 --- a/components/StyledButton.tsx +++ b/components/StyledButton.tsx @@ -1,5 +1,5 @@ -import React from "react"; -import { Animated, Pressable, StyleSheet, StyleProp, ViewStyle, PressableProps, TextStyle } from "react-native"; +import React, { forwardRef } from "react"; +import { Animated, Pressable, StyleSheet, StyleProp, ViewStyle, PressableProps, TextStyle, View } from "react-native"; import { ThemedText } from "./ThemedText"; import { Colors } from "@/constants/Colors"; import { useButtonAnimation } from "@/hooks/useAnimation"; @@ -13,133 +13,130 @@ interface StyledButtonProps extends PressableProps { textStyle?: StyleProp; } -export const StyledButton: React.FC = ({ - children, - text, - variant = "default", - isSelected = false, - style, - textStyle, - ...rest -}) => { - const colorScheme = "dark"; - const colors = Colors[colorScheme]; - const [isFocused, setIsFocused] = React.useState(false); - const animationStyle = useButtonAnimation(isFocused); +export const StyledButton = forwardRef( + ({ children, text, variant = "default", isSelected = false, style, textStyle, ...rest }, ref) => { + const colorScheme = "dark"; + const colors = Colors[colorScheme]; + const [isFocused, setIsFocused] = React.useState(false); + const animationStyle = useButtonAnimation(isFocused); - const variantStyles = { - default: StyleSheet.create({ + const variantStyles = { + default: StyleSheet.create({ + button: { + backgroundColor: colors.border, + }, + text: { + color: colors.text, + }, + selectedButton: { + backgroundColor: colors.tint, + }, + focusedButton: { + backgroundColor: colors.link, + borderColor: colors.background, + }, + selectedText: { + color: Colors.dark.text, + }, + }), + primary: StyleSheet.create({ + button: { + backgroundColor: "transparent", + }, + text: { + color: colors.text, + }, + focusedButton: { + backgroundColor: colors.link, + borderColor: colors.background, + }, + selectedButton: { + backgroundColor: "rgba(0, 122, 255, 0.3)", + }, + selectedText: { + color: colors.link, + }, + }), + ghost: StyleSheet.create({ + button: { + backgroundColor: "transparent", + }, + text: { + color: colors.text, + }, + focusedButton: { + backgroundColor: "rgba(119, 119, 119, 0.9)", + }, + selectedButton: {}, + selectedText: {}, + }), + }; + + const styles = StyleSheet.create({ button: { - backgroundColor: colors.border, + paddingHorizontal: 16, + paddingVertical: 10, + borderRadius: 8, + borderWidth: 2, + borderColor: "transparent", + flexDirection: "row", + alignItems: "center", + justifyContent: "center", }, - text: { - color: colors.text, + focusedButton: { + backgroundColor: colors.link, + borderColor: colors.background, + elevation: 5, + shadowColor: colors.link, + shadowOffset: { width: 0, height: 0 }, + shadowOpacity: 1, + shadowRadius: 15, }, selectedButton: { backgroundColor: colors.tint, }, - focusedButton: { - backgroundColor: colors.link, - borderColor: colors.background, + text: { + fontSize: 16, + fontWeight: "500", + color: colors.text, }, selectedText: { color: Colors.dark.text, }, - }), - primary: StyleSheet.create({ - button: { - backgroundColor: "transparent", - }, - text: { - color: colors.text, - }, - focusedButton: { - backgroundColor: colors.link, - borderColor: colors.background, - }, - selectedButton: { - backgroundColor: "rgba(0, 122, 255, 0.3)", - }, - selectedText: { - color: colors.link, - }, - }), - ghost: StyleSheet.create({ - button: { - backgroundColor: "transparent", - }, - text: { - color: colors.text, - }, - focusedButton: { - backgroundColor: "rgba(119, 119, 119, 0.9)", - }, - selectedButton: {}, - selectedText: {}, - }), - }; + }); - const styles = StyleSheet.create({ - button: { - paddingHorizontal: 16, - paddingVertical: 10, - borderRadius: 8, - borderWidth: 2, - borderColor: "transparent", - flexDirection: "row", - alignItems: "center", - justifyContent: "center", - }, - focusedButton: { - backgroundColor: colors.link, - borderColor: colors.background, - elevation: 5, - shadowColor: colors.link, - shadowOffset: { width: 0, height: 0 }, - shadowOpacity: 1, - shadowRadius: 15, - }, - selectedButton: { - backgroundColor: colors.tint, - }, - text: { - fontSize: 16, - fontWeight: "500", - color: colors.text, - }, - selectedText: { - color: Colors.dark.text, - }, - }); + return ( + + setIsFocused(true)} + onBlur={() => setIsFocused(false)} + style={({ focused }) => [ + styles.button, + variantStyles[variant].button, + isSelected && (variantStyles[variant].selectedButton ?? styles.selectedButton), + focused && (variantStyles[variant].focusedButton ?? styles.focusedButton), + ]} + {...rest} + > + {text ? ( + + {text} + + ) : ( + children + )} + + + ); + } +); - return ( - - setIsFocused(true)} - onBlur={() => setIsFocused(false)} - style={({ focused }) => [ - styles.button, - variantStyles[variant].button, - isSelected && (variantStyles[variant].selectedButton ?? styles.selectedButton), - focused && (variantStyles[variant].focusedButton ?? styles.focusedButton), - ]} - {...rest} - > - {text ? ( - - {text} - - ) : ( - children - )} - - - ); -}; +StyledButton.displayName = "StyledButton"; diff --git a/services/api.ts b/services/api.ts index 561ab8a..8ca7db3 100644 --- a/services/api.ts +++ b/services/api.ts @@ -42,10 +42,13 @@ export interface SearchResult { } export interface Favorite { + cover: string; title: string; poster: string; source_name: string; - save_time: number; + total_episodes: number; + search_title: string; + year: string; } export interface PlayRecord { diff --git a/services/storage.ts b/services/storage.ts index ff70db6..4d64a55 100644 --- a/services/storage.ts +++ b/services/storage.ts @@ -82,7 +82,7 @@ export class FavoriteManager { return (await api.getFavorites()) as Record; } - static async save(source: string, id: string, item: Omit): Promise { + static async save(source: string, id: string, item: Favorite): Promise { const key = generateKey(source, id); await api.addFavorite(key, item); } @@ -98,7 +98,7 @@ export class FavoriteManager { return favorite !== null; } - static async toggle(source: string, id: string, item: Omit): Promise { + static async toggle(source: string, id: string, item: Favorite): Promise { const isFav = await this.isFavorited(source, id); if (isFav) { await this.remove(source, id);