import {useCallback, useState} from 'react'; import {toast} from '../../ui/toast/toast'; import {useDisconnectSocial} from './disconnect-social'; import {useTrans} from '../../i18n/use-trans'; import {getBootstrapData} from '../../core/bootstrap-data/use-backend-bootstrap-data'; import {useBootstrapData} from '../../core/bootstrap-data/bootstrap-data-context'; export type SocialService = 'google' | 'twitter' | 'facebook' | 'envato'; interface SocialMessageEvent { status?: 'SUCCESS' | 'ALREADY_LOGGED_IN' | 'REQUEST_PASSWORD' | 'ERROR'; callbackData?: { bootstrapData?: string; errorMessage?: string; }; } export function useSocialLogin() { const {trans} = useTrans(); const {setBootstrapData} = useBootstrapData(); const disconnectSocial = useDisconnectSocial(); const [requestingPassword, setIsRequestingPassword] = useState(false); const handleSocialLoginCallback = useCallback( (e: SocialMessageEvent) => { const {status, callbackData} = e; if (!status) return; switch (status.toUpperCase()) { case 'SUCCESS': if (callbackData?.bootstrapData) { setBootstrapData(callbackData.bootstrapData); } return e; case 'REQUEST_PASSWORD': setIsRequestingPassword(true); return e; case 'ERROR': const message: string = callbackData?.errorMessage || trans({ message: 'An error occurred. Please try again later', }); toast.danger(message); return e; default: return e; } }, [trans, setBootstrapData], ); return { requestingPassword, setIsRequestingPassword, loginWithSocial: async (serviceName: SocialService) => { const event = await openNewSocialAuthWindow( `secure/auth/social/${serviceName}/login`, ); return handleSocialLoginCallback(event); }, connectSocial: async (serviceNameOrUrl: SocialService | string) => { const url = serviceNameOrUrl.includes('/') ? serviceNameOrUrl : `secure/auth/social/${serviceNameOrUrl}/connect`; const event = await openNewSocialAuthWindow(url); return handleSocialLoginCallback(event); }, disconnectSocial, }; } const windowHeight = 550; const windowWidth = 650; let win: Window | null; function openNewSocialAuthWindow(url: string): Promise { const left = window.screen.width / 2 - windowWidth / 2; const top = window.screen.height / 2 - windowHeight / 2; return new Promise(resolve => { win = window.open( url, 'Authenticate Account', `menubar=0, location=0, toolbar=0, titlebar=0, status=0, scrollbars=1, width=${windowWidth}, height=${windowHeight}, left=${left}, top=${top}`, ); const messageListener = (e: MessageEvent) => { const baseUrl = getBootstrapData().settings.base_url; if (e.data.type === 'social-auth' && baseUrl.indexOf(e.origin) > -1) { resolve(e.data); window.removeEventListener('message', messageListener); } }; window.addEventListener('message', messageListener); // if user closes social login callback without interacting with it, remove message event listener const timer = setInterval(() => { if (!win || win.closed) { clearInterval(timer); resolve({}); window.removeEventListener('message', messageListener); } }, 1000); }); }