Refactor wunderbar index/view and encode search query

This commit is contained in:
ioancole 2020-09-11 01:11:31 +08:00 committed by Sean Yesmunt
parent c80b28ade9
commit 4add1f7200
2 changed files with 67 additions and 62 deletions

View file

@ -7,7 +7,6 @@ import { doToast } from 'redux/actions/notifications';
import analytics from 'analytics'; import analytics from 'analytics';
import Wunderbar from './view'; import Wunderbar from './view';
import { withRouter } from 'react-router-dom'; import { withRouter } from 'react-router-dom';
import { formatLbryUrlForWeb } from 'util/url';
const select = state => ({ const select = state => ({
suggestions: selectSearchSuggestions(state), suggestions: selectSearchSuggestions(state),
@ -17,15 +16,14 @@ const select = state => ({
}); });
const perform = (dispatch, ownProps) => ({ const perform = (dispatch, ownProps) => ({
onSearch: query => { doSearch: query => {
ownProps.history.push({ pathname: `/$/search`, search: `?q=${encodeURIComponent(query)}` }); let encodedQuery = encodeURIComponent(query);
ownProps.history.push({ pathname: `/$/search`, search: `?q=${encodedQuery}` });
dispatch(doUpdateSearchQuery(query)); dispatch(doUpdateSearchQuery(query));
analytics.apiLogSearch(); analytics.apiLogSearch();
}, },
onSubmit: uri => { navigateToUri: uri => {
const path = formatLbryUrlForWeb(uri); ownProps.history.push(uri);
ownProps.history.push(path);
dispatch(doUpdateSearchQuery(''));
}, },
updateSearchQuery: query => dispatch(doUpdateSearchQuery(query)), updateSearchQuery: query => dispatch(doUpdateSearchQuery(query)),
doShowSnackBar: message => dispatch(doToast({ isError: true, message })), doShowSnackBar: message => dispatch(doToast({ isError: true, message })),

View file

@ -5,25 +5,30 @@ import * as PAGES from 'constants/pages';
import * as ICONS from 'constants/icons'; import * as ICONS from 'constants/icons';
import React from 'react'; import React from 'react';
import classnames from 'classnames'; import classnames from 'classnames';
import { normalizeURI, isURIValid } from 'lbry-redux';
import { withRouter } from 'react-router'; import { withRouter } from 'react-router';
import Icon from 'component/common/icon'; import Icon from 'component/common/icon';
import Autocomplete from './internal/autocomplete'; import Autocomplete from './internal/autocomplete';
import Tag from 'component/tag'; import Tag from 'component/tag';
import { isURIValid, normalizeURI } from 'lbry-redux';
const L_KEY_CODE = 76; import { formatLbryUrlForWeb } from '../../util/url';
const ESC_KEY_CODE = 27;
const WEB_DEV_PREFIX = `${URL_DEV}/`; const WEB_DEV_PREFIX = `${URL_DEV}/`;
const WEB_LOCAL_PREFIX = `${URL_LOCAL}/`; const WEB_LOCAL_PREFIX = `${URL_LOCAL}/`;
const WEB_PROD_PREFIX = `${URL}/`; const WEB_PROD_PREFIX = `${URL}/`;
const SEARCH_PREFIX = `$/${PAGES.SEARCH}q=`; const SEARCH_PREFIX = `$/${PAGES.SEARCH}q=`;
const INVALID_URL_ERROR = "Invalid LBRY URL entered. Only A-Z, a-z, 0-9, and '-' allowed.";
const L_KEY_CODE = 76;
const ESC_KEY_CODE = 27;
type Props = { type Props = {
searchQuery: ?string, searchQuery: ?string,
updateSearchQuery: string => void, updateSearchQuery: string => void,
onSearch: string => void, onSearch: string => void,
onSubmit: string => void, onSubmit: string => void,
wunderbarValue: ?string,
navigateToUri: string => void,
doSearch: string => void,
suggestions: Array<string>, suggestions: Array<string>,
doFocus: () => void, doFocus: () => void,
doBlur: () => void, doBlur: () => void,
@ -99,68 +104,70 @@ class WunderBar extends React.PureComponent<Props, State> {
updateSearchQuery(value); updateSearchQuery(value);
} }
handleSubmit(value: string, suggestion?: { value: string, type: string }) { onSubmitWebUri(uri: string) {
const { onSubmit, onSearch, doShowSnackBar, history } = this.props;
let query = value.trim();
this.input && this.input.blur();
const showSnackError = () => {
doShowSnackBar('Invalid LBRY URL entered. Only A-Z, a-z, 0-9, and "-" allowed.');
};
// Allow copying a lbry.tv url and pasting it into the search bar // Allow copying a lbry.tv url and pasting it into the search bar
const includesLbryTvProd = query.includes(WEB_PROD_PREFIX); const { doSearch, navigateToUri, updateSearchQuery } = this.props;
const includesLbryTvLocal = query.includes(WEB_LOCAL_PREFIX);
const includesLbryTvDev = query.includes(WEB_DEV_PREFIX);
const wasCopiedFromWeb = includesLbryTvDev || includesLbryTvLocal || includesLbryTvProd;
if (wasCopiedFromWeb) {
if (includesLbryTvDev) {
query = query.slice(WEB_DEV_PREFIX.length);
} else if (includesLbryTvLocal) {
query = query.slice(WEB_LOCAL_PREFIX.length);
} else {
query = query.slice(WEB_PROD_PREFIX.length);
}
const slashPosition = uri.indexOf('/');
let query = uri.slice(slashPosition);
query = query.replace(/:/g, '#'); query = query.replace(/:/g, '#');
if (query.includes(SEARCH_PREFIX)) { if (query.includes(SEARCH_PREFIX)) {
query = query.slice(SEARCH_PREFIX.length); query = query.slice(SEARCH_PREFIX.length);
onSearch(query); doSearch(query);
return;
} else { } else {
query = `lbry://${query}`; // TODO - double check this code path
onSubmit(query); let path = `lbry://${query}`;
return; const uri = formatLbryUrlForWeb(path);
navigateToUri(uri);
updateSearchQuery('');
} }
} }
// User selected a suggestion onClickSuggestion(query: string, suggestion: { value: string, type: string }): void {
if (suggestion) { const { navigateToUri, doSearch, doShowSnackBar } = this.props;
if (suggestion.type === SEARCH_TYPES.SEARCH) { if (suggestion.type === SEARCH_TYPES.SEARCH) {
onSearch(query); doSearch(query);
} else if (suggestion.type === SEARCH_TYPES.TAG) { } else if (suggestion.type === SEARCH_TYPES.TAG) {
history.push(`/$/${PAGES.DISCOVER}?t=${suggestion.value}`); const encodedSuggestion = encodeURIComponent(suggestion.value);
const uri = `/$/${PAGES.DISCOVER}?t=${encodedSuggestion}`;
navigateToUri(uri);
} else if (isURIValid(query)) { } else if (isURIValid(query)) {
const uri = normalizeURI(query); let uri = normalizeURI(query);
onSubmit(uri); uri = formatLbryUrlForWeb(uri);
navigateToUri(uri);
} else { } else {
showSnackError(); doShowSnackBar(INVALID_URL_ERROR);
}
} }
return; onSubmitRawString(st: string): void {
} const { navigateToUri, doSearch, doShowSnackBar } = this.props;
// Currently no suggestion is highlighted. The user may have started // Currently no suggestion is highlighted. The user may have started
// typing, then lost focus and came back later on the same page // typing, then lost focus and came back later on the same page
try { try {
if (isURIValid(query)) { if (isURIValid(st)) {
const uri = normalizeURI(query); const uri = normalizeURI(st);
onSubmit(uri); navigateToUri(uri);
} else { } else {
showSnackError(); doShowSnackBar(INVALID_URL_ERROR);
} }
} catch (e) { } catch (e) {
onSearch(query); doSearch(st);
}
}
handleSubmit(value: string, suggestion?: { value: string, type: string }) {
let query = value.trim();
this.input && this.input.blur();
const wasCopiedFromWeb = [WEB_DEV_PREFIX, WEB_LOCAL_PREFIX, WEB_PROD_PREFIX].some(p => query.includes(p));
if (wasCopiedFromWeb) {
this.onSubmitWebUri(query);
} else if (suggestion) {
this.onClickSuggestion(query, suggestion);
} else {
this.onSubmitRawString(query);
} }
} }