2018-03-26 23:32:43 +02:00
|
|
|
// @flow
|
2017-12-21 22:08:54 +01:00
|
|
|
import React from 'react';
|
2018-03-26 23:32:43 +02:00
|
|
|
import classnames from 'classnames';
|
2018-06-19 19:59:55 +02:00
|
|
|
import { normalizeURI, SEARCH_TYPES } from 'lbry-redux';
|
2018-03-26 23:32:43 +02:00
|
|
|
import Icon from 'component/common/icon';
|
2018-01-09 02:15:44 +01:00
|
|
|
import { parseQueryParams } from 'util/query_params';
|
2018-03-26 23:32:43 +02:00
|
|
|
import * as icons from 'constants/icons';
|
2018-03-27 23:25:23 +02:00
|
|
|
import Autocomplete from './internal/autocomplete';
|
2018-03-26 23:32:43 +02:00
|
|
|
|
|
|
|
type Props = {
|
|
|
|
updateSearchQuery: string => void,
|
|
|
|
onSearch: string => void,
|
|
|
|
onSubmit: (string, {}) => void,
|
|
|
|
wunderbarValue: ?string,
|
|
|
|
suggestions: Array<string>,
|
2018-05-16 20:32:25 +02:00
|
|
|
doFocus: () => void,
|
|
|
|
doBlur: () => void,
|
2018-06-19 05:36:15 +02:00
|
|
|
resultCount: number,
|
2018-03-26 23:32:43 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
class WunderBar extends React.PureComponent<Props> {
|
|
|
|
constructor(props: Props) {
|
2018-01-09 02:15:44 +01:00
|
|
|
super(props);
|
2017-05-04 05:44:08 +02:00
|
|
|
|
2018-03-26 23:32:43 +02:00
|
|
|
(this: any).handleSubmit = this.handleSubmit.bind(this);
|
|
|
|
(this: any).handleChange = this.handleChange.bind(this);
|
|
|
|
this.input = undefined;
|
2018-01-09 02:15:44 +01:00
|
|
|
}
|
|
|
|
|
2018-03-26 23:32:43 +02:00
|
|
|
getSuggestionIcon = (type: string) => {
|
|
|
|
switch (type) {
|
|
|
|
case 'file':
|
2018-06-19 19:59:55 +02:00
|
|
|
return icons.LOCAL;
|
2018-03-26 23:32:43 +02:00
|
|
|
case 'channel':
|
|
|
|
return icons.AT_SIGN;
|
|
|
|
default:
|
|
|
|
return icons.SEARCH;
|
2018-01-09 02:15:44 +01:00
|
|
|
}
|
2018-03-26 23:32:43 +02:00
|
|
|
};
|
2017-05-04 05:44:08 +02:00
|
|
|
|
2018-03-26 23:32:43 +02:00
|
|
|
handleChange(e: SyntheticInputEvent<*>) {
|
|
|
|
const { updateSearchQuery } = this.props;
|
|
|
|
const { value } = e.target;
|
2018-01-09 02:15:44 +01:00
|
|
|
|
2018-03-26 23:32:43 +02:00
|
|
|
updateSearchQuery(value);
|
|
|
|
}
|
2018-01-09 02:15:44 +01:00
|
|
|
|
2018-03-26 23:32:43 +02:00
|
|
|
handleSubmit(value: string, suggestion?: { value: string, type: string }) {
|
2018-06-19 05:36:15 +02:00
|
|
|
const { onSubmit, onSearch, resultCount } = this.props;
|
2018-03-26 23:32:43 +02:00
|
|
|
const query = value.trim();
|
|
|
|
const getParams = () => {
|
|
|
|
const parts = query.split('?');
|
2018-01-09 02:15:44 +01:00
|
|
|
|
2018-03-26 23:32:43 +02:00
|
|
|
let extraParams = {};
|
|
|
|
if (parts.length > 0) {
|
|
|
|
extraParams = parseQueryParams(parts.join(''));
|
2018-01-09 02:15:44 +01:00
|
|
|
}
|
2017-05-04 05:44:08 +02:00
|
|
|
|
2018-03-26 23:32:43 +02:00
|
|
|
return extraParams;
|
2018-01-09 02:15:44 +01:00
|
|
|
};
|
|
|
|
|
2018-03-26 23:32:43 +02:00
|
|
|
// User selected a suggestion
|
|
|
|
if (suggestion) {
|
|
|
|
if (suggestion.type === 'search') {
|
2018-06-19 05:36:15 +02:00
|
|
|
onSearch(query, resultCount);
|
2018-01-09 02:15:44 +01:00
|
|
|
} else {
|
2018-03-26 23:32:43 +02:00
|
|
|
const params = getParams();
|
|
|
|
const uri = normalizeURI(query);
|
|
|
|
onSubmit(uri, params);
|
2018-01-09 02:15:44 +01:00
|
|
|
}
|
2017-05-04 05:44:08 +02:00
|
|
|
|
2018-03-26 23:32:43 +02:00
|
|
|
return;
|
2017-05-04 05:44:08 +02:00
|
|
|
}
|
2018-01-09 02:15:44 +01:00
|
|
|
|
2018-03-26 23:32:43 +02:00
|
|
|
// Currently no suggestion is highlighted. The user may have started
|
|
|
|
// typing, then lost focus and came back later on the same page
|
|
|
|
try {
|
|
|
|
const uri = normalizeURI(query);
|
|
|
|
const params = getParams();
|
|
|
|
onSubmit(uri, params);
|
|
|
|
} catch (e) {
|
2018-06-19 05:36:15 +02:00
|
|
|
onSearch(query, resultCount);
|
2018-01-04 06:05:20 +01:00
|
|
|
}
|
2017-05-04 05:44:08 +02:00
|
|
|
}
|
|
|
|
|
2018-03-26 23:32:43 +02:00
|
|
|
input: ?HTMLInputElement;
|
2018-01-04 06:05:20 +01:00
|
|
|
|
2018-01-09 02:15:44 +01:00
|
|
|
render() {
|
2018-05-16 20:32:25 +02:00
|
|
|
const { wunderbarValue, suggestions, doFocus, doBlur } = this.props;
|
2018-03-26 23:32:43 +02:00
|
|
|
|
2017-05-04 05:44:08 +02:00
|
|
|
return (
|
2018-03-26 23:32:43 +02:00
|
|
|
<div className="wunderbar">
|
|
|
|
<Icon icon={icons.SEARCH} />
|
|
|
|
<Autocomplete
|
|
|
|
autoHighlight
|
2018-06-21 00:58:55 +02:00
|
|
|
wrapperStyle={{ flex: 1, position: 'relative' }}
|
2018-03-26 23:32:43 +02:00
|
|
|
value={wunderbarValue || ''}
|
|
|
|
items={suggestions}
|
|
|
|
getItemValue={item => item.value}
|
|
|
|
onChange={this.handleChange}
|
|
|
|
onSelect={this.handleSubmit}
|
2018-05-16 20:32:25 +02:00
|
|
|
inputProps={{
|
|
|
|
onFocus: doFocus,
|
|
|
|
onBlur: doBlur,
|
|
|
|
}}
|
2018-03-26 23:32:43 +02:00
|
|
|
renderInput={props => (
|
|
|
|
<input
|
|
|
|
{...props}
|
|
|
|
className="wunderbar__input"
|
2018-06-10 20:32:47 +02:00
|
|
|
placeholder="Enter LBRY URL here or search for videos, music, games and more"
|
2018-03-26 23:32:43 +02:00
|
|
|
/>
|
|
|
|
)}
|
2018-06-19 19:59:55 +02:00
|
|
|
renderItem={({ value, type }, isHighlighted) => (
|
2018-03-26 23:32:43 +02:00
|
|
|
<div
|
|
|
|
key={value}
|
|
|
|
className={classnames('wunderbar__suggestion', {
|
|
|
|
'wunderbar__active-suggestion': isHighlighted,
|
|
|
|
})}
|
|
|
|
>
|
|
|
|
<Icon icon={this.getSuggestionIcon(type)} />
|
2018-06-19 19:59:55 +02:00
|
|
|
<span className="wunderbar__suggestion-label">{value}</span>
|
|
|
|
{isHighlighted && (
|
2018-03-26 23:32:43 +02:00
|
|
|
<span className="wunderbar__suggestion-label--action">
|
|
|
|
{'- '}
|
2018-06-19 19:59:55 +02:00
|
|
|
{type === SEARCH_TYPES.SEARCH && __('Search')}
|
|
|
|
{type === SEARCH_TYPES.CHANNEL && __('View channel')}
|
|
|
|
{type === SEARCH_TYPES.FILE && __('View file')}
|
2018-03-26 23:32:43 +02:00
|
|
|
</span>
|
|
|
|
)}
|
|
|
|
</div>
|
|
|
|
)}
|
2017-06-06 23:19:12 +02:00
|
|
|
/>
|
2017-05-04 05:44:08 +02:00
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
export default WunderBar;
|