2017-05-04 05:44:08 +02:00
import React from 'react' ;
import lbryuri from 'lbryuri.js' ;
import { Icon } from 'component/common.js' ;
class WunderBar extends React . PureComponent {
2017-05-12 01:28:43 +02:00
static TYPING _TIMEOUT = 800
2017-05-04 05:44:08 +02:00
static propTypes = {
onSearch : React . PropTypes . func . isRequired ,
onSubmit : React . PropTypes . func . isRequired
}
constructor ( props ) {
super ( props ) ;
this . _userTypingTimer = null ;
2017-05-12 01:28:43 +02:00
this . _isSearchDispatchPending = false ;
2017-05-04 05:44:08 +02:00
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 = {
address : this . props . address ,
icon : this . props . icon
} ;
}
componentWillUnmount ( ) {
if ( this . userTypingTimer ) {
clearTimeout ( this . _userTypingTimer ) ;
}
}
onChange ( event ) {
if ( this . _userTypingTimer )
{
clearTimeout ( this . _userTypingTimer ) ;
}
this . setState ( { address : event . target . value } )
2017-05-12 01:28:43 +02:00
this . _isSearchDispatchPending = true ;
2017-05-10 03:33:13 +02:00
let searchQuery = event . target . value ;
2017-05-04 05:44:08 +02:00
this . _userTypingTimer = setTimeout ( ( ) => {
2017-05-10 03:33:13 +02:00
const hasQuery = searchQuery . length === 0 ;
this . _resetOnNextBlur = hasQuery ;
2017-05-12 01:28:43 +02:00
this . _isSearchDispatchPending = false ;
2017-05-10 03:33:13 +02:00
if ( searchQuery ) {
this . props . onSearch ( searchQuery ) ;
}
2017-05-12 01:28:43 +02:00
} , WunderBar . TYPING _TIMEOUT ) ; // 800ms delay, tweak for faster/slower
2017-05-04 05:44:08 +02:00
}
componentWillReceiveProps ( nextProps ) {
if ( nextProps . viewingPage !== this . props . viewingPage || nextProps . address != this . props . address ) {
this . setState ( { address : nextProps . address , icon : nextProps . icon } ) ;
}
}
onFocus ( ) {
this . _stateBeforeSearch = this . state ;
let newState = {
icon : "icon-search" ,
isActive : true
}
this . _focusPending = true ;
//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
{
newState . address = '' ;
}
this . setState ( newState ) ;
}
onBlur ( ) {
2017-05-12 01:28:43 +02:00
if ( this . _isSearchDispatchPending ) {
setTimeout ( ( ) => {
this . onBlur ( ) ;
} , WunderBar . TYPING _TIMEOUT + 1 )
2017-05-04 05:44:08 +02:00
} else {
2017-05-12 01:28:43 +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-04 05:44:08 +02:00
}
}
componentDidUpdate ( ) {
2017-05-12 20:36:44 +02:00
if ( this . _input ) {
const start = this . _input . selectionStart ,
end = this . _input . selectionEnd ;
this . _input . value = this . state . address ; //this causes cursor to go to end of input
this . _input . setSelectionRange ( start , end ) ;
if ( this . _focusPending ) {
this . _input . select ( ) ;
this . _focusPending = false ;
}
2017-05-04 05:44:08 +02:00
}
}
onKeyPress ( event ) {
if ( event . charCode == 13 && this . _input . value ) {
let uri = null ,
method = "onSubmit" ;
this . _resetOnNextBlur = false ;
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 ) ;
this . _input . blur ( ) ;
}
}
onReceiveRef ( ref ) {
this . _input = ref ;
}
render ( ) {
return (
< div className = { 'wunderbar' + ( this . state . isActive ? ' wunderbar--active' : '' ) } >
{ this . state . icon ? < Icon fixed icon = { this . state . icon } / > : '' }
2017-05-07 14:50:32 +02:00
< input className = "wunderbar__input" type = "search"
2017-05-04 05:44:08 +02:00
ref = { this . onReceiveRef }
onFocus = { this . onFocus }
onBlur = { this . onBlur }
onChange = { this . onChange }
onKeyPress = { this . onKeyPress }
value = { this . state . address }
placeholder = "Find movies, music, games, and more" / >
< / div >
) ;
}
}
export default WunderBar ;