From 006db2af07317a2e5d34e1306ff3480c34d4a1ac Mon Sep 17 00:00:00 2001 From: jinyaqiu Date: Thu, 17 Jul 2025 14:05:07 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E7=99=BB=E5=BD=95=E4=BA=A4=E4=BA=92?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/(tabs)/index.tsx | 56 +++++++++++++++++++++++++------ app/(tabs)/user-message.tsx | 11 ++++-- assets/icons/svg/chatIn.svg | 6 ++-- assets/icons/svg/chatNotIn.svg | 3 ++ assets/icons/svg/personIn.svg | 4 ++- assets/icons/svg/personNotIn.svg | 3 ++ assets/images/png/owner/ask.png | Bin 0 -> 2735 bytes components/ask/aiChat.tsx | 7 ++-- components/layout/ask.tsx | 19 ++++++----- components/login/login.tsx | 8 +++-- components/owner/userInfo.tsx | 8 ++++- i18n/locales/en/ask.json | 4 ++- i18n/locales/zh/ask.json | 4 ++- 13 files changed, 98 insertions(+), 35 deletions(-) create mode 100644 assets/icons/svg/chatNotIn.svg create mode 100644 assets/icons/svg/personNotIn.svg create mode 100644 assets/images/png/owner/ask.png diff --git a/app/(tabs)/index.tsx b/app/(tabs)/index.tsx index 1adcf62..a8f83c8 100644 --- a/app/(tabs)/index.tsx +++ b/app/(tabs)/index.tsx @@ -3,7 +3,7 @@ import { registerBackgroundUploadTask, triggerManualUpload } from '@/components/ import * as MediaLibrary from 'expo-media-library'; import { useRouter } from 'expo-router'; import * as SecureStore from 'expo-secure-store'; -import { useEffect, useState } from 'react'; +import { useEffect, useRef, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { Platform, Text, TouchableOpacity, View } from 'react-native'; import { useSafeAreaInsets } from "react-native-safe-area-context"; @@ -15,20 +15,26 @@ export default function HomeScreen() { const insets = useSafeAreaInsets(); const [isLoading, setIsLoading] = useState(true); const [isLoggedIn, setIsLoggedIn] = useState(false); + const [token, setToken] = useState(''); + const tokenInterval = useRef(null); + const isMounted = useRef(true); + + const getAuthToken = async (): Promise => { + let tokenValue = ''; + if (Platform.OS === 'web') { + tokenValue = localStorage.getItem('token') || ''; + } else { + tokenValue = (await SecureStore.getItemAsync('token')) || ''; + } + setToken(tokenValue); // 只在获取到新token时更新状态 + return tokenValue; + }; useEffect(() => { const checkAuthStatus = async () => { try { - let token; - if (Platform.OS === 'web') { - token = localStorage.getItem('token') || ''; - } else { - token = await SecureStore.getItemAsync('token') || ''; - } - const loggedIn = !!token; setIsLoggedIn(loggedIn); - console.log(loggedIn); if (loggedIn) { // 已登录,请求必要的权限 @@ -49,10 +55,38 @@ export default function HomeScreen() { setIsLoading(false); } }; - checkAuthStatus(); }, []); + // 轮询获取token + useEffect(() => { + // 如果已经有token,直接返回 + if (token) { + if (tokenInterval.current) { + clearInterval(tokenInterval.current); + } + return; + } + if (!tokenInterval.current) return; + // 设置轮询 + tokenInterval.current = setInterval(async () => { + if (isMounted.current) { + const currentToken = await getAuthToken(); + // 如果获取到token,清除定时器 + if (currentToken && tokenInterval.current) { + clearInterval(tokenInterval.current); + } + } + }, 5000); + + // 返回清理函数 + return () => { + if (tokenInterval.current) { + clearInterval(tokenInterval.current); + } + }; + }, [token]); // 添加token作为依赖 + if (isLoading) { return ( @@ -91,7 +125,7 @@ export default function HomeScreen() { {"\n"} {t('auth.welcomeAwaken.back', { ns: 'login' })} - {/* */} + {/* 唤醒按钮 */} ("userName") const [username, setUsername] = useState('') const [avatar, setAvatar] = useState('') @@ -18,6 +19,10 @@ export default function UserMessage() { const [userInfo, setUserInfo] = useState(null); const statusBarHeight = StatusBar?.currentHeight ?? 0; + // 获取路由参数 + const params = useLocalSearchParams(); + const { username: usernameParam } = params; + // 获取用户信息 const getUserInfo = async () => { const res = await fetchApi("/iam/user-info"); @@ -44,7 +49,7 @@ export default function UserMessage() { useEffect(() => { getUserInfo(); setSteps("userName") - }, []); + }, [usernameParam]); return ( - - + + + diff --git a/assets/icons/svg/chatNotIn.svg b/assets/icons/svg/chatNotIn.svg new file mode 100644 index 0000000..9a1bd84 --- /dev/null +++ b/assets/icons/svg/chatNotIn.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/icons/svg/personIn.svg b/assets/icons/svg/personIn.svg index 5b0516a..c0cf339 100644 --- a/assets/icons/svg/personIn.svg +++ b/assets/icons/svg/personIn.svg @@ -1 +1,3 @@ - \ No newline at end of file + + + diff --git a/assets/icons/svg/personNotIn.svg b/assets/icons/svg/personNotIn.svg new file mode 100644 index 0000000..883c7f4 --- /dev/null +++ b/assets/icons/svg/personNotIn.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/png/owner/ask.png b/assets/images/png/owner/ask.png new file mode 100644 index 0000000000000000000000000000000000000000..8c5f798897961c11059a28108c9668aa1c3ab559 GIT binary patch literal 2735 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 E1*r0UCjbBd literal 0 HcmV?d00001 diff --git a/components/ask/aiChat.tsx b/components/ask/aiChat.tsx index 7080d00..8aeeee1 100644 --- a/components/ask/aiChat.tsx +++ b/components/ask/aiChat.tsx @@ -7,6 +7,7 @@ import { Message, Video } from "@/types/ask"; import { MaterialItem } from "@/types/personal-info"; import { useVideoPlayer, VideoView } from 'expo-video'; import React from 'react'; +import { useTranslation } from "react-i18next"; import { FlatList, Image, @@ -40,7 +41,7 @@ const renderMessage = ({ insets, item, sessionId, setModalVisible, modalVisible, const isVideo = (data: Video | MaterialItem): data is Video => { return 'video' in data; }; - + const { t } = useTranslation(); // 创建一个新的 VideoPlayer 组件 const VideoPlayer = ({ videoUrl, @@ -222,7 +223,7 @@ const renderMessage = ({ insets, item, sessionId, setModalVisible, modalVisible, setModalDetailsVisible(false)}> - Select Photo + {t('ask.selectPhoto', { ns: 'ask' })} @@ -292,7 +293,7 @@ const renderMessage = ({ insets, item, sessionId, setModalVisible, modalVisible, activeOpacity={0.8} > - Continue Asking + {t('ask.continueAsking', { ns: 'ask' })} diff --git a/components/layout/ask.tsx b/components/layout/ask.tsx index dcf964a..3a8445b 100644 --- a/components/layout/ask.tsx +++ b/components/layout/ask.tsx @@ -1,10 +1,10 @@ import ChatInSvg from "@/assets/icons/svg/chatIn.svg"; -import NavbarSvg from "@/assets/icons/svg/navbar.svg"; +import ChatNotInSvg from "@/assets/icons/svg/chatNotIn.svg"; import PersonInSvg from "@/assets/icons/svg/personIn.svg"; -import { Ionicons } from "@expo/vector-icons"; +import PersonNotInSvg from "@/assets/icons/svg/personNotIn.svg"; import { router, usePathname } from "expo-router"; import React from 'react'; -import { Dimensions, Platform, TouchableOpacity, View } from 'react-native'; +import { Dimensions, Image, Platform, TouchableOpacity, View } from 'react-native'; import { Circle, Ellipse, G, Mask, Path, Rect, Svg } from 'react-native-svg'; const AskNavbar = () => { @@ -21,10 +21,11 @@ const AskNavbar = () => { shadowRadius: 8, elevation: 10, // For Android }}> - + {/* */} + - router.push('/memo-list')} > - {pathname === "/memo-list" ? : } + router.push('/memo-list')} style={{ padding: 16 }}> + {pathname === "/memo-list" ? : } { params: { newSession: "true" } }); }} - className={`${Platform.OS === 'web' ? '-mt-[4rem]' : width <= 375 ? '-mt-[5rem] ml-[2rem]' : '-mt-[5rem] ml-[0.8rem]'}`} + className={`${Platform.OS === 'web' ? '-mt-[4rem]' : width <= 375 ? '-mt-[5rem]' : '-mt-[5rem]'}`} > { - router.push('/owner')}> + router.push('/owner')} style={{ padding: 16 }}> - {pathname === "/owner" ? : } + {pathname === "/owner" ? : } {/* */} diff --git a/components/login/login.tsx b/components/login/login.tsx index 0bb9162..0ea2f08 100644 --- a/components/login/login.tsx +++ b/components/login/login.tsx @@ -45,9 +45,13 @@ const Login = ({ updateUrlParam, setError, setShowPassword, showPassword }: Logi body: JSON.stringify(body), }); login({ ...res, email: res?.account }, res.access_token || ''); - router.replace('/user-message'); + const userInfo = await fetchApi("/iam/user-info"); + if (userInfo?.nickname) { + router.replace('/ask'); + } else { + router.replace('/user-message'); + } } catch (error) { - // console.error('Login failed', error); } finally { setIsLoading(false); } diff --git a/components/owner/userInfo.tsx b/components/owner/userInfo.tsx index 5e769a9..7356e9e 100644 --- a/components/owner/userInfo.tsx +++ b/components/owner/userInfo.tsx @@ -125,7 +125,13 @@ const UserInfo = (props: UserInfoProps) => { } { setModalVisible(false); - router.push('/user-message') + // 携带参数跳转 + router.push({ + pathname: '/user-message', + params: { + username: "true" + } + }); }}> diff --git a/i18n/locales/en/ask.json b/i18n/locales/en/ask.json index 94e5c93..3031390 100644 --- a/i18n/locales/en/ask.json +++ b/i18n/locales/en/ask.json @@ -3,6 +3,8 @@ "hi": "Hi,", "iAmMemo": "I'm Memo!", "ready": "Ready to wake up your memories?", - "justAsk": "Just ask MeMo, let me bring them back to life!" + "justAsk": "Just ask MeMo, let me bring them back to life!", + "selectPhoto": "Select Photo", + "continueAsking": "Continue Asking" } } \ No newline at end of file diff --git a/i18n/locales/zh/ask.json b/i18n/locales/zh/ask.json index 94e5c93..3031390 100644 --- a/i18n/locales/zh/ask.json +++ b/i18n/locales/zh/ask.json @@ -3,6 +3,8 @@ "hi": "Hi,", "iAmMemo": "I'm Memo!", "ready": "Ready to wake up your memories?", - "justAsk": "Just ask MeMo, let me bring them back to life!" + "justAsk": "Just ask MeMo, let me bring them back to life!", + "selectPhoto": "Select Photo", + "continueAsking": "Continue Asking" } } \ No newline at end of file