mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
Fix/tauri login state (#1919)
* fix: redux serializableCheck * chore: read login state * fix: show loading page while checking user state * chore: cell data parser
This commit is contained in:
parent
3f0d3d802a
commit
205b0fc4a5
Binary file not shown.
After Width: | Height: | Size: 1.1 MiB |
@ -1,5 +1,4 @@
|
||||
import React from 'react';
|
||||
import TestApiButton from './TestApiButton';
|
||||
import {
|
||||
TestCreateGrid,
|
||||
TestCreateNewField,
|
||||
@ -18,7 +17,7 @@ export const TestAPI = () => {
|
||||
return (
|
||||
<React.Fragment>
|
||||
<ul className='m-6, space-y-2'>
|
||||
<TestApiButton></TestApiButton>
|
||||
{/*<TestApiButton></TestApiButton>*/}
|
||||
<TestCreateGrid></TestCreateGrid>
|
||||
<TestCreateRow></TestCreateRow>
|
||||
<TestDeleteRow></TestDeleteRow>
|
||||
|
@ -126,8 +126,10 @@ export const TestCreateSelectOptionInCell = () => {
|
||||
);
|
||||
await cellController.subscribeChanged({
|
||||
onCellChanged: (value) => {
|
||||
const option: SelectOptionCellDataPB = value.unwrap();
|
||||
console.log(option);
|
||||
if (value.some) {
|
||||
const option: SelectOptionCellDataPB = value.unwrap();
|
||||
console.log(option);
|
||||
}
|
||||
},
|
||||
});
|
||||
const backendSvc = new SelectOptionCellBackendService(cellController.cellIdentifier);
|
||||
|
@ -1,16 +1,54 @@
|
||||
import { Navigate, Outlet, useLocation } from 'react-router-dom';
|
||||
import { Outlet } from 'react-router-dom';
|
||||
import { useAuth } from './auth.hooks';
|
||||
import { Screen } from '../layout/Screen';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { GetStarted } from './GetStarted/GetStarted';
|
||||
import { AppflowyLogo } from '../_shared/svg/AppflowyLogo';
|
||||
|
||||
export const ProtectedRoutes = () => {
|
||||
const location = useLocation();
|
||||
const { currentUser } = useAuth();
|
||||
const { currentUser, checkUser } = useAuth();
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
|
||||
return currentUser.isAuthenticated ? (
|
||||
<Screen>
|
||||
<Outlet />
|
||||
</Screen>
|
||||
) : (
|
||||
<Navigate to='/auth/getStarted' replace state={{ from: location }} />
|
||||
useEffect(() => {
|
||||
void checkUser().then(async (result) => {
|
||||
if (result.err) {
|
||||
throw new Error(result.val.msg);
|
||||
}
|
||||
|
||||
await new Promise(() =>
|
||||
setTimeout(() => {
|
||||
setIsLoading(false);
|
||||
}, 1200)
|
||||
);
|
||||
});
|
||||
}, []);
|
||||
|
||||
if (isLoading) {
|
||||
// It's better to make a fading effect to disappear the loading page
|
||||
return <StartLoading />;
|
||||
} else {
|
||||
return <SplashScreen isAuthenticated={currentUser.isAuthenticated} />;
|
||||
}
|
||||
};
|
||||
|
||||
const StartLoading = () => {
|
||||
return (
|
||||
<div className='flex h-screen w-full flex-col items-center justify-center'>
|
||||
<div className='h-40 w-40 justify-center'>
|
||||
<AppflowyLogo />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const SplashScreen = ({ isAuthenticated }: { isAuthenticated: boolean }) => {
|
||||
if (isAuthenticated) {
|
||||
return (
|
||||
<Screen>
|
||||
<Outlet />
|
||||
</Screen>
|
||||
);
|
||||
} else {
|
||||
return <GetStarted></GetStarted>;
|
||||
}
|
||||
};
|
||||
|
@ -1,20 +1,46 @@
|
||||
import { currentUserActions } from '../../stores/reducers/current-user/slice';
|
||||
import { useAppDispatch, useAppSelector } from '../../stores/store';
|
||||
import { UserProfilePB } from '../../../services/backend/events/flowy-user';
|
||||
import { AuthBackendService } from '../../stores/effects/user/user_bd_svc';
|
||||
import { AuthBackendService, UserBackendService } from '../../stores/effects/user/user_bd_svc';
|
||||
import { FolderEventReadCurrentWorkspace } from '../../../services/backend/events/flowy-folder';
|
||||
import { WorkspaceSettingPB } from '../../../services/backend/models/flowy-folder/workspace';
|
||||
import { Log } from '../../utils/log';
|
||||
|
||||
export const useAuth = () => {
|
||||
const dispatch = useAppDispatch();
|
||||
const currentUser = useAppSelector((state) => state.currentUser);
|
||||
const authBackendService = new AuthBackendService();
|
||||
|
||||
async function checkUser() {
|
||||
const result = await UserBackendService.checkUser();
|
||||
if (result.ok) {
|
||||
const userProfile = result.val;
|
||||
const workspaceSetting = await _openWorkspace().then((r) => {
|
||||
if (r.ok) {
|
||||
return r.val;
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
});
|
||||
dispatch(
|
||||
currentUserActions.checkUser({
|
||||
id: userProfile.id,
|
||||
token: userProfile.token,
|
||||
email: userProfile.email,
|
||||
displayName: userProfile.name,
|
||||
isAuthenticated: true,
|
||||
workspaceSetting: workspaceSetting,
|
||||
})
|
||||
);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
async function register(email: string, password: string, name: string): Promise<UserProfilePB> {
|
||||
const authResult = await authBackendService.signUp({ email, password, name });
|
||||
|
||||
if (authResult.ok) {
|
||||
const { id, token } = authResult.val;
|
||||
const userProfile = authResult.val;
|
||||
// Get the workspace setting after user registered. The workspace setting
|
||||
// contains the latest visiting view and the current workspace data.
|
||||
const openWorkspaceResult = await _openWorkspace();
|
||||
@ -22,10 +48,10 @@ export const useAuth = () => {
|
||||
const workspaceSetting: WorkspaceSettingPB = openWorkspaceResult.val;
|
||||
dispatch(
|
||||
currentUserActions.updateUser({
|
||||
id: id,
|
||||
token: token,
|
||||
email,
|
||||
displayName: name,
|
||||
id: userProfile.id,
|
||||
token: userProfile.token,
|
||||
email: userProfile.email,
|
||||
displayName: userProfile.name,
|
||||
isAuthenticated: true,
|
||||
workspaceSetting: workspaceSetting,
|
||||
})
|
||||
@ -33,7 +59,7 @@ export const useAuth = () => {
|
||||
}
|
||||
return authResult.val;
|
||||
} else {
|
||||
console.error(authResult.val.msg);
|
||||
Log.error(authResult.val.msg);
|
||||
throw new Error(authResult.val.msg);
|
||||
}
|
||||
}
|
||||
@ -53,7 +79,7 @@ export const useAuth = () => {
|
||||
);
|
||||
return result.val;
|
||||
} else {
|
||||
console.error(result.val.msg);
|
||||
Log.error(result.val.msg);
|
||||
throw new Error(result.val.msg);
|
||||
}
|
||||
}
|
||||
@ -67,5 +93,5 @@ export const useAuth = () => {
|
||||
return FolderEventReadCurrentWorkspace();
|
||||
}
|
||||
|
||||
return { currentUser, register, login, logout };
|
||||
return { currentUser, checkUser, register, login, logout };
|
||||
};
|
||||
|
@ -13,7 +13,7 @@ type Callbacks<T> = { onCellChanged: (value: Option<T>) => void; onFieldChanged?
|
||||
|
||||
export class CellController<T, D> {
|
||||
private fieldBackendService: FieldBackendService;
|
||||
private cellDataNotifier: CellDataNotifier<Option<T>>;
|
||||
private cellDataNotifier: CellDataNotifier<T>;
|
||||
private cellObserver: CellObserver;
|
||||
private readonly cacheKey: CellCacheKey;
|
||||
private readonly fieldNotifier: DatabaseFieldObserver;
|
||||
@ -59,7 +59,7 @@ export class CellController<T, D> {
|
||||
this.subscribeCallbacks = callbacks;
|
||||
this.cellDataNotifier.observer.subscribe((cellData) => {
|
||||
if (cellData !== null) {
|
||||
callbacks.onCellChanged(cellData);
|
||||
callbacks.onCellChanged(Some(cellData));
|
||||
}
|
||||
});
|
||||
};
|
||||
@ -95,8 +95,11 @@ export class CellController<T, D> {
|
||||
private _loadCellData = () => {
|
||||
return this.cellDataLoader.loadData().then((result) => {
|
||||
if (result.ok) {
|
||||
this.cellCache.insert(this.cacheKey, result.val);
|
||||
this.cellDataNotifier.cellData = Some(result.val);
|
||||
const cellData = result.val;
|
||||
if (cellData.some) {
|
||||
this.cellCache.insert(this.cacheKey, cellData.val);
|
||||
this.cellDataNotifier.cellData = cellData;
|
||||
}
|
||||
} else {
|
||||
this.cellCache.remove(this.cacheKey);
|
||||
this.cellDataNotifier.cellData = None;
|
||||
@ -110,12 +113,12 @@ export class CellController<T, D> {
|
||||
};
|
||||
}
|
||||
|
||||
class CellDataNotifier<T> extends ChangeNotifier<T | null> {
|
||||
class CellDataNotifier<T> extends ChangeNotifier<T> {
|
||||
_cellData: Option<T>;
|
||||
|
||||
constructor(cellData: T) {
|
||||
constructor(cellData: Option<T>) {
|
||||
super();
|
||||
this._cellData = Some(cellData);
|
||||
this._cellData = cellData;
|
||||
}
|
||||
|
||||
set cellData(data: Option<T>) {
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { nanoid } from '@reduxjs/toolkit';
|
||||
import {
|
||||
UserEventCheckUser,
|
||||
UserEventGetUserProfile,
|
||||
UserEventSignIn,
|
||||
UserEventSignOut,
|
||||
@ -29,6 +30,10 @@ export class UserBackendService {
|
||||
return UserEventGetUserProfile();
|
||||
};
|
||||
|
||||
static checkUser = () => {
|
||||
return UserEventCheckUser();
|
||||
};
|
||||
|
||||
updateUserProfile = (params: { name?: string; password?: string; email?: string; openAIKey?: string }) => {
|
||||
const payload = UpdateUserProfilePayloadPB.fromObject({ id: this.userId });
|
||||
|
||||
|
@ -12,10 +12,6 @@ export interface ICurrentUser {
|
||||
}
|
||||
|
||||
const initialState: ICurrentUser | null = {
|
||||
id: nanoid(8),
|
||||
displayName: 'Me 😃',
|
||||
email: `${nanoid(4)}@gmail.com`,
|
||||
token: nanoid(8),
|
||||
isAuthenticated: false,
|
||||
};
|
||||
|
||||
@ -23,6 +19,9 @@ export const currentUserSlice = createSlice({
|
||||
name: 'currentUser',
|
||||
initialState: initialState,
|
||||
reducers: {
|
||||
checkUser: (state, action: PayloadAction<ICurrentUser>) => {
|
||||
return action.payload;
|
||||
},
|
||||
updateUser: (state, action: PayloadAction<ICurrentUser>) => {
|
||||
return action.payload;
|
||||
},
|
||||
|
@ -33,7 +33,7 @@ const store = configureStore({
|
||||
[workspaceSlice.name]: workspaceSlice.reducer,
|
||||
[errorSlice.name]: errorSlice.reducer,
|
||||
},
|
||||
middleware: (gDM) => gDM().prepend(listenerMiddlewareInstance.middleware),
|
||||
middleware: (gDM) => gDM({ serializableCheck: false }).prepend(listenerMiddlewareInstance.middleware),
|
||||
});
|
||||
|
||||
export { store };
|
||||
|
Loading…
Reference in New Issue
Block a user