You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tailchat/web/src/routes/Main/Provider.tsx

90 lines
2.3 KiB
TypeScript

import {
createSocket,
createStore,
setupRedux,
useAsync,
userActions,
loginWithToken,
} from 'tailchat-shared';
import React from 'react';
import { LoadingSpinner } from '../../components/LoadingSpinner';
import { Provider as ReduxProvider } from 'react-redux';
import { getGlobalUserLoginInfo } from '../../utils/user-helper';
import _isNil from 'lodash/isNil';
import { getUserJWT } from '../../utils/jwt-helper';
import { useHistory } from 'react-router';
import { SidebarContextProvider } from './SidebarContext';
import { PortalHost } from '@/components/Portal';
/**
* hooks
*/
function useAppState() {
const history = useHistory();
const { value, loading } = useAsync(async () => {
let userLoginInfo = getGlobalUserLoginInfo();
if (_isNil(userLoginInfo)) {
// 如果没有全局缓存的数据, 则尝试自动登录
try {
const token = await getUserJWT();
if (typeof token !== 'string') {
throw new Error('Token 不合法');
}
userLoginInfo = await loginWithToken(token);
} catch (e) {
// 当前 Token 不存在或已过期
history.replace('/entry/login');
return;
}
}
// 到这里 userLoginInfo 必定存在
// 创建Redux store
const store = createStore();
store.dispatch(userActions.setUserInfo(userLoginInfo));
// 创建 websocket 连接
const socket = await createSocket(userLoginInfo.token);
// 初始化Redux
setupRedux(socket, store);
return { store, socket };
}, [history]);
const store = value?.store;
const socket = value?.socket;
return { loading, store, socket };
}
/**
* Provider
*
*/
export const MainProvider: React.FC = React.memo((props) => {
const { loading, store } = useAppState();
if (loading) {
return (
<div className="fixed inset-0 flex items-center justify-center bg-gray-700 text-white text-xl">
<LoadingSpinner tip="正在连接到聊天服务器..." />
</div>
);
}
if (_isNil(store)) {
return <div>, Store </div>;
}
return (
<ReduxProvider store={store}>
<SidebarContextProvider>
<PortalHost>{props.children}</PortalHost>
</SidebarContextProvider>
</ReduxProvider>
);
});
MainProvider.displayName = 'MainProvider';