192 lines
5.9 KiB
TypeScript
192 lines
5.9 KiB
TypeScript
import UserSvg from "@/assets/icons/svg/ataver.svg";
|
|
import EditSvg from "@/assets/icons/svg/edit.svg";
|
|
import LocationSvg from "@/assets/icons/svg/location.svg";
|
|
import RefreshSvg from "@/assets/icons/svg/refresh.svg";
|
|
import { Address, User } from "@/types/user";
|
|
import { useRouter } from "expo-router";
|
|
import * as SecureStore from 'expo-secure-store';
|
|
import { useEffect, useRef } from "react";
|
|
import { useTranslation } from "react-i18next";
|
|
import { Animated, Easing, Image, Platform, StyleSheet, TouchableOpacity, View } from "react-native";
|
|
import { ThemedText } from "../ThemedText";
|
|
|
|
interface UserInfoProps {
|
|
userInfo: User;
|
|
getCurrentLocation: () => void;
|
|
isLoading: boolean;
|
|
isRefreshing: boolean;
|
|
currentLocation: Address;
|
|
setCurrentLocation: (location: Address) => void;
|
|
}
|
|
const UserInfo = (props: UserInfoProps) => {
|
|
const { userInfo, getCurrentLocation, isLoading, isRefreshing, currentLocation, setCurrentLocation } = props;
|
|
|
|
const router = useRouter();
|
|
const { t } = useTranslation();
|
|
// 获取本地存储的location
|
|
const getLocation = async () => {
|
|
if (Platform.OS === 'web') {
|
|
const location = localStorage.getItem('location');
|
|
if (location) {
|
|
setCurrentLocation(JSON.parse(location));
|
|
}
|
|
} else {
|
|
const location = await SecureStore.getItemAsync('location');
|
|
if (location) {
|
|
setCurrentLocation(JSON.parse(location));
|
|
}
|
|
}
|
|
};
|
|
// 添加旋转动画值
|
|
const spinValue = useRef(new Animated.Value(0)).current;
|
|
|
|
|
|
// 旋转动画
|
|
const startSpin = () => {
|
|
spinValue.setValue(0);
|
|
Animated.loop(
|
|
Animated.timing(spinValue, {
|
|
toValue: 1,
|
|
duration: 1000,
|
|
easing: Easing.linear,
|
|
useNativeDriver: true,
|
|
})
|
|
).start();
|
|
};
|
|
|
|
// 停止旋转
|
|
const stopSpin = () => {
|
|
spinValue.stopAnimation();
|
|
spinValue.setValue(0);
|
|
};
|
|
// 当开始加载时启动旋转
|
|
useEffect(() => {
|
|
if (isLoading) {
|
|
startSpin();
|
|
} else {
|
|
stopSpin();
|
|
}
|
|
}, [isLoading]);
|
|
|
|
// 在组件挂载时自动获取位置(可选)
|
|
useEffect(() => {
|
|
getLocation();
|
|
if (currentLocation && Object?.keys(currentLocation)?.length === 0) {
|
|
getCurrentLocation();
|
|
}
|
|
}, [])
|
|
|
|
return (
|
|
<View style={styles.container}>
|
|
<View style={styles.info}>
|
|
<ThemedText style={styles.nickname}>{userInfo?.nickname}</ThemedText>
|
|
<ThemedText style={styles.userId}>{t('generalSetting.userId', { ns: 'personal' })}{userInfo?.user_id}</ThemedText>
|
|
<View style={styles.location}>
|
|
<LocationSvg />
|
|
<ThemedText style={styles.userId}>
|
|
{currentLocation?.country}-{currentLocation?.city}-{currentLocation?.district}
|
|
</ThemedText>
|
|
<TouchableOpacity
|
|
onPress={getCurrentLocation}
|
|
disabled={isRefreshing}
|
|
style={styles.refreshContainer}
|
|
>
|
|
<Animated.View
|
|
style={[
|
|
styles.refreshIcon,
|
|
{
|
|
transform: [{
|
|
rotate: spinValue.interpolate({
|
|
inputRange: [0, 1],
|
|
outputRange: ['0deg', '360deg']
|
|
})
|
|
}]
|
|
}
|
|
]}
|
|
>
|
|
<RefreshSvg color="#4C320C" width={16} height={16} />
|
|
</Animated.View>
|
|
</TouchableOpacity>
|
|
</View>
|
|
</View>
|
|
<View style={styles.avatar}>
|
|
{userInfo?.avatar_file_url
|
|
?
|
|
<Image
|
|
className='rounded-full'
|
|
style={{ width: 80, height: 80 }}
|
|
source={{ uri: userInfo?.avatar_file_url }}
|
|
/>
|
|
:
|
|
<UserSvg width={80} height={80} />
|
|
}
|
|
<TouchableOpacity style={styles.edit} onPress={() => {
|
|
// 携带参数跳转
|
|
router.push({
|
|
pathname: '/user-message',
|
|
params: {
|
|
username: "true"
|
|
}
|
|
});
|
|
}}>
|
|
<EditSvg />
|
|
</TouchableOpacity>
|
|
</View>
|
|
</View>
|
|
);
|
|
}
|
|
|
|
const styles = StyleSheet.create({
|
|
container: {
|
|
flexDirection: 'row',
|
|
justifyContent: 'space-between',
|
|
alignItems: 'center',
|
|
backgroundColor: "#FAF9F6",
|
|
padding: 16,
|
|
borderRadius: 24,
|
|
},
|
|
info: {
|
|
flexDirection: 'column',
|
|
gap: 8,
|
|
},
|
|
nickname: {
|
|
fontSize: 20,
|
|
fontWeight: 'bold',
|
|
color: '#4C320C',
|
|
},
|
|
userId: {
|
|
fontSize: 12,
|
|
color: '#4C320C',
|
|
},
|
|
location: {
|
|
flexDirection: 'row',
|
|
alignItems: 'center',
|
|
marginTop: 4,
|
|
gap: 4
|
|
},
|
|
refreshContainer: {
|
|
width: 24,
|
|
height: 24,
|
|
justifyContent: 'center',
|
|
alignItems: 'center',
|
|
marginLeft: 4
|
|
},
|
|
refreshIcon: {
|
|
width: 16,
|
|
height: 16,
|
|
},
|
|
avatar: {
|
|
position: 'relative',
|
|
},
|
|
edit: {
|
|
position: 'absolute',
|
|
padding: 8,
|
|
backgroundColor: '#fff',
|
|
borderRadius: 50,
|
|
right: -5,
|
|
bottom: -5,
|
|
}
|
|
})
|
|
|
|
export default UserInfo;
|