feat: optimize sign in experience (#4099)
This commit is contained in:
@@ -22,11 +22,7 @@ export const AfterSignInSendEmail = ({
|
|||||||
const t = useAFFiNEI18N();
|
const t = useAFFiNEI18N();
|
||||||
const loginStatus = useCurrentLoginStatus();
|
const loginStatus = useCurrentLoginStatus();
|
||||||
|
|
||||||
const { resendCountDown, allowSendEmail, signIn } = useAuth({
|
const { resendCountDown, allowSendEmail, signIn } = useAuth();
|
||||||
onNoAccess: useCallback(() => {
|
|
||||||
setAuthState('noAccess');
|
|
||||||
}, [setAuthState]),
|
|
||||||
});
|
|
||||||
if (loginStatus === 'authenticated') {
|
if (loginStatus === 'authenticated') {
|
||||||
onSignedIn?.();
|
onSignedIn?.();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,11 +21,7 @@ export const AfterSignUpSendEmail: FC<AuthPanelProps> = ({
|
|||||||
const t = useAFFiNEI18N();
|
const t = useAFFiNEI18N();
|
||||||
const loginStatus = useCurrentLoginStatus();
|
const loginStatus = useCurrentLoginStatus();
|
||||||
|
|
||||||
const { resendCountDown, allowSendEmail, signUp } = useAuth({
|
const { resendCountDown, allowSendEmail, signUp } = useAuth();
|
||||||
onNoAccess: useCallback(() => {
|
|
||||||
setAuthState('noAccess');
|
|
||||||
}, [setAuthState]),
|
|
||||||
});
|
|
||||||
|
|
||||||
if (loginStatus === 'authenticated') {
|
if (loginStatus === 'authenticated') {
|
||||||
onSignedIn?.();
|
onSignedIn?.();
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import { useCurrentLoginStatus } from '../../../hooks/affine/use-current-login-s
|
|||||||
import { emailRegex } from '../../../utils/email-regex';
|
import { emailRegex } from '../../../utils/email-regex';
|
||||||
import type { AuthPanelProps } from './index';
|
import type { AuthPanelProps } from './index';
|
||||||
import * as style from './style.css';
|
import * as style from './style.css';
|
||||||
import { useAuth } from './use-auth';
|
import { INTERNAL_BETA_URL, useAuth } from './use-auth';
|
||||||
|
|
||||||
function validateEmail(email: string) {
|
function validateEmail(email: string) {
|
||||||
return emailRegex.test(email);
|
return emailRegex.test(email);
|
||||||
@@ -31,12 +31,14 @@ export const SignIn: FC<AuthPanelProps> = ({
|
|||||||
const t = useAFFiNEI18N();
|
const t = useAFFiNEI18N();
|
||||||
const loginStatus = useCurrentLoginStatus();
|
const loginStatus = useCurrentLoginStatus();
|
||||||
|
|
||||||
const { resendCountDown, allowSendEmail, signIn, signUp, signInWithGoogle } =
|
const {
|
||||||
useAuth({
|
isMutating: isSigningIn,
|
||||||
onNoAccess: useCallback(() => {
|
resendCountDown,
|
||||||
setAuthState('noAccess');
|
allowSendEmail,
|
||||||
}, [setAuthState]),
|
signIn,
|
||||||
});
|
signUp,
|
||||||
|
signInWithGoogle,
|
||||||
|
} = useAuth();
|
||||||
|
|
||||||
const { trigger: verifyUser, isMutating } = useMutation({
|
const { trigger: verifyUser, isMutating } = useMutation({
|
||||||
mutation: getUserQuery,
|
mutation: getUserQuery,
|
||||||
@@ -55,16 +57,20 @@ export const SignIn: FC<AuthPanelProps> = ({
|
|||||||
|
|
||||||
setIsValidEmail(true);
|
setIsValidEmail(true);
|
||||||
const { user } = await verifyUser({ email });
|
const { user } = await verifyUser({ email });
|
||||||
|
|
||||||
setAuthEmail(email);
|
setAuthEmail(email);
|
||||||
|
|
||||||
if (user) {
|
if (user) {
|
||||||
|
const res = await signIn(email);
|
||||||
|
if (res?.status === 403 && res?.url === INTERNAL_BETA_URL) {
|
||||||
|
return setAuthState('noAccess');
|
||||||
|
}
|
||||||
setAuthState('afterSignInSendEmail');
|
setAuthState('afterSignInSendEmail');
|
||||||
|
|
||||||
await signIn(email);
|
|
||||||
} else {
|
} else {
|
||||||
|
const res = await signUp(email);
|
||||||
|
if (res?.status === 403 && res?.url === INTERNAL_BETA_URL) {
|
||||||
|
return setAuthState('noAccess');
|
||||||
|
}
|
||||||
setAuthState('afterSignUpSendEmail');
|
setAuthState('afterSignUpSendEmail');
|
||||||
|
|
||||||
await signUp(email);
|
|
||||||
}
|
}
|
||||||
}, [email, setAuthEmail, setAuthState, signIn, signUp, verifyUser]);
|
}, [email, setAuthEmail, setAuthState, signIn, signUp, verifyUser]);
|
||||||
|
|
||||||
@@ -112,7 +118,7 @@ export const SignIn: FC<AuthPanelProps> = ({
|
|||||||
size="extraLarge"
|
size="extraLarge"
|
||||||
data-testid="continue-login-button"
|
data-testid="continue-login-button"
|
||||||
block
|
block
|
||||||
loading={isMutating}
|
loading={isMutating || isSigningIn}
|
||||||
disabled={!allowSendEmail}
|
disabled={!allowSendEmail}
|
||||||
icon={
|
icon={
|
||||||
allowSendEmail || isMutating ? (
|
allowSendEmail || isMutating ? (
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import { useCallback } from 'react';
|
|||||||
import { signInCloud } from '../../../utils/cloud-utils';
|
import { signInCloud } from '../../../utils/cloud-utils';
|
||||||
|
|
||||||
const COUNT_DOWN_TIME = 60;
|
const COUNT_DOWN_TIME = 60;
|
||||||
const INTERNAL_BETA_URL = `https://community.affine.pro/c/insider-general/`;
|
export const INTERNAL_BETA_URL = `https://community.affine.pro/c/insider-general/`;
|
||||||
|
|
||||||
function handleSendEmailError(
|
function handleSendEmailError(
|
||||||
res: SignInResponse | undefined | void,
|
res: SignInResponse | undefined | void,
|
||||||
@@ -20,21 +20,16 @@ function handleSendEmailError(
|
|||||||
type: 'error',
|
type: 'error',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// if (res?.status === 403 && res?.url === INTERNAL_BETA_URL) {
|
|
||||||
// pushNotification({
|
|
||||||
// title: 'Sign up error',
|
|
||||||
// message: `You don't have early access permission\nVisit ${INTERNAL_BETA_URL} for more information`,
|
|
||||||
// type: 'error',
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type AuthStoreAtom = {
|
type AuthStoreAtom = {
|
||||||
allowSendEmail: boolean;
|
allowSendEmail: boolean;
|
||||||
resendCountDown: number;
|
resendCountDown: number;
|
||||||
|
isMutating: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const authStoreAtom = atom<AuthStoreAtom>({
|
export const authStoreAtom = atom<AuthStoreAtom>({
|
||||||
|
isMutating: false,
|
||||||
allowSendEmail: true,
|
allowSendEmail: true,
|
||||||
resendCountDown: COUNT_DOWN_TIME,
|
resendCountDown: COUNT_DOWN_TIME,
|
||||||
});
|
});
|
||||||
@@ -46,6 +41,7 @@ const countDownAtom = atom(
|
|||||||
const countDown = get(authStoreAtom).resendCountDown;
|
const countDown = get(authStoreAtom).resendCountDown;
|
||||||
if (countDown === 0) {
|
if (countDown === 0) {
|
||||||
set(authStoreAtom, {
|
set(authStoreAtom, {
|
||||||
|
isMutating: false,
|
||||||
allowSendEmail: true,
|
allowSendEmail: true,
|
||||||
resendCountDown: COUNT_DOWN_TIME,
|
resendCountDown: COUNT_DOWN_TIME,
|
||||||
});
|
});
|
||||||
@@ -53,6 +49,7 @@ const countDownAtom = atom(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
set(authStoreAtom, {
|
set(authStoreAtom, {
|
||||||
|
isMutating: false,
|
||||||
resendCountDown: countDown - 1,
|
resendCountDown: countDown - 1,
|
||||||
allowSendEmail: false,
|
allowSendEmail: false,
|
||||||
});
|
});
|
||||||
@@ -60,18 +57,19 @@ const countDownAtom = atom(
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
export const useAuth = ({ onNoAccess }: { onNoAccess: () => void }) => {
|
export const useAuth = () => {
|
||||||
const pushNotification = useSetAtom(pushNotificationAtom);
|
const pushNotification = useSetAtom(pushNotificationAtom);
|
||||||
const [authStore, setAuthStore] = useAtom(authStoreAtom);
|
const [authStore, setAuthStore] = useAtom(authStoreAtom);
|
||||||
const startResendCountDown = useSetAtom(countDownAtom);
|
const startResendCountDown = useSetAtom(countDownAtom);
|
||||||
|
|
||||||
const signIn = useCallback(
|
const signIn = useCallback(
|
||||||
async (email: string) => {
|
async (email: string) => {
|
||||||
setAuthStore(() => ({
|
setAuthStore(prev => {
|
||||||
allowSendEmail: false,
|
return {
|
||||||
resendCountDown: COUNT_DOWN_TIME,
|
...prev,
|
||||||
}));
|
isMutating: true,
|
||||||
startResendCountDown();
|
};
|
||||||
|
});
|
||||||
|
|
||||||
const res = await signInCloud('email', {
|
const res = await signInCloud('email', {
|
||||||
email: email,
|
email: email,
|
||||||
@@ -81,20 +79,27 @@ export const useAuth = ({ onNoAccess }: { onNoAccess: () => void }) => {
|
|||||||
|
|
||||||
handleSendEmailError(res, pushNotification);
|
handleSendEmailError(res, pushNotification);
|
||||||
|
|
||||||
if (res?.status === 403 && res?.url === INTERNAL_BETA_URL) {
|
setAuthStore({
|
||||||
onNoAccess();
|
isMutating: false,
|
||||||
}
|
allowSendEmail: false,
|
||||||
|
resendCountDown: COUNT_DOWN_TIME,
|
||||||
|
});
|
||||||
|
|
||||||
|
startResendCountDown();
|
||||||
|
|
||||||
|
return res;
|
||||||
},
|
},
|
||||||
[onNoAccess, pushNotification, setAuthStore, startResendCountDown]
|
[pushNotification, setAuthStore, startResendCountDown]
|
||||||
);
|
);
|
||||||
|
|
||||||
const signUp = useCallback(
|
const signUp = useCallback(
|
||||||
async (email: string) => {
|
async (email: string) => {
|
||||||
setAuthStore({
|
setAuthStore(prev => {
|
||||||
allowSendEmail: false,
|
return {
|
||||||
resendCountDown: COUNT_DOWN_TIME,
|
...prev,
|
||||||
|
isMutating: true,
|
||||||
|
};
|
||||||
});
|
});
|
||||||
startResendCountDown();
|
|
||||||
|
|
||||||
const res = await signInCloud('email', {
|
const res = await signInCloud('email', {
|
||||||
email: email,
|
email: email,
|
||||||
@@ -104,11 +109,17 @@ export const useAuth = ({ onNoAccess }: { onNoAccess: () => void }) => {
|
|||||||
|
|
||||||
handleSendEmailError(res, pushNotification);
|
handleSendEmailError(res, pushNotification);
|
||||||
|
|
||||||
if (res?.status === 403 && res?.url === INTERNAL_BETA_URL) {
|
setAuthStore({
|
||||||
onNoAccess();
|
isMutating: false,
|
||||||
}
|
allowSendEmail: false,
|
||||||
|
resendCountDown: COUNT_DOWN_TIME,
|
||||||
|
});
|
||||||
|
|
||||||
|
startResendCountDown();
|
||||||
|
|
||||||
|
return res;
|
||||||
},
|
},
|
||||||
[onNoAccess, pushNotification, setAuthStore, startResendCountDown]
|
[pushNotification, setAuthStore, startResendCountDown]
|
||||||
);
|
);
|
||||||
|
|
||||||
const signInWithGoogle = useCallback(() => {
|
const signInWithGoogle = useCallback(() => {
|
||||||
@@ -118,6 +129,7 @@ export const useAuth = ({ onNoAccess }: { onNoAccess: () => void }) => {
|
|||||||
return {
|
return {
|
||||||
allowSendEmail: authStore.allowSendEmail,
|
allowSendEmail: authStore.allowSendEmail,
|
||||||
resendCountDown: authStore.resendCountDown,
|
resendCountDown: authStore.resendCountDown,
|
||||||
|
isMutating: authStore.isMutating,
|
||||||
signUp,
|
signUp,
|
||||||
signIn,
|
signIn,
|
||||||
signInWithGoogle,
|
signInWithGoogle,
|
||||||
|
|||||||
Reference in New Issue
Block a user