2016-11-22 21:19:08 +01:00
import React from 'react' ;
2017-04-23 11:56:50 +02:00
import lbryuri from 'lbryuri.js' ;
import { Icon , CreditAmount } from 'component/common.js' ;
2017-04-07 07:15:22 +02:00
import Link from 'component/link' ;
2016-11-22 21:19:08 +01:00
2017-04-22 15:17:01 +02:00
let Header = React . createClass ( {
2017-04-27 05:54:53 +02:00
_balanceSubscribeId : null ,
2017-04-27 15:17:18 +02:00
_isMounted : false ,
2017-04-27 05:54:53 +02:00
2017-05-01 05:38:14 +02:00
propTypes : {
onSearch : React . PropTypes . func . isRequired ,
onSubmit : React . PropTypes . func . isRequired
} ,
2016-08-08 00:13:17 +02:00
getInitialState : function ( ) {
return {
2017-04-27 05:54:53 +02:00
balance : 0
2016-08-08 00:13:17 +02:00
} ;
} ,
2016-08-08 04:48:45 +02:00
componentDidMount : function ( ) {
2017-04-27 15:17:18 +02:00
this . _isMounted = true ;
2017-04-27 05:54:53 +02:00
this . _balanceSubscribeId = lbry . balanceSubscribe ( ( balance ) => {
2017-04-27 15:17:18 +02:00
if ( this . _isMounted ) {
this . setState ( { balance : balance } ) ;
}
2017-04-27 05:54:53 +02:00
} ) ;
2016-08-08 02:20:14 +02:00
} ,
2016-08-08 04:48:45 +02:00
componentWillUnmount : function ( ) {
2017-04-27 15:17:18 +02:00
this . _isMounted = false ;
2017-04-27 05:54:53 +02:00
if ( this . _balanceSubscribeId ) {
lbry . balanceUnsubscribe ( this . _balanceSubscribeId )
2016-08-08 04:48:45 +02:00
}
2016-08-08 02:20:14 +02:00
} ,
2017-04-27 05:54:53 +02:00
render : function ( ) {
2017-04-27 15:17:18 +02:00
return < header id = "header" >
2017-04-27 05:54:53 +02:00
< div className = "header__item" >
2017-05-01 02:15:21 +02:00
< Link onClick = { ( ) => { lbry . back ( ) } } button = "alt button--flat" icon = "icon-arrow-left" / >
2017-04-27 05:54:53 +02:00
< / div >
< div className = "header__item" >
< Link href = "?discover" button = "alt button--flat" icon = "icon-home" / >
< / div >
< div className = "header__item header__item--wunderbar" >
2017-05-01 02:15:21 +02:00
< WunderBar address = { this . props . address } icon = { this . props . wunderBarIcon }
2017-05-01 05:38:14 +02:00
onSearch = { this . props . onSearch } onSubmit = { this . props . onSubmit } viewingPage = { this . props . viewingPage } / >
2017-04-27 05:54:53 +02:00
< / div >
< div className = "header__item" >
< Link href = "?wallet" button = "text" icon = "icon-bank" label = { lbry . formatCredits ( this . state . balance , 1 ) } > < / Link >
< / div >
< div className = "header__item" >
< Link button = "primary button--flat" href = "?publish" icon = "icon-upload" label = "Publish" / >
< / div >
< div className = "header__item" >
< Link button = "alt button--flat" href = "?downloaded" icon = "icon-folder" / >
< / div >
< div className = "header__item" >
< Link button = "alt button--flat" href = "?settings" icon = "icon-gear" / >
< / div >
< / header >
}
} ) ;
2017-05-02 00:31:13 +02:00
class WunderBar extends React . PureComponent {
static propTypes = {
2017-05-01 05:38:14 +02:00
onSearch : React . PropTypes . func . isRequired ,
onSubmit : React . PropTypes . func . isRequired
2017-05-02 00:31:13 +02:00
}
2017-05-01 02:15:21 +02:00
2017-05-02 00:31:13 +02:00
constructor ( props ) {
super ( props ) ;
this . _userTypingTimer = null ;
this . _input = null ;
this . _stateBeforeSearch = null ;
this . _resetOnNextBlur = true ;
this . onChange = this . onChange . bind ( this ) ;
this . onFocus = this . onFocus . bind ( this ) ;
this . onBlur = this . onBlur . bind ( this ) ;
this . onKeyPress = this . onKeyPress . bind ( this ) ;
this . onReceiveRef = this . onReceiveRef . bind ( this ) ;
this . state = {
2017-04-27 05:54:53 +02:00
address : this . props . address ,
icon : this . props . icon
} ;
2017-05-02 00:31:13 +02:00
}
componentWillUnmount ( ) {
2017-04-27 05:54:53 +02:00
if ( this . userTypingTimer ) {
clearTimeout ( this . _userTypingTimer ) ;
}
2017-05-02 00:31:13 +02:00
}
onChange ( event ) {
2016-08-08 02:57:12 +02:00
2017-04-27 05:54:53 +02:00
if ( this . _userTypingTimer )
2016-08-08 02:57:12 +02:00
{
2017-04-27 05:54:53 +02:00
clearTimeout ( this . _userTypingTimer ) ;
2016-08-08 02:57:12 +02:00
}
2017-04-27 05:54:53 +02:00
this . setState ( { address : event . target . value } )
2017-05-01 02:15:21 +02:00
let searchTerm = event . target . value ;
2017-04-27 05:54:53 +02:00
this . _userTypingTimer = setTimeout ( ( ) => {
2017-05-01 05:38:14 +02:00
this . _resetOnNextBlur = false ;
2016-08-08 04:48:45 +02:00
this . props . onSearch ( searchTerm ) ;
} , 800 ) ; // 800ms delay, tweak for faster/slower
2017-05-02 00:31:13 +02:00
}
2017-04-27 05:54:53 +02:00
componentWillReceiveProps ( nextProps ) {
2017-05-01 05:38:14 +02:00
if ( nextProps . viewingPage !== this . props . viewingPage || nextProps . address != this . props . address ) {
2017-04-27 05:54:53 +02:00
this . setState ( { address : nextProps . address , icon : nextProps . icon } ) ;
}
2017-05-02 00:31:13 +02:00
}
onFocus ( ) {
2017-04-27 05:54:53 +02:00
this . _stateBeforeSearch = this . state ;
let newState = {
2017-04-27 15:17:18 +02:00
icon : "icon-search" ,
isActive : true
2017-04-27 05:54:53 +02:00
}
2017-05-02 00:31:13 +02:00
2017-04-27 05:54:53 +02:00
this . _focusPending = true ;
2017-05-01 02:15:21 +02:00
//below is hacking, improved when we have proper routing
if ( ! this . state . address . startsWith ( 'lbry://' ) && this . state . icon !== "icon-search" ) //onFocus, if they are not on an exact URL or a search page, clear the bar
2017-04-27 05:54:53 +02:00
{
2017-04-30 10:06:50 +02:00
newState . address = '' ;
2017-04-27 05:54:53 +02:00
}
this . setState ( newState ) ;
2017-05-02 00:31:13 +02:00
}
onBlur ( ) {
2017-05-01 05:38:14 +02:00
let commonState = { isActive : false } ;
if ( this . _resetOnNextBlur ) {
this . setState ( Object . assign ( { } , this . _stateBeforeSearch , commonState ) ) ;
this . _input . value = this . state . address ;
} else {
this . _resetOnNextBlur = true ;
this . _stateBeforeSearch = this . state ;
this . setState ( commonState ) ;
}
2017-05-02 00:31:13 +02:00
}
componentDidUpdate ( ) {
2017-04-27 05:54:53 +02:00
this . _input . value = this . state . address ;
if ( this . _input && this . _focusPending ) {
this . _input . select ( ) ;
this . _focusPending = false ;
}
2017-05-02 00:31:13 +02:00
}
onKeyPress ( event ) {
2017-05-01 05:38:14 +02:00
if ( event . charCode == 13 && this . _input . value ) {
2017-05-02 00:31:13 +02:00
let uri = null ,
method = "onSubmit" ;
2017-05-01 21:59:40 +02:00
this . _resetOnNextBlur = false ;
2017-05-02 00:31:13 +02:00
clearTimeout ( this . _userTypingTimer ) ;
try {
uri = lbryuri . normalize ( this . _input . value ) ;
this . setState ( { value : uri } ) ;
} catch ( error ) { //then it's not a valid URL, so let's search
uri = this . _input . value ;
method = "onSearch" ;
}
this . props [ method ] ( uri ) ;
2017-05-01 21:59:40 +02:00
this . _input . blur ( ) ;
2017-05-01 05:38:14 +02:00
}
2017-05-02 00:31:13 +02:00
}
onReceiveRef ( ref ) {
2017-04-27 05:54:53 +02:00
this . _input = ref ;
2017-05-02 00:31:13 +02:00
}
render ( ) {
2017-04-30 10:06:50 +02:00
return (
< div className = { 'wunderbar' + ( this . state . isActive ? ' wunderbar--active' : '' ) } >
{ this . state . icon ? < Icon fixed icon = { this . state . icon } / > : '' }
< input className = "wunderbar__input" type = "search" placeholder = "Type a LBRY address or search term"
ref = { this . onReceiveRef }
onFocus = { this . onFocus }
onBlur = { this . onBlur }
onChange = { this . onChange }
2017-05-01 05:38:14 +02:00
onKeyPress = { this . onKeyPress }
2017-04-30 10:06:50 +02:00
value = { this . state . address }
placeholder = "Find movies, music, games, and more" / >
2017-04-27 05:54:53 +02:00
< / div >
2017-04-30 10:06:50 +02:00
) ;
2016-08-07 22:10:44 +02:00
}
2017-05-02 00:31:13 +02:00
}
2016-08-27 16:12:56 +02:00
2016-11-22 21:19:08 +01:00
export default Header ;