/** @jsx createElement */ import { createElement, Component, createRef } from 'preact'; import { useCallback } from 'preact/hooks'; import { IntlShape, FormattedMessage, defineMessages, useIntl } from 'react-intl'; import { AuthProvider, Theme, User } from '@app/common/types'; import { PROVIDER_NAMES, IS_STORAGE_AVAILABLE } from '@app/common/constants'; import { getHandleClickProps } from '@app/common/accessibility'; import { Button } from '@app/components/button'; import { Dropdown, DropdownItem } from '@app/components/dropdown'; import debounce from '@app/utils/debounce'; import { ProviderState } from '@app/store/provider/reducers'; import { StaticStore } from '@app/common/static_store'; import { useSelector, useDispatch } from 'react-redux'; import { StoreState } from '@app/store'; import useTheme from '@app/hooks/useTheme'; import { logIn } from '@app/store/user/actions'; import { AnonymousLoginForm } from './__anonymous-login-form'; import { EmailLoginFormConnected, EmailLoginFormRef } from './__email-login-form'; import styles from './auth.module.pcss'; interface Props { intl: IntlShape; theme: Theme; onSignIn(provider: AuthProvider): any; // eslint-disable-line user: User | null; provider: ProviderState; } interface State { threshold: number; } class Auth extends Component { emailLoginRef = createRef(); singInMessageAndSortWidth = 255; state = { threshold: 3, }; componentWillMount() { this.resizeHandler(); window.addEventListener('resize', this.resizeHandler); } componentWillUnmount() { window.removeEventListener('resize', this.resizeHandler); } resizeHandler = debounce(() => { this.setState({ threshold: Math.max(3, Math.round((window.innerWidth - this.singInMessageAndSortWidth) / 80)), }); }, 100); onEmailTitleClick = () => { this.emailLoginRef.current && this.emailLoginRef.current.focus(); }; onEmailSignIn = (token: string) => { return this.props.onSignIn({ name: 'email', token }); }; handleOAuthLogin = async (e: MouseEvent | KeyboardEvent) => { const name = (e.target as HTMLButtonElement).dataset.provider! as AuthProvider['name']; this.props.onSignIn({ name } as AuthProvider); }; handleAnonymousLoginFormSubmut = async (username: string) => { this.props.onSignIn({ name: 'anonymous', username }); }; renderOther = (providers: AuthProvider['name'][]) => { const other = this.props.intl.formatMessage(authPanelMessages.otherProvider); return ( {providers.map(provider => ( {this.renderProvider(provider)} ))} ); }; renderProvider = (provider: AuthProvider['name']) => { if (provider === 'anonymous') { const anonymous = this.props.intl.formatMessage(authPanelMessages.anonymousProvider); return ( ); } if (provider === 'email') { return ( ); } return ( ); }; render({ intl }: Props, { threshold }: State) { if (!IS_STORAGE_AVAILABLE) return null; const sortedProviders = ((providers): typeof providers => { if (!this.props.provider.name) return providers; const lastProviderIndex = providers.indexOf(this.props.provider.name as typeof providers[0]); if (lastProviderIndex < 1) return providers; return [ this.props.provider.name as typeof providers[0], ...providers.slice(0, lastProviderIndex), ...providers.slice(lastProviderIndex + 1), ]; })(StaticStore.config.auth_providers); const isAboveThreshold = sortedProviders.length > threshold; const or = intl.formatMessage(authPanelMessages.orProvider); return (
{' '} {!isAboveThreshold && sortedProviders.map((provider, i) => { const comma = i === 0 ? '' : i === sortedProviders.length - 1 ? ` ${or} ` : ', '; return ( {comma} {this.renderProvider(provider)} ); })} {isAboveThreshold && sortedProviders.slice(0, threshold - 1).map((provider, i) => { const comma = i === 0 ? '' : ', '; return ( {comma} {this.renderProvider(provider)} ); })} {isAboveThreshold && ( {` ${or} `} {this.renderOther(sortedProviders.slice(threshold - 1))} )}
); } } const authPanelMessages = defineMessages({ otherProvider: { id: 'authPanel.other-provider', defaultMessage: 'Other', }, anonymousProvider: { id: 'authPanel.anonymous-provider', defaultMessage: 'Anonymous', }, orProvider: { id: 'authPanel.or-provider', defaultMessage: 'or', }, }); export default function() { const dispatch = useDispatch(); const provider = useSelector(store => store.provider); const user = useSelector(store => store.user); const theme = useTheme(); const intl = useIntl(); const handleSignin = useCallback((provider: AuthProvider) => dispatch(logIn(provider)), []); return ; }