// @flow import { ENABLE_NO_SOURCE_CLAIMS, CHANNEL_STAKED_LEVEL_LIVESTREAM, ENABLE_UI_NOTIFICATIONS } from 'config'; import * as ICONS from 'constants/icons'; import { SETTINGS } from 'lbry-redux'; import * as PAGES from 'constants/pages'; import React, { useCallback } from 'react'; import { withRouter } from 'react-router'; import classnames from 'classnames'; import Button from 'component/button'; import WunderBar from 'component/wunderbar'; import Icon from 'component/common/icon'; import { Menu, MenuList, MenuButton, MenuItem } from '@reach/menu-button'; import NavigationButton from 'component/navigationButton'; import { useIsMobile } from 'effects/use-screensize'; import NotificationBubble from 'component/notificationBubble'; import NotificationHeaderButton from 'component/notificationHeaderButton'; import ChannelThumbnail from 'component/channelThumbnail'; import SkipNavigationButton from 'component/skipNavigationButton'; import keycloak from 'util/keycloak'; import Logo from 'component/logo'; // @if TARGET='app' import { remote } from 'electron'; import { IS_MAC } from 'component/app/view'; // @endif type Props = { user: ?User, balance: string, balance: number, roundedBalance: string, roundedSpendableBalance: string, history: { entities: {}[], goBack: () => void, goForward: () => void, index: number, length: number, location: { pathname: string }, push: (string) => void, replace: (string) => void, }, currentTheme: string, automaticDarkModeEnabled: boolean, setClientSetting: (string, boolean | string, ?boolean) => void, hideBalance: boolean, email: ?string, authenticated: boolean, authHeader: boolean, 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 }, syncError: ?string, emailToVerify?: string, signOut: () => void, openSignOutModal: () => void, clearEmailEntry: () => void, clearPasswordEntry: () => void, hasNavigated: boolean, sidebarOpen: boolean, setSidebarOpen: (boolean) => void, isAbsoluteSideNavHidden: boolean, hideCancel: boolean, activeChannelClaim: ?ChannelClaim, activeChannelStakedLevel: number, }; const Header = (props: Props) => { const { balance, roundedBalance, roundedSpendableBalance, history, setClientSetting, currentTheme, automaticDarkModeEnabled, hideBalance, email, authenticated, authHeader, signOut, syncError, openSignOutModal, clearEmailEntry, clearPasswordEntry, emailToVerify, backout, sidebarOpen, setSidebarOpen, isAbsoluteSideNavHidden, hideCancel, user, activeChannelClaim, activeChannelStakedLevel, } = props; 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 = history.location.pathname.includes(PAGES.AUTH_VERIFY); const isSignUpPage = history.location.pathname.includes(PAGES.AUTH); const isSignInPage = history.location.pathname.includes(PAGES.AUTH_SIGNIN); const isPwdResetPage = history.location.pathname.includes(PAGES.AUTH_PASSWORD_RESET); const hasBackout = Boolean(backout); const { backLabel, backNavDefault, title: backTitle, simpleTitle: simpleBackTitle } = backout || {}; const notificationsEnabled = ENABLE_UI_NOTIFICATIONS || (user && user.experimental_ui); const livestreamEnabled = Boolean( ENABLE_NO_SOURCE_CLAIMS && user && !user.odysee_live_disabled && (activeChannelStakedLevel >= CHANNEL_STAKED_LEVEL_LIVESTREAM || user.odysee_live_enabled) ); const activeChannelUrl = activeChannelClaim && activeChannelClaim.permanent_url; // Sign out if they click the "x" when they are on the password prompt const authHeaderAction = syncError ? { onClick: signOut } : { navigate: '/' }; const homeButtonNavigationProps = isVerifyPage ? {} : authHeader ? authHeaderAction : { navigate: '/' }; const closeButtonNavigationProps = { onClick: () => { clearEmailEntry(); clearPasswordEntry(); if (syncError) { signOut(); } if (isSignInPage && !emailToVerify) { history.goBack(); } else if (isSignUpPage) { history.goBack(); } else if (isPwdResetPage) { history.goBack(); } else { history.push('/'); } }, }; function onBackout(e) { const { history, hasNavigated } = props; const { goBack, replace } = history; window.removeEventListener('popstate', onBackout); if (e.type !== 'popstate') { // if not initiated by pop (back button) if (hasNavigated && !backNavDefault) { goBack(); } else { replace(backNavDefault || `/`); } } } React.useEffect(() => { if (hasBackout) { window.addEventListener('popstate', onBackout); return () => window.removeEventListener('popstate', onBackout); } }, [hasBackout]); function handleThemeToggle() { if (automaticDarkModeEnabled) { setClientSetting(SETTINGS.AUTOMATIC_DARK_MODE_ENABLED, false); } if (currentTheme === 'dark') { setClientSetting(SETTINGS.THEME, 'light', true); } else { setClientSetting(SETTINGS.THEME, 'dark', true); } } const login = useCallback(() => { keycloak && keycloak.login().then((x) => console.log('cb', x)); }, [keycloak]); const loginButtons = (
); type BalanceButtonProps = { className: string }; const BalanceButton = (balanceButtonProps: BalanceButtonProps) => ( )} {!authHeader && (
{/* @if TARGET='app' */} {!authHeader && (
)} {/* @endif */} {!authHeader && }
)} {!authHeader && !backout ? (
{(!IS_WEB || authenticated) && ( )} {IS_WEB && !authenticated && loginButtons} {(authenticated || !IS_WEB) && ( { e.stopPropagation(); }} // @endif > {activeChannelUrl ? ( ) : ( )} history.push(`/$/${PAGES.UPLOADS}`)}> {__('Uploads')} history.push(`/$/${PAGES.CHANNELS}`)}> {__('Channels')} history.push(`/$/${PAGES.CREATOR_DASHBOARD}`)}> {__('Creator Analytics')} history.push(`/$/${PAGES.REWARDS}`)}> {__('Rewards')} history.push(`/$/${PAGES.INVITE}`)}> {__('Invites')} {authenticated ? (
{__('Sign Out')}
{email}
) : !IS_WEB ? ( <> history.push(`/$/${PAGES.AUTH}`)}> {__('Sign Up')} history.push(`/$/${PAGES.AUTH_SIGNIN}`)}> {__('Sign In')} ) : null}
)}
) : ( !isVerifyPage && !hideCancel && (
{/* Add an empty span here so we can use the same style as above */} {/* This pushes the close button to the right side */}
) )} )} ); }; type HeaderMenuButtonProps = { authenticated: boolean, notificationsEnabled: boolean, history: { push: (string) => void }, handleThemeToggle: (string) => void, currentTheme: string, livestreamEnabled: boolean, }; function HeaderMenuButtons(props: HeaderMenuButtonProps) { const { authenticated, notificationsEnabled, history, handleThemeToggle, currentTheme, livestreamEnabled } = props; return (
{(authenticated || !IS_WEB) && ( { e.stopPropagation(); }} // @endif > history.push(`/$/${PAGES.UPLOAD}`)}> {__('Upload')} history.push(`/$/${PAGES.CHANNEL_NEW}`)}> {__('New Channel')} {/* @if TARGET='web' */} history.push(`/$/${PAGES.YOUTUBE_SYNC}`)}> {__('Sync YouTube Channel')} {/* @endif */} {livestreamEnabled && ( history.push(`/$/${PAGES.LIVESTREAM}`)}> {__('Go Live')} )} )} {notificationsEnabled && } { e.stopPropagation(); }} // @endif > history.push(`/$/${PAGES.SETTINGS}`)}> {__('Settings')} history.push(`/$/${PAGES.HELP}`)}> {__('Help')} {currentTheme === 'light' ? __('Dark') : __('Light')}
); } export default withRouter(Header);