tiefen_space_app/screeens/Setting/SwitchAccount/index.jsx

343 lines
10 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import {
View,
Text,
FlatList,
Image as NativeImage,
ActivityIndicator,
TouchableOpacity,
} from "react-native";
import React, {
useState,
useEffect,
useRef,
useCallback,
useContext,
} from "react";
import { useTailwind } from "tailwind-rn";
import { useSafeAreaInsets } from "react-native-safe-area-context";
import AsyncStorage from "@react-native-async-storage/async-storage";
import { ListItem, Button, Icon } from "@rneui/themed";
import { Image } from "expo-image";
import Empty from "../../../components/Empty";
import { get, remove, save } from "../../../utils/storeInfo";
import { AuthContext } from "../../../App";
import baseRequest from "../../../utils/baseRequest";
import { generateSignature } from "../../../utils/crypto";
import MyModal from "../../../components/MyModal";
import Toast from "react-native-toast-message";
import { handleLogin } from "../../../store/reducer";
import { connect } from "react-redux";
function SwitchAccount({ changeLogin }) {
const blurhash = "LcKUTa%gOYWBYRt6xuoJo~s8V@fk";
const tailwind = useTailwind();
const insets = useSafeAreaInsets();
//退出登录
const { signIn, signOut } = useContext(AuthContext);
const [accountList, setAccountList] = useState([]);
useEffect(() => {
//获取所有可切换账号
async function getAccountList() {
try {
const keys = await AsyncStorage.getAllKeys();
const accountKeys = keys.filter((key) =>
key.startsWith(`account_list_`)
);
const accountListCache = await AsyncStorage.multiGet(accountKeys);
const jsonParsedAccountList = accountListCache.map((item) => ({
key: item[0],
data: JSON.parse(item[1]),
}));
//判断当前账号是否登录并将登录的账号放到第一位
const account = await get("account");
const allAccountList = jsonParsedAccountList
.map((item) => ({
...item,
online: item.data.account.user_id === account.user_id,
}))
.sort((a, b) => {
if (!b.data.login_time && !a.data.login_time) return 0;
if (!a.data.login_time) return 1;
if (!b.data.login_time) return -1;
return b.data.login_time - a.data.login_time;
});
//删除没有设置密码且不在线的账号
const _accountList = allAccountList.filter(
(item) => item.data?.password !== undefined || item.online === true
);
setAccountList(_accountList);
} catch (error) {
console.error(error);
}
}
getAccountList();
}, []);
//接口登录
const signInAccount = async (data) => {
const apiUrl = process.env.EXPO_PUBLIC_API_URL;
const base = await baseRequest();
const signature = await generateSignature({
mobile_phone: data.mobile_phone,
region_code: data.region_code,
password: data.password,
...base,
});
try {
const _response = await fetch(
`${apiUrl}/api/login/login_by_pswd?signature=${signature}`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
mobile_phone: data.mobile_phone,
region_code: data.region_code,
password: data.password,
...base,
}),
}
);
const _data = await _response.json();
if (_data.ret === -1) {
Toast.show({
type: "error",
text1: _data.msg,
topOffset: 60,
});
return;
}
//更新登录时间
await save(`account_list_${data.account.user_id}`, {
...data,
login_time: new Date().getTime(),
});
signIn(_data, data.mobile_phone_origion, data.region_code);
changeLogin({
isSignin: true,
userToken: data.token,
recommendMid: null,
inviter: null,
});
setAccountList((pre) =>
pre.map((item) => ({
...item,
online: item.data.account.user_id === data.account.user_id,
}))
);
} catch (error) {
console.error(error);
}
};
//切换账号
const [isSwitching, setIsSwitching] = useState(false);
const [warnModalVisible, setWarnModalVisible] = useState(false);
const [warnModalData, setWarnModalData] = useState({});
const switchAccount = async (data) => {
const onlineAccount = accountList.filter((item) => item.online === true);
if (onlineAccount[0].data.account.user_id === data.account.user_id) return;
if (!onlineAccount[0].data?.password) {
setWarnModalVisible(true);
setWarnModalData(data);
return;
}
setIsSwitching(true);
await signInAccount(data);
setIsSwitching(false);
};
//从验证码登录的账号进行切换账号
const switchAccountWithPhoneNumLogin = async (data) => {
setIsSwitching(true);
const onlineAccount = accountList.filter((item) => item.online === true);
setAccountList((pre) =>
pre.filter(
(item) =>
item.data.account.user_id !== onlineAccount[0].data.account.user_id
)
);
await signInAccount(data);
setIsSwitching(false);
};
//删除账号
const removeAccount = async (key, online) => {
await remove(key);
if (online) {
signOut();
changeLogin({
isSignin: false,
userToken: null,
recommendMid: null,
inviter: null,
});
return;
}
setAccountList((pre) => pre.filter((item) => item.key !== key));
};
//账号卡片组件
const AccountCard = useCallback(
({ data, listRef }) => {
return (
<ListItem.Swipeable
onPress={() => switchAccount(data.data)}
bottomDivider
onSwipeBegin={() => {
listRef.current.setNativeProps({
scrollEnabled: false,
});
}}
onSwipeEnd={() => {
listRef.current.setNativeProps({
scrollEnabled: true,
});
}}
containerStyle={tailwind("p-0 bg-[#07050A]")}
rightContent={(reset) => (
<Button
title="删除"
onPress={() => {
removeAccount(data.key, data.online);
reset();
}}
icon={{ name: "delete", color: "white" }}
buttonStyle={{ minHeight: "100%", backgroundColor: "red" }}
titleStyle={tailwind("text-base")}
/>
)}
>
<View style={tailwind("flex-1")}>
<View style={tailwind("flex-row py-3")}>
<Image
style={tailwind("w-12 h-12 rounded-full")}
source={data.data.account.avatar.images[0].urls[0]}
placeholder={blurhash}
contentFit="cover"
transition={1000}
cachePolicy="disk"
/>
<View
style={tailwind(
"flex flex-col flex-1 ml-2 justify-around items-start"
)}
>
<Text
style={tailwind("text-base text-white font-medium")}
numberOfLines={1}
ellipsizeMode="tail"
>
{data.data.account.name}
</Text>
<View
style={tailwind(
"flex-row items-center py-0.5 px-2 bg-[#FFFFFF1A] rounded-full"
)}
>
<NativeImage
source={require("../../../assets/icon/12DP/ID.png")}
/>
<Text
style={tailwind("text-white text-xs font-medium ml-0.5")}
>
{data.data.account.user_id}
</Text>
</View>
</View>
{data.online && (
<View style={tailwind("flex justify-center")}>
<Icon
type="ionicon"
name="checkmark"
size={24}
color="#27F5B7"
/>
</View>
)}
</View>
</View>
</ListItem.Swipeable>
);
},
[accountList]
);
//删除账号的时候禁用FlatList的滑动
const accountListRef = useRef(null);
//单个账号卡片
const renderItem = ({ item }) => (
<AccountCard data={item} listRef={accountListRef} />
);
return (
<View
style={{
paddingBottom: insets.bottom,
paddingLeft: insets.left,
paddingRight: insets.right,
...tailwind("flex-1"),
}}
>
<View style={tailwind("px-4 flex-1")}>
<FlatList
ref={accountListRef}
data={accountList}
renderItem={renderItem}
initialNumToRender={6}
ListEmptyComponent={<Empty type="nodata" />}
ListFooterComponent={
<TouchableOpacity
onPress={signOut}
style={tailwind(
"flex flex-row items-center justify-center py-2 bg-[#FFFFFF1A] rounded-full mt-4"
)}
>
<Icon type="ionicon" name="add-outline" size={24} color="white" />
<Text style={tailwind("text-white text-base font-medium ml-1")}>
添加或注册账号
</Text>
</TouchableOpacity>
}
/>
</View>
{isSwitching && (
<View
style={tailwind(
"absolute flex w-full h-full items-center justify-center"
)}
>
<ActivityIndicator size="large" />
</View>
)}
<MyModal
visible={warnModalVisible}
setVisible={setWarnModalVisible}
title="是否继续切换?"
content="当前账号为验证码登录,切换账号会导致当前登录状态失效,无法快速切换回此账号,需进行一次密码登录方可保存快速切换账号。"
cancel={() => {
setWarnModalVisible(false);
}}
confirm={() => {
setWarnModalVisible(false);
switchAccountWithPhoneNumLogin(warnModalData);
}}
/>
</View>
);
}
const mapDispatchFromProps = (dispatch) => {
return {
changeLogin: (data) => {
// 调用dispatch方法传递actions
dispatch(handleLogin(data));
},
};
};
export default connect(null, mapDispatchFromProps)(SwitchAccount);