Skip to content

Commit

Permalink
refactor(experience): add global loading status on page redirect
Browse files Browse the repository at this point in the history
add global loading status on page redirect
  • Loading branch information
simeng-li committed May 17, 2024
1 parent a1091ae commit 3f8c027
Show file tree
Hide file tree
Showing 15 changed files with 121 additions and 50 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@ import { useCallback } from 'react';
import { bindSocialRelatedUser } from '@/apis/interaction';
import useApi from '@/hooks/use-api';
import useErrorHandler from '@/hooks/use-error-handler';
import useGlobalRedirectTo from '@/hooks/use-global-redirect-to';
import usePreSignInErrorHandler from '@/hooks/use-pre-sign-in-error-handler';

const useBindSocialRelatedUser = () => {
const handleError = useErrorHandler();
const preSignInErrorHandler = usePreSignInErrorHandler();
const redirectTo = useGlobalRedirectTo();

const asyncBindSocialRelatedUser = useApi(bindSocialRelatedUser);

Expand All @@ -22,10 +24,10 @@ const useBindSocialRelatedUser = () => {
}

if (result?.redirectTo) {
window.location.replace(result.redirectTo);
redirectTo(result.redirectTo);
}
},
[asyncBindSocialRelatedUser, handleError, preSignInErrorHandler]
[asyncBindSocialRelatedUser, handleError, preSignInErrorHandler, redirectTo]
);
};

Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import type { EmailVerificationCodePayload, PhoneVerificationCodePayload } from '@logto/schemas';
import { SignInIdentifier } from '@logto/schemas';
import { useMemo, useCallback } from 'react';
import { useCallback, useMemo } from 'react';
import { useSearchParams } from 'react-router-dom';

import { addProfileWithVerificationCodeIdentifier } from '@/apis/interaction';
import useApi from '@/hooks/use-api';
import type { ErrorHandlers } from '@/hooks/use-error-handler';
import useErrorHandler from '@/hooks/use-error-handler';
import useGlobalRedirectTo from '@/hooks/use-global-redirect-to';
import usePreSignInErrorHandler from '@/hooks/use-pre-sign-in-error-handler';
import type { VerificationCodeIdentifier } from '@/types';
import { SearchParameters } from '@/types';
Expand All @@ -21,6 +22,7 @@ const useContinueFlowCodeVerification = (
errorCallback?: () => void
) => {
const [searchParameters] = useSearchParams();
const redirectTo = useGlobalRedirectTo();

const handleError = useErrorHandler();
const verifyVerificationCode = useApi(addProfileWithVerificationCodeIdentifier);
Expand Down Expand Up @@ -76,10 +78,16 @@ const useContinueFlowCodeVerification = (
}

if (result?.redirectTo) {
window.location.replace(result.redirectTo);
redirectTo(result.redirectTo);
}
},
[errorCallback, handleError, verifyVerificationCode, verifyVerificationCodeErrorHandlers]
[
errorCallback,
handleError,
redirectTo,
verifyVerificationCode,
verifyVerificationCodeErrorHandlers,
]
);

return {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { EmailVerificationCodePayload, PhoneVerificationCodePayload } from '@logto/schemas';
import { SignInIdentifier, SignInMode } from '@logto/schemas';
import { useMemo, useCallback } from 'react';
import { useCallback, useMemo } from 'react';
import { useTranslation } from 'react-i18next';
import { useNavigate } from 'react-router-dom';

Expand All @@ -12,6 +12,7 @@ import useApi from '@/hooks/use-api';
import { useConfirmModal } from '@/hooks/use-confirm-modal';
import type { ErrorHandlers } from '@/hooks/use-error-handler';
import useErrorHandler from '@/hooks/use-error-handler';
import useGlobalRedirectTo from '@/hooks/use-global-redirect-to';
import usePreSignInErrorHandler from '@/hooks/use-pre-sign-in-error-handler';
import { useSieMethods } from '@/hooks/use-sie';
import type { VerificationCodeIdentifier } from '@/types';
Expand All @@ -28,6 +29,7 @@ const useRegisterFlowCodeVerification = (
const { t } = useTranslation();
const { show } = useConfirmModal();
const navigate = useNavigate();
const redirectTo = useGlobalRedirectTo();

const { signInMode } = useSieMethods();

Expand Down Expand Up @@ -74,13 +76,14 @@ const useRegisterFlowCodeVerification = (
}

if (result?.redirectTo) {
window.location.replace(result.redirectTo);
redirectTo(result.redirectTo);
}
}, [
handleError,
method,
navigate,
preSignInErrorHandler,
redirectTo,
show,
showIdentifierErrorAlert,
signInMode,
Expand Down Expand Up @@ -117,10 +120,10 @@ const useRegisterFlowCodeVerification = (
}

if (result?.redirectTo) {
window.location.replace(result.redirectTo);
redirectTo(result.redirectTo);
}
},
[errorCallback, errorHandlers, handleError, verifyVerificationCode]
[errorCallback, errorHandlers, handleError, redirectTo, verifyVerificationCode]
);

return {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
import type { EmailVerificationCodePayload, PhoneVerificationCodePayload } from '@logto/schemas';
import { SignInIdentifier, SignInMode } from '@logto/schemas';
import { useMemo, useCallback } from 'react';
import { useCallback, useMemo } from 'react';
import { useTranslation } from 'react-i18next';
import { useNavigate } from 'react-router-dom';

import {
signInWithVerificationCodeIdentifier,
registerWithVerifiedIdentifier,
signInWithVerificationCodeIdentifier,
} from '@/apis/interaction';
import useApi from '@/hooks/use-api';
import { useConfirmModal } from '@/hooks/use-confirm-modal';
import type { ErrorHandlers } from '@/hooks/use-error-handler';
import useErrorHandler from '@/hooks/use-error-handler';
import useGlobalRedirectTo from '@/hooks/use-global-redirect-to';
import usePreSignInErrorHandler from '@/hooks/use-pre-sign-in-error-handler';
import { useSieMethods } from '@/hooks/use-sie';
import type { VerificationCodeIdentifier } from '@/types';
Expand All @@ -28,6 +29,7 @@ const useSignInFlowCodeVerification = (
const { t } = useTranslation();
const { show } = useConfirmModal();
const navigate = useNavigate();
const redirectTo = useGlobalRedirectTo();
const { signInMode } = useSieMethods();

const handleError = useErrorHandler();
Expand Down Expand Up @@ -77,19 +79,20 @@ const useSignInFlowCodeVerification = (
}

if (result?.redirectTo) {
window.location.replace(result.redirectTo);
redirectTo(result.redirectTo);
}
}, [
handleError,
method,
navigate,
registerWithIdentifierAsync,
preSignInErrorHandler,
show,
showIdentifierErrorAlert,
signInMode,
show,
t,
method,
target,
registerWithIdentifierAsync,
showIdentifierErrorAlert,
navigate,
handleError,
preSignInErrorHandler,
redirectTo,
]);

const errorHandlers = useMemo<ErrorHandlers>(
Expand Down Expand Up @@ -118,10 +121,10 @@ const useSignInFlowCodeVerification = (
}

if (result?.redirectTo) {
window.location.replace(result.redirectTo);
redirectTo(result.redirectTo);
}
},
[asyncSignInWithVerificationCodeIdentifier, errorHandlers, handleError]
[asyncSignInWithVerificationCodeIdentifier, errorHandlers, handleError, redirectTo]
);

return {
Expand Down
26 changes: 26 additions & 0 deletions packages/experience/src/hooks/use-global-redirect-to.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { useCallback, useContext } from 'react';

import PageContext from '@/Providers/PageContextProvider/PageContext';

/**
* This hook provides a function that process the app redirection after user successfully signs in.
* Use window.location.replace to handle the redirection.
* Set the global loading state to true before redirecting.
* This is to prevent the user from interacting with the app while the redirection is in progress.
*/

function useGlobalRedirectTo() {
const { setLoading } = useContext(PageContext);

const redirectTo = useCallback(
(url: string | URL) => {
setLoading(true);
window.location.replace(url);
},
[setLoading]
);

return redirectTo;
}

export default useGlobalRedirectTo;
8 changes: 5 additions & 3 deletions packages/experience/src/hooks/use-password-sign-in.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useState, useMemo, useCallback } from 'react';
import { useCallback, useMemo, useState } from 'react';

import type { PasswordSignInPayload } from '@/apis/interaction';
import { signInWithPasswordIdentifier } from '@/apis/interaction';
Expand All @@ -7,11 +7,13 @@ import useCheckSingleSignOn from '@/hooks/use-check-single-sign-on';
import type { ErrorHandlers } from '@/hooks/use-error-handler';
import useErrorHandler from '@/hooks/use-error-handler';

import useGlobalRedirectTo from './use-global-redirect-to';
import usePreSignInErrorHandler from './use-pre-sign-in-error-handler';

const usePasswordSignIn = () => {
const [errorMessage, setErrorMessage] = useState<string>();
const { onSubmit: checkSingleSignOn } = useCheckSingleSignOn();
const redirectTo = useGlobalRedirectTo();

const clearErrorMessage = useCallback(() => {
setErrorMessage('');
Expand Down Expand Up @@ -51,10 +53,10 @@ const usePasswordSignIn = () => {
}

if (result?.redirectTo) {
window.location.replace(result.redirectTo);
redirectTo(result.redirectTo);
}
},
[asyncSignIn, checkSingleSignOn, errorHandlers, handleError]
[asyncSignIn, checkSingleSignOn, errorHandlers, handleError, redirectTo]
);

return {
Expand Down
6 changes: 4 additions & 2 deletions packages/experience/src/hooks/use-send-mfa-payload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { UserMfaFlow } from '@/types';

import useApi from './use-api';
import useErrorHandler, { type ErrorHandlers } from './use-error-handler';
import useGlobalRedirectTo from './use-global-redirect-to';
import usePreSignInErrorHandler from './use-pre-sign-in-error-handler';

export type SendMfaPayloadApiOptions =
Expand All @@ -29,6 +30,7 @@ const useSendMfaPayload = () => {
const asyncSendMfaPayload = useApi(sendMfaPayloadApi);
const preSignInErrorHandler = usePreSignInErrorHandler({ replace: true });
const handleError = useErrorHandler();
const redirectTo = useGlobalRedirectTo();

return useCallback(
async (
Expand All @@ -48,10 +50,10 @@ const useSendMfaPayload = () => {
}

if (result) {
window.location.replace(result.redirectTo);
redirectTo(result.redirectTo);
}
},
[asyncSendMfaPayload, handleError, preSignInErrorHandler]
[asyncSendMfaPayload, handleError, preSignInErrorHandler, redirectTo]
);
};

Expand Down
6 changes: 4 additions & 2 deletions packages/experience/src/hooks/use-skip-mfa.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@ import { skipMfa } from '@/apis/interaction';

import useApi from './use-api';
import useErrorHandler from './use-error-handler';
import useGlobalRedirectTo from './use-global-redirect-to';
import usePreSignInErrorHandler from './use-pre-sign-in-error-handler';

const useSkipMfa = () => {
const asyncSkipMfa = useApi(skipMfa);
const redirectTo = useGlobalRedirectTo();

const handleError = useErrorHandler();
const preSignInErrorHandler = usePreSignInErrorHandler({ replace: true });
Expand All @@ -20,9 +22,9 @@ const useSkipMfa = () => {
}

if (result) {
window.location.replace(result.redirectTo);
redirectTo(result.redirectTo);
}
}, [asyncSkipMfa, handleError, preSignInErrorHandler]);
}, [asyncSkipMfa, handleError, preSignInErrorHandler, redirectTo]);
};

export default useSkipMfa;
6 changes: 4 additions & 2 deletions packages/experience/src/hooks/use-social-link-account.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@ import { linkWithSocial } from '@/apis/interaction';
import useApi from '@/hooks/use-api';

import useErrorHandler from './use-error-handler';
import useGlobalRedirectTo from './use-global-redirect-to';

const useLinkSocial = () => {
const handleError = useErrorHandler();
const asyncLinkWithSocial = useApi(linkWithSocial);
const redirectTo = useGlobalRedirectTo();

return useCallback(
async (connectorId: string) => {
Expand All @@ -20,10 +22,10 @@ const useLinkSocial = () => {
}

if (result?.redirectTo) {
window.location.replace(result.redirectTo);
redirectTo(result.redirectTo);
}
},
[asyncLinkWithSocial, handleError]
[asyncLinkWithSocial, handleError, redirectTo]
);
};

Expand Down
6 changes: 4 additions & 2 deletions packages/experience/src/hooks/use-social-register.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@ import { registerWithVerifiedSocial } from '@/apis/interaction';

import useApi from './use-api';
import useErrorHandler from './use-error-handler';
import useGlobalRedirectTo from './use-global-redirect-to';
import usePreSignInErrorHandler from './use-pre-sign-in-error-handler';

const useSocialRegister = (connectorId?: string, replace?: boolean) => {
const handleError = useErrorHandler();
const asyncRegisterWithSocial = useApi(registerWithVerifiedSocial);
const redirectTo = useGlobalRedirectTo();

const preSignInErrorHandler = usePreSignInErrorHandler({ linkSocial: connectorId, replace });

Expand All @@ -23,10 +25,10 @@ const useSocialRegister = (connectorId?: string, replace?: boolean) => {
}

if (result?.redirectTo) {
window.location.replace(result.redirectTo);
redirectTo(result.redirectTo);
}
},
[asyncRegisterWithSocial, handleError, preSignInErrorHandler]
[asyncRegisterWithSocial, handleError, preSignInErrorHandler, redirectTo]
);
};

Expand Down
6 changes: 4 additions & 2 deletions packages/experience/src/pages/Consent/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import TermsLinks from '@/components/TermsLinks';
import TextLink from '@/components/TextLink';
import useApi from '@/hooks/use-api';
import useErrorHandler from '@/hooks/use-error-handler';
import useGlobalRedirectTo from '@/hooks/use-global-redirect-to';

import OrganizationSelector, { type Organization } from './OrganizationSelector';
import ScopesListCard from './ScopesListCard';
Expand All @@ -21,6 +22,7 @@ const Consent = () => {
const handleError = useErrorHandler();
const asyncConsent = useApi(consent);
const { t } = useTranslation();
const redirectTo = useGlobalRedirectTo();

const [consentData, setConsentData] = useState<ConsentInfoResponse>();
const [selectedOrganization, setSelectedOrganization] = useState<Organization>();
Expand All @@ -37,9 +39,9 @@ const Consent = () => {
}

if (result?.redirectTo) {
window.location.replace(result.redirectTo);
redirectTo(result.redirectTo);
}
}, [asyncConsent, handleError, selectedOrganization?.id]);
}, [asyncConsent, handleError, redirectTo, selectedOrganization?.id]);

useEffect(() => {
const getConsentInfoHandler = async () => {
Expand Down
Loading

0 comments on commit 3f8c027

Please sign in to comment.