63a2430a7c
## Issue 1709 - If you sign in while reporting, you end up in the homepage ## Notes The other option is to just make `<Header>` always redirect back to where it came from using the full path. But existing code elsewhere seem to always trim off any params (e.g. `location.search`, `location.hash`) when doing redirects. So, ended up making it generic and let the caller decide where to redirect (and with what params).
302 lines
9.8 KiB
JavaScript
302 lines
9.8 KiB
JavaScript
// @flow
|
|
import 'scss/component/_header.scss';
|
|
|
|
import { formatCredits } from 'util/format-credits';
|
|
import { useIsMobile } from 'effects/use-screensize';
|
|
import { withRouter } from 'react-router';
|
|
import * as ICONS from 'constants/icons';
|
|
import * as PAGES from 'constants/pages';
|
|
import Button from 'component/button';
|
|
import classnames from 'classnames';
|
|
import HeaderMenuButtons from 'component/headerMenuButtons';
|
|
import HeaderProfileMenuButton from 'component/headerProfileMenuButton';
|
|
import Logo from 'component/logo';
|
|
import NotificationBubble from 'component/notificationBubble';
|
|
import React from 'react';
|
|
import Skeleton from '@mui/material/Skeleton';
|
|
import SkipNavigationButton from 'component/skipNavigationButton';
|
|
import Tooltip from 'component/common/tooltip';
|
|
import WunderBar from 'component/wunderbar';
|
|
|
|
type Props = {
|
|
authenticated: boolean,
|
|
authHeader: boolean,
|
|
authRedirect?: string, // Redirects to '/' by default.
|
|
backout: {
|
|
backLabel?: string,
|
|
backNavDefault?: string,
|
|
title: string,
|
|
simpleTitle: string, // Just use the same value as `title` if `title` is already short (~< 10 chars), unless you have a better idea for title overlfow on mobile
|
|
},
|
|
balance: number,
|
|
emailToVerify?: string,
|
|
hasNavigated: boolean,
|
|
hideBalance: boolean,
|
|
hideCancel: boolean,
|
|
history: {
|
|
goBack: () => void,
|
|
location: { pathname: string },
|
|
push: (string) => void,
|
|
replace: (string) => void,
|
|
},
|
|
isAbsoluteSideNavHidden: boolean,
|
|
sidebarOpen: boolean,
|
|
syncError: ?string,
|
|
totalBalance?: number,
|
|
user: ?User,
|
|
prefsReady: boolean,
|
|
doClearClaimSearch: () => void,
|
|
clearEmailEntry: () => void,
|
|
clearPasswordEntry: () => void,
|
|
openChangelog: ({}) => void,
|
|
setSidebarOpen: (boolean) => void,
|
|
signOut: () => void,
|
|
};
|
|
|
|
const Header = (props: Props) => {
|
|
const {
|
|
authenticated,
|
|
authHeader,
|
|
authRedirect,
|
|
backout,
|
|
balance,
|
|
emailToVerify,
|
|
hideBalance,
|
|
hideCancel,
|
|
history,
|
|
isAbsoluteSideNavHidden,
|
|
sidebarOpen,
|
|
syncError,
|
|
totalBalance,
|
|
user,
|
|
prefsReady,
|
|
doClearClaimSearch,
|
|
clearEmailEntry,
|
|
clearPasswordEntry,
|
|
openChangelog,
|
|
setSidebarOpen,
|
|
signOut,
|
|
} = props;
|
|
|
|
const {
|
|
location: { pathname },
|
|
goBack,
|
|
push,
|
|
} = history;
|
|
|
|
const isMobile = useIsMobile();
|
|
|
|
// on the verify page don't let anyone escape other than by closing the tab to keep session data consistent
|
|
const isVerifyPage = pathname.includes(PAGES.AUTH_VERIFY);
|
|
const isSignUpPage = pathname.includes(PAGES.AUTH);
|
|
const isSignInPage = pathname.includes(PAGES.AUTH_SIGNIN);
|
|
const isPwdResetPage = pathname.includes(PAGES.AUTH_PASSWORD_RESET);
|
|
const iYTSyncPage = pathname.includes(PAGES.YOUTUBE_SYNC);
|
|
|
|
// For pages that allow for "backing out", shows a backout option instead of the Home logo
|
|
const canBackout = Boolean(backout);
|
|
const { backLabel, backNavDefault, title: backTitle, simpleTitle: simpleBackTitle } = backout || {};
|
|
|
|
const balanceLoading = totalBalance === undefined;
|
|
const roundedSpendableBalance = formatCredits(balance, 2, true);
|
|
const roundedTotalBalance = formatCredits(totalBalance, 2, true);
|
|
|
|
// Sign out if they click the "x" when they are on the password prompt
|
|
const authHeaderAction = syncError && { onClick: signOut };
|
|
const homeButtonNavigationProps = (isVerifyPage && {}) || (authHeader && authHeaderAction) || { navigate: '/' };
|
|
const sidebarLabel = sidebarOpen
|
|
? __('Close sidebar - hide channels you are following.')
|
|
: __('Expand sidebar - view channels you are following.');
|
|
|
|
const authRedirectParam = authRedirect ? `?redirect=${authRedirect}` : '';
|
|
|
|
const onBackout = React.useCallback(
|
|
(e: any) => {
|
|
const { hasNavigated } = props;
|
|
const { replace } = history;
|
|
|
|
window.removeEventListener('popstate', onBackout);
|
|
|
|
if (e.type !== 'popstate') {
|
|
// if not initiated by pop (back button)
|
|
if (hasNavigated && !backNavDefault) {
|
|
goBack();
|
|
} else {
|
|
replace(backNavDefault || `/`);
|
|
}
|
|
}
|
|
},
|
|
[backNavDefault, goBack, history, props]
|
|
);
|
|
|
|
React.useEffect(() => {
|
|
if (canBackout) {
|
|
window.addEventListener('popstate', onBackout);
|
|
return () => window.removeEventListener('popstate', onBackout);
|
|
}
|
|
}, [canBackout, onBackout]);
|
|
|
|
const userButtons = (hideWallet?: boolean, hideProfile?: boolean) => (
|
|
<div className="header__menu--right">
|
|
{isMobile && !authHeader && !canBackout && <WunderBar />}
|
|
|
|
{authenticated ? (
|
|
<>
|
|
{!hideWallet && (
|
|
<Tooltip
|
|
title={
|
|
balance > 0
|
|
? __('Immediately spendable: %spendable_balance%', { spendable_balance: roundedSpendableBalance })
|
|
: __('Your Wallet')
|
|
}
|
|
>
|
|
<div>
|
|
{balanceLoading ? (
|
|
<Skeleton variant="text" animation="wave" className="header__navigationItem--balanceLoading" />
|
|
) : (
|
|
<Button
|
|
navigate={`/$/${PAGES.WALLET}`}
|
|
className="button--file-action header__navigationItem--balance"
|
|
label={
|
|
hideBalance || Number(roundedTotalBalance) === 0 || !prefsReady
|
|
? __(isMobile ? 'Wallet' : 'Your Wallet')
|
|
: roundedTotalBalance
|
|
}
|
|
icon={ICONS.LBC}
|
|
/>
|
|
)}
|
|
</div>
|
|
</Tooltip>
|
|
)}
|
|
|
|
{!hideProfile && <HeaderProfileMenuButton />}
|
|
</>
|
|
) : !isMobile ? (
|
|
<div className="header__authButtons">
|
|
<Button
|
|
navigate={`/$/${PAGES.AUTH_SIGNIN}${authRedirectParam}`}
|
|
button="link"
|
|
label={__('Log In')}
|
|
disabled={user === null}
|
|
/>
|
|
<Button
|
|
navigate={`/$/${PAGES.AUTH}${authRedirectParam}`}
|
|
button="primary"
|
|
label={__('Sign Up')}
|
|
disabled={user === null}
|
|
/>
|
|
</div>
|
|
) : (
|
|
<HeaderProfileMenuButton />
|
|
)}
|
|
</div>
|
|
);
|
|
|
|
return (
|
|
<header className={classnames('header', { 'header--minimal': authHeader })}>
|
|
{!authHeader && canBackout ? (
|
|
<div className="card__actions--between header__contents">
|
|
<div className="header__menu--left">
|
|
<Button onClick={onBackout} button="link" label={backLabel || __('Cancel')} icon={ICONS.ARROW_LEFT} />
|
|
</div>
|
|
|
|
{backTitle && <h1 className="header__authTitle">{(isMobile && simpleBackTitle) || backTitle}</h1>}
|
|
|
|
{userButtons(false, isMobile)}
|
|
</div>
|
|
) : (
|
|
<>
|
|
<div className="header__navigation">
|
|
<div className="header__menu--left">
|
|
<SkipNavigationButton />
|
|
|
|
{!authHeader && (
|
|
<span style={{ position: 'relative' }}>
|
|
<Button
|
|
aria-label={sidebarLabel}
|
|
className="header__navigationItem--icon button-rotate"
|
|
icon={ICONS.MENU}
|
|
aria-expanded={sidebarOpen}
|
|
onClick={() => setSidebarOpen(!sidebarOpen)}
|
|
/>
|
|
{isAbsoluteSideNavHidden && isMobile && <NotificationBubble />}
|
|
</span>
|
|
)}
|
|
|
|
<Button
|
|
aria-label={__('Home')}
|
|
className="header__navigationItem--logo"
|
|
onClick={() => {
|
|
if (pathname === '/') {
|
|
window.scrollTo({ top: 0, left: 0, behavior: 'smooth' });
|
|
doClearClaimSearch();
|
|
}
|
|
}}
|
|
{...homeButtonNavigationProps}
|
|
>
|
|
<Logo />
|
|
</Button>
|
|
|
|
{/* @if process.env.DEV_CHANGELOG */}
|
|
{history.location.pathname === '/' && (
|
|
<Button
|
|
title="Changelog"
|
|
className="badge--alert"
|
|
label="Changelog"
|
|
icon={ICONS.FEEDBACK}
|
|
onClick={() =>
|
|
openChangelog({
|
|
title: __('Changelog'),
|
|
subtitle: __('Warning: this is a test instance.'),
|
|
body: <p style={{ whiteSpace: 'pre-wrap' }}>{process.env.DEV_CHANGELOG}</p>,
|
|
onConfirm: (closeModal) => closeModal(),
|
|
hideCancel: true,
|
|
})
|
|
}
|
|
/>
|
|
)}
|
|
{/* @endif */}
|
|
</div>
|
|
|
|
{!authHeader && !isMobile && (
|
|
<div className="header__center">
|
|
<WunderBar />
|
|
<HeaderMenuButtons />
|
|
</div>
|
|
)}
|
|
|
|
{!authHeader && !canBackout
|
|
? userButtons(isMobile)
|
|
: !isVerifyPage &&
|
|
!hideCancel && (
|
|
<div className="header__menu--right">
|
|
<Button
|
|
title={__('Go Back')}
|
|
button="alt"
|
|
// className="button--header-close"
|
|
icon={ICONS.REMOVE}
|
|
onClick={() => {
|
|
if (!iYTSyncPage && !isPwdResetPage) {
|
|
clearEmailEntry();
|
|
clearPasswordEntry();
|
|
}
|
|
|
|
if (syncError) signOut();
|
|
|
|
if ((isSignInPage && !emailToVerify) || isSignUpPage || isPwdResetPage || iYTSyncPage) {
|
|
goBack();
|
|
} else {
|
|
push('/');
|
|
}
|
|
}}
|
|
/>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</>
|
|
)}
|
|
</header>
|
|
);
|
|
};
|
|
|
|
export default withRouter(Header);
|