Better search

This commit is contained in:
6ea86b96 2017-05-07 19:50:32 +07:00
parent b19e356a06
commit 4b5187bc7f
No known key found for this signature in database
GPG key ID: B282D183E4931E8F
9 changed files with 127 additions and 42 deletions

View file

@ -3,9 +3,6 @@ import lbry from 'lbry'
import lbryio from 'lbryio'
import lbryuri from 'lbryuri'
import lighthouse from 'lighthouse'
import {
selectSearchQuery,
} from 'selectors/search'
import {
doResolveUri,
} from 'actions/content'
@ -14,6 +11,7 @@ import {
} from 'actions/app'
import {
selectCurrentPage,
selectSearchQuery,
} from 'selectors/app'
export function doSearchContent(query) {
@ -33,7 +31,9 @@ export function doSearchContent(query) {
data: { query }
})
if(page != 'discover' && query != undefined) dispatch(doNavigate('discover'))
if(page != 'search' && query != undefined) {
dispatch(doNavigate('search', { query: query }))
}
lighthouse.search(query).then(results => {
results.forEach(result => {
@ -75,3 +75,49 @@ export function doDeactivateSearch() {
type: types.DEACTIVATE_SEARCH,
}
}
export function doSetSearchQuery(query) {
return function(dispatch, getState) {
const state = getState()
dispatch(doNavigate('/search', { query }))
}
}
export function doSearch() {
return function(dispatch, getState) {
const state = getState()
const page = selectCurrentPage(state)
const query = selectSearchQuery(state)
if (!query) {
return dispatch({
type: types.SEARCH_CANCELLED,
})
}
dispatch({
type: types.SEARCH_STARTED,
data: { query }
})
lighthouse.search(query).then(results => {
results.forEach(result => {
const uri = lbryuri.build({
channelName: result.channel_name,
contentName: result.name,
claimId: result.channel_id || result.claim_id,
})
dispatch(doResolveUri(uri))
})
dispatch({
type: types.SEARCH_COMPLETED,
data: {
query,
results,
}
})
})
}
}

View file

@ -23,10 +23,12 @@ const select = (state) => ({
const perform = (dispatch) => ({
// navigate: (path) => dispatch(doNavigate(path)),
onSearch: (query) => dispatch(doSearchContent(query)),
onSubmit: (query) => dispatch(doSearchContent(query)),
activateSearch: () => dispatch(doActivateSearch()),
deactivateSearch: () => setTimeout(() => { dispatch(doDeactivateSearch()) }, 50),
// onSearch: (query) => dispatch(doSearchContent(query)),
// onSubmit: (query) => dispatch(doSearchContent(query)),
// activateSearch: () => dispatch(doActivateSearch()),
// deactivateSearch: () => setTimeout(() => { dispatch(doDeactivateSearch()) }, 50),
onSearch: (query) => dispatch(doNavigate('/search', { query })),
onSubmit: (query) => console.debug('you submitted'),
})
export default connect(select, perform)(Wunderbar)

View file

@ -61,8 +61,6 @@ class WunderBar extends React.PureComponent {
isActive: true
}
this.props.activateSearch()
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
@ -73,7 +71,6 @@ class WunderBar extends React.PureComponent {
}
onBlur() {
this.props.deactivateSearch()
let commonState = {isActive: false};
if (this._resetOnNextBlur) {
this.setState(Object.assign({}, this._stateBeforeSearch, commonState));
@ -123,7 +120,7 @@ class WunderBar extends React.PureComponent {
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"
<input className="wunderbar__input" type="search"
ref={this.onReceiveRef}
onFocus={this.onFocus}
onBlur={this.onBlur}

View file

@ -14,6 +14,7 @@ import {
doDaemonReady,
doChangePath,
} from 'actions/app'
import parseQueryParams from 'util/query_params'
const {remote} = require('electron');
const contextMenu = remote.require('./menu/context-menu');
@ -27,21 +28,6 @@ window.addEventListener('contextmenu', (event) => {
event.preventDefault();
});
const parseQueryParams = (queryString) => {
if (queryString === '') return {};
const parts = queryString
.split('?')
.pop()
.split('&')
.map(function(p) { return p.split('=') })
const params = {};
parts.forEach(function(arr) {
params[arr[0]] = arr[1];
})
return params;
}
window.addEventListener('popstate', (event) => {
const pathname = document.location.pathname
const queryString = document.location.search

View file

@ -7,10 +7,12 @@ import {
} from 'actions/search'
import {
selectIsSearching,
selectSearchQuery,
selectCurrentSearchResults,
selectSearchActivated,
} from 'selectors/search'
import {
selectSearchQuery,
} from 'selectors/app'
import {
doNavigate,
} from 'actions/app'

View file

@ -1,9 +1,6 @@
import {createSelector} from 'reselect'
import parseQueryParams from 'util/query_params'
import lbryuri from 'lbryuri'
import {
selectIsSearching,
selectSearchActivated,
} from 'selectors/search'
export const _selectState = state => state.app || {}
@ -19,14 +16,26 @@ export const selectCurrentPath = createSelector(
export const selectCurrentPage = createSelector(
selectCurrentPath,
selectSearchActivated,
(path, searchActivated) => {
if (searchActivated) return 'search'
(path) => {
return path.replace(/^\//, '').split('?')[0]
}
)
export const selectCurrentParams = createSelector(
selectCurrentPath,
(path) => {
if (path === undefined) return {}
if (!path.match(/\?/)) return {}
return parseQueryParams(path.split('?')[1])
}
)
export const selectSearchQuery = createSelector(
selectCurrentParams,
(params) => params.query
)
export const selectCurrentUri = createSelector(
selectCurrentPath,
(path) => {
@ -86,7 +95,8 @@ export const selectPageTitle = createSelector(
export const selectWunderBarAddress = createSelector(
selectPageTitle,
(title) => title
selectSearchQuery,
(title, query) => query || title
)
export const selectWunderBarIcon = createSelector(

View file

@ -1,12 +1,12 @@
import { createSelector } from 'reselect'
import {
selectCurrentParams,
selectDaemonReady,
selectSearchQuery,
} from 'selectors/app'
export const _selectState = state => state.search || {}
export const selectSearchQuery = createSelector(
_selectState,
(state) => state.query
)
export const selectIsSearching = createSelector(
_selectState,
(state) => !!state.searching
@ -32,3 +32,18 @@ export const selectSearchActivated = createSelector(
_selectState,
(state) => !!state.activated
)
export const shouldSearch = createSelector(
selectDaemonReady,
selectSearchQuery,
selectIsSearching,
selectSearchResultsByQuery,
(daemonReady, query, isSearching, resultsByQuery) => {
if (!daemonReady) return false
if (!query) return false
if (isSearching) return false
if (Object.keys(resultsByQuery).indexOf(query) != -1) return false
return true
}
)

View file

@ -34,6 +34,12 @@ import {
import {
doFetchCurrentUriAvailability,
} from 'actions/availability'
import {
shouldSearch,
} from 'selectors/search'
import {
doSearch,
} from 'actions/search'
const triggers = []
@ -77,6 +83,11 @@ triggers.push({
action: doFetchCurrentUriAvailability,
})
triggers.push({
selector: shouldSearch,
action: doSearch,
})
const runTriggers = function() {
triggers.forEach(function(trigger) {
const state = app.store.getState();

View file

@ -0,0 +1,16 @@
function parseQueryParams(queryString) {
if (queryString === '') return {};
const parts = queryString
.split('?')
.pop()
.split('&')
.map(function(p) { return p.split('=') })
const params = {};
parts.forEach(function(arr) {
params[arr[0]] = arr[1];
})
return params;
}
export default parseQueryParams