2018-03-26 23:32:43 +02:00
// @flow
2018-11-26 02:21:25 +01:00
import * as ICONS from 'constants/icons' ;
2020-07-10 23:04:36 +02:00
import { SETTINGS } from 'lbry-redux' ;
2019-08-21 22:54:44 +02:00
import * as PAGES from 'constants/pages' ;
2020-08-11 22:32:03 +02:00
import React from 'react' ;
2019-06-17 22:32:38 +02:00
import { withRouter } from 'react-router' ;
2019-08-27 16:43:42 +02:00
import classnames from 'classnames' ;
2018-03-26 23:32:43 +02:00
import Button from 'component/button' ;
2017-12-21 22:08:54 +01:00
import WunderBar from 'component/wunderbar' ;
2019-06-17 22:32:38 +02:00
import Icon from 'component/common/icon' ;
import { Menu , MenuList , MenuButton , MenuItem } from '@reach/menu-button' ;
2020-01-25 22:04:48 +01:00
import NavigationButton from 'component/navigationButton' ;
2020-05-07 20:44:11 +02:00
import { LOGO _TITLE } from 'config' ;
2020-08-10 22:47:39 +02:00
import { useIsMobile } from 'effects/use-screensize' ;
import NotificationBubble from 'component/notificationBubble' ;
import NotificationHeaderButton from 'component/notificationHeaderButton' ;
2020-10-05 19:38:40 +02:00
import ChannelThumbnail from 'component/channelThumbnail' ;
2019-10-15 18:21:49 +02:00
// @if TARGET='app'
2020-05-18 06:26:30 +02:00
import { remote } from 'electron' ;
2019-10-15 18:21:49 +02:00
import { IS _MAC } from 'component/app/view' ;
// @endif
2019-10-09 18:34:18 +02:00
2018-03-26 23:32:43 +02:00
type Props = {
2020-09-29 22:15:35 +02:00
user : ? User ,
2018-03-26 23:32:43 +02:00
balance : string ,
2021-01-25 19:34:21 +01:00
balance : number ,
roundedBalance : string ,
roundedSpendableBalance : string ,
2020-01-22 05:37:33 +01:00
history : {
entities : { } [ ] ,
goBack : ( ) => void ,
goForward : ( ) => void ,
index : number ,
length : number ,
location : { pathname : string } ,
2021-03-03 19:50:16 +01:00
push : ( string ) => void ,
replace : ( string ) => void ,
2020-01-22 05:37:33 +01:00
} ,
2019-06-17 22:32:38 +02:00
currentTheme : string ,
automaticDarkModeEnabled : boolean ,
2020-09-04 17:02:30 +02:00
setClientSetting : ( string , boolean | string , ? boolean ) => void ,
2019-07-29 17:37:29 +02:00
hideBalance : boolean ,
2019-08-21 22:54:44 +02:00
email : ? string ,
2020-01-03 20:34:17 +01:00
authenticated : boolean ,
2019-10-28 15:04:37 +01:00
authHeader : boolean ,
2020-06-30 07:51:15 +02:00
backout : {
2020-07-10 23:04:36 +02:00
backLabel ? : string ,
backNavDefault ? : string ,
2020-06-30 07:51:15 +02:00
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
} ,
2019-11-01 17:19:28 +01:00
syncError : ? string ,
2020-04-13 21:16:07 +02:00
emailToVerify ? : string ,
2019-09-26 18:07:11 +02:00
signOut : ( ) => void ,
2020-03-14 00:00:22 +01:00
openSignOutModal : ( ) => void ,
2020-04-13 21:16:07 +02:00
clearEmailEntry : ( ) => void ,
clearPasswordEntry : ( ) => void ,
2020-07-10 23:04:36 +02:00
hasNavigated : boolean ,
2020-08-10 22:47:39 +02:00
sidebarOpen : boolean ,
2021-03-03 19:50:16 +01:00
setSidebarOpen : ( boolean ) => void ,
2020-08-10 22:47:39 +02:00
isAbsoluteSideNavHidden : boolean ,
2020-10-05 19:38:40 +02:00
hideCancel : boolean ,
2021-02-09 17:05:56 +01:00
activeChannelClaim : ? ChannelClaim ,
2018-03-26 23:32:43 +02:00
} ;
const Header = ( props : Props ) => {
2019-08-21 22:54:44 +02:00
const {
2021-01-25 19:34:21 +01:00
balance ,
2019-08-21 22:54:44 +02:00
roundedBalance ,
2021-01-25 19:34:21 +01:00
roundedSpendableBalance ,
2019-08-21 22:54:44 +02:00
history ,
setClientSetting ,
currentTheme ,
automaticDarkModeEnabled ,
hideBalance ,
email ,
2020-01-03 20:34:17 +01:00
authenticated ,
2019-10-28 15:04:37 +01:00
authHeader ,
2019-09-26 18:07:11 +02:00
signOut ,
2019-11-01 17:19:28 +01:00
syncError ,
2020-03-14 00:00:22 +01:00
openSignOutModal ,
2020-04-13 21:16:07 +02:00
clearEmailEntry ,
clearPasswordEntry ,
emailToVerify ,
2020-06-29 21:54:07 +02:00
backout ,
2020-08-10 22:47:39 +02:00
sidebarOpen ,
setSidebarOpen ,
isAbsoluteSideNavHidden ,
2020-09-29 22:15:35 +02:00
user ,
2020-10-05 19:38:40 +02:00
hideCancel ,
2021-02-09 17:05:56 +01:00
activeChannelClaim ,
2019-08-21 22:54:44 +02:00
} = props ;
2020-06-30 07:51:15 +02:00
const isMobile = useIsMobile ( ) ;
2019-11-22 22:13:00 +01:00
// on the verify page don't let anyone escape other than by closing the tab to keep session data consistent
2019-11-14 01:33:36 +01:00
const isVerifyPage = history . location . pathname . includes ( PAGES . AUTH _VERIFY ) ;
2020-04-13 21:16:07 +02:00
const isSignUpPage = history . location . pathname . includes ( PAGES . AUTH ) ;
const isSignInPage = history . location . pathname . includes ( PAGES . AUTH _SIGNIN ) ;
2020-07-07 11:47:52 +02:00
const isPwdResetPage = history . location . pathname . includes ( PAGES . AUTH _PASSWORD _RESET ) ;
2020-07-10 23:04:36 +02:00
const hasBackout = Boolean ( backout ) ;
2020-07-30 21:14:22 +02:00
const { backLabel , backNavDefault , title : backTitle , simpleTitle : simpleBackTitle } = backout || { } ;
2020-12-11 19:33:27 +01:00
const notificationsEnabled = ( user && user . experimental _ui ) || false ;
2021-02-09 17:05:56 +01:00
const activeChannelUrl = activeChannelClaim && activeChannelClaim . permanent _url ;
2019-11-01 17:19:28 +01:00
// Sign out if they click the "x" when they are on the password prompt
2020-01-20 17:47:03 +01:00
const authHeaderAction = syncError ? { onClick : signOut } : { navigate : '/' } ;
const homeButtonNavigationProps = isVerifyPage ? { } : authHeader ? authHeaderAction : { navigate : '/' } ;
2020-04-13 21:16:07 +02:00
const closeButtonNavigationProps = {
onClick : ( ) => {
clearEmailEntry ( ) ;
clearPasswordEntry ( ) ;
2020-08-27 05:16:47 +02:00
if ( syncError ) {
signOut ( ) ;
2020-04-13 21:16:07 +02:00
}
2020-08-27 05:16:47 +02:00
if ( isSignInPage && ! emailToVerify ) {
2020-04-13 21:16:07 +02:00
history . goBack ( ) ;
2020-08-27 05:16:47 +02:00
} else if ( isSignUpPage ) {
2020-07-07 11:47:52 +02:00
history . goBack ( ) ;
2020-08-27 05:16:47 +02:00
} else if ( isPwdResetPage ) {
history . goBack ( ) ;
} else {
history . push ( '/' ) ;
2020-07-07 11:47:52 +02:00
}
2020-04-13 21:16:07 +02:00
} ,
} ;
2018-03-26 23:32:43 +02:00
2020-07-10 23:04:36 +02:00
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 || ` / ` ) ;
}
}
}
2020-07-27 16:43:55 +02:00
React . useEffect ( ( ) => {
if ( hasBackout ) {
window . addEventListener ( 'popstate' , onBackout ) ;
return ( ) => window . removeEventListener ( 'popstate' , onBackout ) ;
}
} , [ hasBackout ] ) ;
2019-06-17 22:32:38 +02:00
function handleThemeToggle ( ) {
if ( automaticDarkModeEnabled ) {
setClientSetting ( SETTINGS . AUTOMATIC _DARK _MODE _ENABLED , false ) ;
}
if ( currentTheme === 'dark' ) {
2020-09-04 17:02:30 +02:00
setClientSetting ( SETTINGS . THEME , 'light' , true ) ;
2019-06-17 22:32:38 +02:00
} else {
2020-09-04 17:02:30 +02:00
setClientSetting ( SETTINGS . THEME , 'dark' , true ) ;
2019-06-17 22:32:38 +02:00
}
}
2018-03-26 23:32:43 +02:00
2020-11-10 06:21:04 +01:00
const loginButtons = (
< div className = "header__auth-buttons" >
< Button navigate = { ` / $ / ${ PAGES . AUTH _SIGNIN } ` } button = "link" label = { _ _ ( 'Log In' ) } className = "mobile-hidden" / >
< Button navigate = { ` / $ / ${ PAGES . AUTH } ` } button = "primary" label = { _ _ ( 'Sign Up' ) } / >
< / div >
) ;
2021-01-25 19:34:21 +01:00
type BalanceButtonProps = { className : string } ;
const BalanceButton = ( balanceButtonProps : BalanceButtonProps ) => (
< Button
title = {
balance > 0
? _ _ ( 'Immediately spendable: %spendable_balance%' , { spendable _balance : roundedSpendableBalance } )
: _ _ ( 'Your Wallet' )
}
navigate = { ` / $ / ${ PAGES . WALLET } ` }
2021-03-04 07:03:58 +01:00
className = { classnames ( balanceButtonProps . className , 'header__navigation-item--balance' ) }
2021-01-25 19:34:21 +01:00
label = { hideBalance || Number ( roundedBalance ) === 0 ? _ _ ( 'Your Wallet' ) : roundedBalance }
icon = { ICONS . LBC }
// @if TARGET='app'
2021-03-03 19:50:16 +01:00
onDoubleClick = { ( e ) => {
2021-01-25 19:34:21 +01:00
e . stopPropagation ( ) ;
} }
// @endif
/ >
) ;
2017-06-06 23:19:12 +02:00
return (
2019-10-15 18:21:49 +02:00
< header
className = { classnames ( 'header' , {
2019-10-28 15:04:37 +01:00
'header--minimal' : authHeader ,
2019-10-15 18:21:49 +02:00
// @if TARGET='app'
'header--mac' : IS _MAC ,
// @endif
} ) }
2020-05-18 06:26:30 +02:00
// @if TARGET='app'
2021-03-03 19:50:16 +01:00
onDoubleClick = { ( e ) => {
2020-05-18 06:26:30 +02:00
remote . getCurrentWindow ( ) . maximize ( ) ;
} }
// @endif
2019-10-15 18:21:49 +02:00
>
2019-06-11 20:10:58 +02:00
< div className = "header__contents" >
2020-06-29 21:54:07 +02:00
{ ! authHeader && backout ? (
2020-06-30 07:51:15 +02:00
< div className = "card__actions--between" >
2020-07-10 23:04:36 +02:00
< Button
onClick = { onBackout }
button = "link"
label = { ( backLabel && backLabel ) || _ _ ( 'Cancel' ) }
icon = { ICONS . ARROW _LEFT }
/ >
2020-09-03 22:05:38 +02:00
{ backTitle && < h1 className = "header__auth-title" > { isMobile ? simpleBackTitle || backTitle : backTitle } < / h1 > }
2020-12-04 01:10:23 +01:00
{ authenticated || ! IS _WEB ? (
2021-03-04 07:03:58 +01:00
< BalanceButton className = "header__navigation-item menu__title" / >
2020-11-10 06:21:04 +01:00
) : (
loginButtons
) }
2020-06-29 21:54:07 +02:00
< / div >
) : (
< >
< div className = "header__navigation" >
2020-08-11 22:32:03 +02:00
{ ! authHeader && (
< span style = { { position : 'relative' } } >
< Button
2020-12-15 22:13:08 +01:00
aria - label = {
sidebarOpen
? _ _ ( 'Close sidebar - hide channels you are following.' )
: _ _ ( 'Expand sidebar - view channels you are following.' )
}
2020-08-11 22:32:03 +02:00
className = "header__navigation-item menu__title header__navigation-item--icon"
icon = { ICONS . MENU }
onClick = { ( ) => setSidebarOpen ( ! sidebarOpen ) }
>
2020-09-29 22:15:35 +02:00
{ isAbsoluteSideNavHidden && isMobile && notificationsEnabled && < NotificationBubble / > }
2020-08-11 22:32:03 +02:00
< / Button >
< / span >
) }
2020-06-29 21:54:07 +02:00
< Button
2020-12-11 19:33:27 +01:00
className = "header__navigation-item header__navigation-item--lbry"
2020-07-09 00:31:23 +02:00
// @if TARGET='app'
label = { 'LBRY' }
// @endif
// @if TARGET='web'
label = { LOGO _TITLE } // eslint-disable-line
// @endif
2020-06-29 21:54:07 +02:00
icon = { ICONS . LBRY }
onClick = { ( ) => {
if ( history . location . pathname === '/' ) window . location . reload ( ) ;
} }
// @if TARGET='app'
2021-03-03 19:50:16 +01:00
onDoubleClick = { ( e ) => {
2020-06-29 21:54:07 +02:00
e . stopPropagation ( ) ;
} }
// @endif
{ ... homeButtonNavigationProps }
/ >
{ ! authHeader && (
2020-08-10 22:47:39 +02:00
< div className = "header__center" >
{ /* @if TARGET='app' */ }
{ ! authHeader && (
< div className = "header__buttons" >
< NavigationButton isBackward history = { history } / >
< NavigationButton isBackward = { false } history = { history } / >
< / div >
) }
{ /* @endif */ }
2019-09-30 23:48:30 +02:00
2020-08-10 22:47:39 +02:00
{ ! authHeader && < WunderBar / > }
2019-08-27 16:43:42 +02:00
2020-12-11 19:33:27 +01:00
< HeaderMenuButtons
authenticated = { authenticated }
notificationsEnabled = { notificationsEnabled }
history = { history }
handleThemeToggle = { handleThemeToggle }
currentTheme = { currentTheme }
/ >
2020-08-10 22:47:39 +02:00
< / div >
) }
< / div >
2020-08-11 22:32:03 +02:00
{ ! authHeader && ! backout ? (
2020-08-10 22:47:39 +02:00
< div className = { classnames ( 'header__menu' , { 'header__menu--with-balance' : ! IS _WEB || authenticated } ) } >
{ ( ! IS _WEB || authenticated ) && (
2021-03-04 07:03:58 +01:00
< BalanceButton className = "header__navigation-item menu__title mobile-hidden" / >
2020-06-29 21:54:07 +02:00
) }
2020-07-23 16:22:57 +02:00
2020-11-10 06:21:04 +01:00
{ IS _WEB && ! authenticated && loginButtons }
2021-03-04 07:03:58 +01:00
{ ( authenticated || ! IS _WEB ) && (
< Menu >
< MenuButton
aria - label = { _ _ ( 'Your account' ) }
title = { _ _ ( 'Your account' ) }
className = { classnames ( 'header__navigation-item' , {
'menu__title header__navigation-item--icon' : ! activeChannelUrl ,
'header__navigation-item--profile-pic' : activeChannelUrl ,
} ) }
// @if TARGET='app'
onDoubleClick = { ( e ) => {
e . stopPropagation ( ) ;
} }
// @endif
>
{ activeChannelUrl ? (
< ChannelThumbnail uri = { activeChannelUrl } / >
) : (
< Icon size = { 18 } icon = { ICONS . ACCOUNT } aria - hidden / >
) }
< / MenuButton >
< MenuList className = "menu__list--header" >
< MenuItem className = "menu__link" onSelect = { ( ) => history . push ( ` / $ / ${ PAGES . UPLOADS } ` ) } >
< Icon aria - hidden icon = { ICONS . PUBLISH } / >
{ _ _ ( 'Uploads' ) }
< / MenuItem >
< MenuItem className = "menu__link" onSelect = { ( ) => history . push ( ` / $ / ${ PAGES . CHANNELS } ` ) } >
< Icon aria - hidden icon = { ICONS . CHANNEL } / >
{ _ _ ( 'Channels' ) }
< / MenuItem >
< MenuItem className = "menu__link" onSelect = { ( ) => history . push ( ` / $ / ${ PAGES . CREATOR _DASHBOARD } ` ) } >
< Icon aria - hidden icon = { ICONS . ANALYTICS } / >
{ _ _ ( 'Creator Analytics' ) }
< / MenuItem >
< MenuItem className = "menu__link" onSelect = { ( ) => history . push ( ` / $ / ${ PAGES . REWARDS } ` ) } >
< Icon aria - hidden icon = { ICONS . REWARDS } / >
{ _ _ ( 'Rewards' ) }
< / MenuItem >
< MenuItem className = "menu__link" onSelect = { ( ) => history . push ( ` / $ / ${ PAGES . INVITE } ` ) } >
< Icon aria - hidden icon = { ICONS . INVITE } / >
{ _ _ ( 'Invites' ) }
< / MenuItem >
{ authenticated ? (
< MenuItem onSelect = { IS _WEB ? signOut : openSignOutModal } >
< div className = "menu__link" >
< Icon aria - hidden icon = { ICONS . SIGN _OUT } / >
{ _ _ ( 'Sign Out' ) }
< / div >
< span className = "menu__link-help" > { email } < / span >
< / MenuItem >
) : ! IS _WEB ? (
< >
< MenuItem className = "menu__link" onSelect = { ( ) => history . push ( ` / $ / ${ PAGES . AUTH } ` ) } >
< Icon aria - hidden icon = { ICONS . SIGN _UP } / >
{ _ _ ( 'Sign Up' ) }
< / MenuItem >
< MenuItem className = "menu__link" onSelect = { ( ) => history . push ( ` / $ / ${ PAGES . AUTH _SIGNIN } ` ) } >
< Icon aria - hidden icon = { ICONS . SIGN _IN } / >
{ _ _ ( 'Sign In' ) }
< / MenuItem >
< / >
) : null }
< / MenuList >
< / Menu >
) }
2020-04-13 21:16:07 +02:00
< / div >
2020-06-29 21:54:07 +02:00
) : (
2020-10-05 19:38:40 +02:00
! isVerifyPage &&
! hideCancel && (
2020-06-29 21:54:07 +02:00
< div className = "header__menu" >
{ /* Add an empty span here so we can use the same style as above */ }
{ /* This pushes the close button to the right side */ }
< span / >
2021-01-25 19:34:21 +01:00
< Button
title = { _ _ ( 'Go Back' ) }
button = "alt"
// className="button--header-close"
icon = { ICONS . REMOVE }
{ ... closeButtonNavigationProps }
// @if TARGET='app'
2021-03-03 19:50:16 +01:00
onDoubleClick = { ( e ) => {
2021-01-25 19:34:21 +01:00
e . stopPropagation ( ) ;
} }
// @endif
/ >
2020-06-29 21:54:07 +02:00
< / div >
)
2019-08-27 16:43:42 +02:00
) }
2020-06-29 21:54:07 +02:00
< / >
2019-08-27 16:43:42 +02:00
) }
2017-06-06 23:19:12 +02:00
< / div >
< / header >
) ;
2017-06-06 06:21:55 +02:00
} ;
2016-08-27 16:12:56 +02:00
2020-12-11 19:33:27 +01:00
type HeaderMenuButtonProps = {
authenticated : boolean ,
notificationsEnabled : boolean ,
2021-03-03 19:50:16 +01:00
history : { push : ( string ) => void } ,
handleThemeToggle : ( string ) => void ,
2020-12-11 19:33:27 +01:00
currentTheme : string ,
} ;
function HeaderMenuButtons ( props : HeaderMenuButtonProps ) {
2021-03-04 07:03:58 +01:00
const { authenticated , notificationsEnabled , history , handleThemeToggle , currentTheme } = props ;
2020-12-11 19:33:27 +01:00
return (
< div className = "header__buttons" >
{ ( authenticated || ! IS _WEB ) && (
< Menu >
< MenuButton
aria - label = { _ _ ( 'Publish a file, or create a channel' ) }
title = { _ _ ( 'Publish a file, or create a channel' ) }
className = "header__navigation-item menu__title header__navigation-item--icon mobile-hidden"
// @if TARGET='app'
2021-03-03 19:50:16 +01:00
onDoubleClick = { ( e ) => {
2020-12-11 19:33:27 +01:00
e . stopPropagation ( ) ;
} }
// @endif
>
< Icon size = { 18 } icon = { ICONS . PUBLISH } aria - hidden / >
< / MenuButton >
< MenuList className = "menu__list--header" >
< MenuItem className = "menu__link" onSelect = { ( ) => history . push ( ` / $ / ${ PAGES . UPLOAD } ` ) } >
< Icon aria - hidden icon = { ICONS . PUBLISH } / >
{ _ _ ( 'Upload' ) }
< / MenuItem >
< MenuItem className = "menu__link" onSelect = { ( ) => history . push ( ` / $ / ${ PAGES . CHANNEL _NEW } ` ) } >
< Icon aria - hidden icon = { ICONS . CHANNEL } / >
{ _ _ ( 'New Channel' ) }
< / MenuItem >
< / MenuList >
< / Menu >
) }
{ notificationsEnabled && < NotificationHeaderButton / > }
< Menu >
< MenuButton
aria - label = { _ _ ( 'Settings' ) }
title = { _ _ ( 'Settings' ) }
className = "header__navigation-item menu__title header__navigation-item--icon mobile-hidden"
// @if TARGET='app'
2021-03-03 19:50:16 +01:00
onDoubleClick = { ( e ) => {
2020-12-11 19:33:27 +01:00
e . stopPropagation ( ) ;
} }
// @endif
>
< Icon size = { 18 } icon = { ICONS . SETTINGS } aria - hidden / >
< / MenuButton >
< MenuList className = "menu__list--header" >
< MenuItem className = "menu__link" onSelect = { ( ) => history . push ( ` / $ / ${ PAGES . SETTINGS } ` ) } >
< Icon aria - hidden tootlip icon = { ICONS . SETTINGS } / >
{ _ _ ( 'Settings' ) }
< / MenuItem >
< MenuItem className = "menu__link" onSelect = { ( ) => history . push ( ` / $ / ${ PAGES . HELP } ` ) } >
< Icon aria - hidden icon = { ICONS . HELP } / >
{ _ _ ( 'Help' ) }
< / MenuItem >
< MenuItem className = "menu__link" onSelect = { handleThemeToggle } >
< Icon icon = { currentTheme === 'light' ? ICONS . DARK : ICONS . LIGHT } / >
{ currentTheme === 'light' ? _ _ ( 'Dark' ) : _ _ ( 'Light' ) }
< / MenuItem >
< / MenuList >
< / Menu >
< / div >
) ;
}
2019-06-17 22:32:38 +02:00
export default withRouter ( Header ) ;