0
Fork 0
mirror of https://github.com/logto-io/logto.git synced 2025-03-17 22:31:28 -05:00

fix(ui): fix social native interaction bug (#772)

* fix(ui): fix social native sdk data namespace

fix social native sdk data namespace

* refactor(ui): refactor nativeSDK callbackUrl

 refactor nativeSDK callbackUrl
`

* refactor(ui): return result from api

return result from api

* fix(ui): should not show error message on social bind account

should not show error message on social bind account
This commit is contained in:
simeng-li 2022-05-10 12:20:15 +08:00 committed by GitHub
parent 475cb52d8e
commit 2161856bcd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 46 additions and 56 deletions

View file

@ -17,7 +17,7 @@ type Props = {
const PrimarySocialSignIn = ({ className, isPopup = false, onSocialSignInCallback }: Props) => {
const [showAll, setShowAll] = useState(false);
const { invokeSocialSignIn, socialConnectors } = useSocial({ onSocialSignInCallback });
const { invokeSocialSignIn, socialConnectors } = useSocial();
const isOverSize = socialConnectors.length > defaultSize;
const fullDisplay = isPopup || !isOverSize;
@ -37,7 +37,7 @@ const PrimarySocialSignIn = ({ className, isPopup = false, onSocialSignInCallbac
className={styles.socialLinkButton}
connector={connector}
onClick={() => {
void invokeSocialSignIn(connector.id);
void invokeSocialSignIn(connector.id, onSocialSignInCallback);
}}
/>
))}

View file

@ -28,7 +28,7 @@ describe('SecondarySocialSignIn', () => {
platform: 'web',
getPostMessage: jest.fn(() => jest.fn()),
callbackLink: '/logto:',
supportedSocialConnectors: socialConnectors.map(({ id }) => id),
supportedSocialConnectorIds: socialConnectors.map(({ id }) => id),
};
/* eslint-enable @silverhand/fp/no-mutation */
});

View file

@ -9,7 +9,7 @@ import { PageContext } from '@/hooks/use-page-context';
type UseApi<T extends any[], U> = {
result?: U;
error: RequestErrorBody | undefined;
run: (...args: T) => Promise<void>;
run: (...args: T) => Promise<U | undefined>;
};
export type ErrorHandlers = {
@ -38,6 +38,8 @@ function useApi<Args extends any[], Response>(
try {
const result = await api(...args);
setResult(result);
return result;
} catch (error: unknown) {
if (error instanceof HTTPError && error.response.body) {
const kyError = await error.response.json<RequestErrorBody>();

View file

@ -23,10 +23,6 @@ type State = {
callbackLink?: string;
};
type Options = {
onSocialSignInCallback?: () => void;
};
const storageKeyPrefix = 'social_auth_state';
const getLogtoNativeSdk = () => {
@ -69,7 +65,7 @@ const isNativeWebview = () => {
return ['ios', 'android'].includes(platform);
};
const useSocial = (options?: Options) => {
const useSocial = () => {
const { setToast, experienceSettings } = useContext(PageContext);
const { termsValidation } = useTerms();
const parameters = useParams();
@ -86,31 +82,26 @@ const useSocial = (options?: Options) => {
},
});
}
setToast(error.message);
},
}),
[navigate, parameters.connector, setToast]
[navigate, parameters.connector]
);
// Filter native supported social connectors
const socialConnectors = useMemo(
() =>
(experienceSettings?.socialConnectors ?? []).filter(({ id }) => {
return !isNativeWebview() || getLogtoNativeSdk()?.supportedSocialConnectors.includes(id);
return !isNativeWebview() || getLogtoNativeSdk()?.supportedSocialConnectorIds.includes(id);
}),
[experienceSettings?.socialConnectors]
);
const { result: invokeSocialSignInResult, run: asyncInvokeSocialSignIn } =
useApi(invokeSocialSignIn);
const { run: asyncInvokeSocialSignIn } = useApi(invokeSocialSignIn);
const { result: signInWithSocialResult, run: asyncSignInWithSocial } = useApi(
signInWithSocial,
signInWithSocialErrorHandlers
);
const { run: asyncSignInWithSocial } = useApi(signInWithSocial, signInWithSocialErrorHandlers);
const invokeSocialSignInHandler = useCallback(
async (connectorId: string) => {
async (connectorId: string, callback?: () => void) => {
if (!termsValidation()) {
return;
}
@ -120,23 +111,52 @@ const useSocial = (options?: Options) => {
const { origin } = window.location;
return asyncInvokeSocialSignIn(connectorId, state, `${origin}/callback/${connectorId}`);
const result = await asyncInvokeSocialSignIn(
connectorId,
state,
`${origin}/callback/${connectorId}`
);
if (!result?.redirectTo) {
return;
}
// Callback hook to close the social sign in modal
callback?.();
// Invoke Native Social Sign In flow
if (isNativeWebview()) {
getLogtoNativeSdk()?.getPostMessage()({
callbackUri: `${origin}/callback/${connectorId}`,
redirectTo: result.redirectTo,
});
return;
}
// Invoke Web Social Sign In flow
window.location.assign(result.redirectTo);
},
[asyncInvokeSocialSignIn, termsValidation]
);
const signInWithSocialHandler = useCallback(
(connectorId: string, state: string, code: string) => {
async (connectorId: string, state: string, code: string) => {
if (!stateValidation(state, connectorId)) {
setToast(t('error.invalid_connector_auth'));
return;
}
void asyncSignInWithSocial({
const result = await asyncSignInWithSocial({
connectorId,
code,
redirectUri: `${origin}/callback/${connectorId}`,
});
if (result?.redirectTo) {
window.location.assign(result.redirectTo);
}
},
[asyncSignInWithSocial, setToast, t]
);
@ -181,38 +201,6 @@ const useSocial = (options?: Options) => {
window.location.assign(new URL(`${callbackLink}${window.location.search}`));
}, [parameters.connector, setToast, t]);
// InvokeSocialSignIn Callback
useEffect(() => {
const { redirectTo } = invokeSocialSignInResult ?? {};
if (!redirectTo) {
return;
}
// Callback hook to close the social sign in modal
options?.onSocialSignInCallback?.();
// Invoke Native Social Sign In flow
if (isNativeWebview()) {
getLogtoNativeSdk()?.getPostMessage()({
callbackUri: redirectTo.replace('/callback', '/sign-in/callback'),
redirectTo,
});
return;
}
// Invoke Web Social Sign In flow
window.location.assign(redirectTo);
}, [invokeSocialSignInResult, options]);
// SignInWithSocial Callback
useEffect(() => {
if (signInWithSocialResult?.redirectTo) {
window.location.assign(signInWithSocialResult.redirectTo);
}
}, [signInWithSocialResult]);
// Social Sign-In Callback Handler
useEffect(() => {
if (!location.pathname.includes('/sign-in/callback') || !parameters.connector) {
@ -225,7 +213,7 @@ const useSocial = (options?: Options) => {
return;
}
signInWithSocialHandler(parameters.connector, state, code);
void signInWithSocialHandler(parameters.connector, state, code);
}, [parameters.connector, signInWithSocialHandler]);
// Monitor Native Error Message

View file

@ -4,7 +4,7 @@ type LogtoNativeSdkInfo = {
platform: 'ios' | 'android';
callbackLink: string;
getPostMessage: () => (data: { callbackUri?: string; redirectTo?: string }) => void;
supportedSocialConnectors: string[];
supportedSocialConnectorIds: string[];
};
declare const logtoNativeSdk: LogtoNativeSdkInfo | undefined;