import { PureComponent } from 'react'; import Box from '@mui/material/Box'; import Button from '@mui/material/Button'; import GoogleIcon from '@mui/icons-material/Google'; import { enqueueSnackbar } from 'notistack'; import { notifyErrorMessage } from '../utils/notify'; import authAutomat from '../automats/authAutomat'; import { StorageManagerContext } from '../api/storageManagerContext'; import { abortGoogleSignIn, FEDCM_BLOCKED_MESSAGE, GoogleSignInBlockedError, GoogleSignInCancelledError, logError, requestGoogleIdToken, } from '../auth/googleSignIn'; class LoginPage extends PureComponent { static contextType = StorageManagerContext; constructor(props) { super(props); this.state = { ...authAutomat.state, busy: false }; this.handleLogin = this.handleLogin.bind(this); } componentDidMount() { this.unsubscribe = authAutomat.subscribe(this, ['status', 'googleClientId']); } componentWillUnmount() { this.unsubscribe?.(); } async handleLogin() { const { googleClientId } = this.state; abortGoogleSignIn(); try { const idToken = await requestGoogleIdToken(googleClientId, { onFedcmBlocked: () => { enqueueSnackbar(FEDCM_BLOCKED_MESSAGE, { variant: 'warning', autoHideDuration: 12000, }); }, }); this.setState({ busy: true }); await authAutomat.actions.loginWithGoogle(idToken); await this.context.updateAuthMe(); } catch (err) { if (err instanceof GoogleSignInCancelledError) return; logError('[login] Google sign-in failed', { message: err?.message, name: err?.name, code: err?.code, status: err?.status, cause: err?.cause, stack: err?.stack, clientId: googleClientId, origin: window.location.origin, href: window.location.href, dashHost: window.__dashHost ? { isDashNative: window.__dashHost.isDashNative, googleSignIn: window.__dashHost.googleSignIn, } : null, error: err, }); if (err instanceof GoogleSignInBlockedError) { enqueueSnackbar(err.message, { variant: 'warning', autoHideDuration: 12000 }); return; } const detail = [err?.message || String(err), err?.code, err?.status] .filter(Boolean) .join(' · '); notifyErrorMessage(`Login failed: ${detail}`); } finally { this.setState({ busy: false }); } } render() { const { busy, status, googleClientId } = this.state; const loading = status === 'loading'; const ready = Boolean(googleClientId); return ( ); } } export default LoginPage;