lbry-desktop/ui/js/component/header/view.jsx

194 lines
5.5 KiB
React
Raw Normal View History

2016-11-22 21:19:08 +01:00
import React from 'react';
import lbryuri from '../lbryuri.js';
import {Icon, CreditAmount} from './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({
_balanceSubscribeId: null,
2017-04-27 15:17:18 +02:00
_isMounted: false,
propTypes: {
onSearch: React.PropTypes.func.isRequired,
onSubmit: React.PropTypes.func.isRequired
},
getInitialState: function() {
return {
balance: 0
};
},
componentDidMount: function() {
2017-04-27 15:17:18 +02:00
this._isMounted = true;
this._balanceSubscribeId = lbry.balanceSubscribe((balance) => {
2017-04-27 15:17:18 +02:00
if (this._isMounted) {
this.setState({balance: balance});
}
});
},
componentWillUnmount: function() {
2017-04-27 15:17:18 +02:00
this._isMounted = false;
if (this._balanceSubscribeId) {
lbry.balanceUnsubscribe(this._balanceSubscribeId)
}
},
render: function() {
2017-04-27 15:17:18 +02:00
return <header id="header">
<div className="header__item">
<Link onClick={() => { lbry.back() }} button="alt button--flat" icon="icon-arrow-left" />
</div>
<div className="header__item">
<Link href="?discover" button="alt button--flat" icon="icon-home" />
</div>
<div className="header__item header__item--wunderbar">
<WunderBar address={this.props.address} icon={this.props.wunderBarIcon}
onSearch={this.props.onSearch} onSubmit={this.props.onSubmit} viewingPage={this.props.viewingPage} />
</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 = {
onSearch: React.PropTypes.func.isRequired,
onSubmit: React.PropTypes.func.isRequired
2017-05-02 00:31:13 +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 = {
address: this.props.address,
icon: this.props.icon
};
2017-05-02 00:31:13 +02:00
}
componentWillUnmount() {
if (this.userTypingTimer) {
clearTimeout(this._userTypingTimer);
}
2017-05-02 00:31:13 +02:00
}
onChange(event) {
2016-08-08 02:57:12 +02:00
if (this._userTypingTimer)
2016-08-08 02:57:12 +02:00
{
clearTimeout(this._userTypingTimer);
2016-08-08 02:57:12 +02:00
}
this.setState({ address: event.target.value })
let searchTerm = event.target.value;
this._userTypingTimer = setTimeout(() => {
this._resetOnNextBlur = false;
this.props.onSearch(searchTerm);
}, 800); // 800ms delay, tweak for faster/slower
2017-05-02 00:31:13 +02:00
}
componentWillReceiveProps(nextProps) {
if (nextProps.viewingPage !== this.props.viewingPage || nextProps.address != this.props.address) {
this.setState({ address: nextProps.address, icon: nextProps.icon });
}
2017-05-02 00:31:13 +02:00
}
onFocus() {
this._stateBeforeSearch = this.state;
let newState = {
2017-04-27 15:17:18 +02:00
icon: "icon-search",
isActive: true
}
2017-05-02 00:31:13 +02:00
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
{
2017-04-30 10:06:50 +02:00
newState.address = '';
}
this.setState(newState);
2017-05-02 00:31:13 +02:00
}
onBlur() {
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() {
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) {
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-02 00:31:13 +02:00
}
onReceiveRef(ref) {
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}
onKeyPress={this.onKeyPress}
2017-04-30 10:06:50 +02:00
value={this.state.address}
placeholder="Find movies, music, games, and more" />
</div>
2017-04-30 10:06:50 +02:00
);
}
2017-05-02 00:31:13 +02:00
}
2016-11-22 21:19:08 +01:00
export default Header;