Search not to fiddle with URL to fix render() triggering

This commit is contained in:
James Barnsley
2018-06-15 08:56:17 +12:00
parent 7a94320d80
commit b72c77f4f8
9 changed files with 23032 additions and 21096 deletions

View File

@ -11,64 +11,32 @@ class SearchForm extends React.Component{
constructor(props){
super(props);
this.state = {
query: '',
in_focus: false
}
}
componentDidMount(){
if (this.props.query){
var query = this.props.query.replace("search:","");
this.setState({query: query});
}
}
componentWillReceiveProps(newProps){
if (newProps.query && newProps.query != this.state.query && !this.state.in_focus){
this.setState({query: newProps.query.replace("search:","")});
}
}
handleSubmit(e){
e.preventDefault()
// check for uri type matching
switch (helpers.uriType(this.state.query)){
switch (helpers.uriType(this.props.term)){
case 'album':
hashHistory.push(global.baseURL+'album/'+encodeURIComponent(this.state.query))
hashHistory.push(global.baseURL+'album/'+encodeURIComponent(this.props.term))
break
case 'artist':
hashHistory.push(global.baseURL+'artist/'+encodeURIComponent(this.state.query))
hashHistory.push(global.baseURL+'artist/'+encodeURIComponent(this.props.term))
break
case 'playlist':
hashHistory.push(global.baseURL+'playlist/'+encodeURIComponent(this.state.query))
hashHistory.push(global.baseURL+'playlist/'+encodeURIComponent(this.props.term))
break
case 'track':
hashHistory.push(global.baseURL+'track/'+encodeURIComponent(this.state.query))
hashHistory.push(global.baseURL+'track/'+encodeURIComponent(this.props.term))
break
default:
var available_views = ["all:","artist:","album:","playlist:",":track"];
var view_defined = false;
var query = this.state.query;
for (var i = 0; i < available_views.length; i++){
if (query.startsWith(available_views[i])){
view_defined = true;
}
}
if (!view_defined){
query = "all:"+query;
}
hashHistory.push(global.baseURL+'search/search:'+query);
this.props.onSubmit(e);
break
}
@ -82,10 +50,8 @@ class SearchForm extends React.Component{
<input
type="text"
placeholder="Search..."
onChange={ e => this.setState({ query: e.target.value }) }
onFocus={e => this.setState({in_focus: true})}
onBlur={e => this.setState({in_focus: false})}
value={ this.state.query } />
onChange={e => this.props.onChange(e)}
value={ this.props.term } />
</label>
</form>
)

View File

@ -449,7 +449,7 @@ export let getFromUri = function(element, uri = ""){
}
break
case 'searchcontext':
case 'searchtype':
if (exploded[0] == "search"){
return exploded[1];
}

View File

@ -25,28 +25,21 @@ class Search extends React.Component{
constructor(props){
super(props);
this.state = {
type: 'all',
term: ''
}
}
componentDidMount(){
var context = "all";
var term = null;
if (this.props.params && this.props.params.query && this.props.params.query !== ''){
context = helpers.getFromUri("searchcontext",this.props.params.query);
term = helpers.getFromUri("searchterm",this.props.params.query);
}
// Auto-focus on the input field
$(document).find('.search-form input').focus();
if (context && term){
if (this.props.mopidy_connected && this.props.uri_schemes_search_enabled){
this.props.mopidyActions.getSearchResults(context, term)
}
if (this.props.uri_schemes_search_enabled && this.props.uri_schemes_search_enabled.includes('spotify:')){
this.props.spotifyActions.getSearchResults(context, term)
}
}
// Listen for a query baked-in to the URL
// This would be the case when we've clicked from a link elsewhere
this.digestUri();
}
componentWillUnmount(){
@ -54,37 +47,59 @@ class Search extends React.Component{
this.props.spotifyActions.clearSearchResults();
}
componentWillReceiveProps(newProps){
componentWillReceiveProps(nextProps){
if (this.props.params && this.props.params.query && this.props.params.query !== ''){
var old_context = helpers.getFromUri("searchcontext",this.props.params.query);
var old_term = helpers.getFromUri("searchterm",this.props.params.query);
} else {
var old_context = "all";
var old_term = null;
// Query changed
if (nextProps.params.query !== this.props.params.query){
this.digestUri(nextProps);
}
if (newProps.params && newProps.params.query && newProps.params.query !== ''){
var context = helpers.getFromUri("searchcontext",newProps.params.query);
var term = helpers.getFromUri("searchterm",newProps.params.query);
} else {
var context = "all";
var term = null;
// Services came online
if (!this.props.mopidy_connected && nextProps.mopidy_connected && nextProps.uri_schemes_search_enabled){
this.search(this.state.type, this.state.term, 'mopidy');
if (nextProps.uri_schemes_search_enabled.includes('spotify:')){
this.search(this.state.type, this.state.term, 'spotify');
}
}
}
handleChange(e){
this.setState({term: e.target.value});
}
// Digest the URI query property
// Triggered when the URL changes
digestUri(props = this.props){
if (props.params && props.params.query && props.params.query !== ''){
var type = helpers.getFromUri("searchtype", props.params.query);
var term = helpers.getFromUri("searchterm", props.params.query);
if (type){
this.setState({type: type});
}
if (term){
this.setState({term: term});
}
if (type && term){
this.search(type, term);
}
}
}
search(type = this.state.type, term = this.state.term, provider){
this.props.mopidyActions.clearSearchResults();
this.props.spotifyActions.clearSearchResults();
if (provider == 'mopidy' || (this.props.mopidy_connected && this.props.uri_schemes_search_enabled)){
this.props.mopidyActions.getSearchResults(type, term)
}
// Search changed
if (term && context && (term !== old_term || context !== old_context)){
this.props.mopidyActions.clearSearchResults();
this.props.spotifyActions.clearSearchResults();
if (this.props.mopidy_connected && this.props.uri_schemes_search_enabled){
this.props.mopidyActions.getSearchResults(context, term)
}
if (this.props.mopidy_connected && this.props.uri_schemes_search_enabled && this.props.uri_schemes_search_enabled.includes('spotify:')){
this.props.spotifyActions.getSearchResults(context, term)
}
if (provider == 'spotify' || (this.props.mopidy_connected && this.props.uri_schemes_search_enabled && this.props.uri_schemes_search_enabled.includes('spotify:'))){
this.props.spotifyActions.getSearchResults(type, term)
}
}
@ -105,13 +120,6 @@ class Search extends React.Component{
}
renderResults(){
var context = helpers.getFromUri("searchcontext",this.props.params.query);
var term = helpers.getFromUri("searchterm",this.props.params.query);
if (!context){
context = "all";
}
var spotify_search_enabled = (this.props.search_settings && this.props.search_settings.spotify);
var sort = this.props.sort;
@ -165,13 +173,13 @@ class Search extends React.Component{
tracks = helpers.sortItems(tracks, (sort == 'followers.total' ? 'popularity' : sort), sort_reverse, sort_map);
switch (context){
switch (this.state.type){
case 'artist':
return (
<div>
<h4>
<URILink unencoded type="search" uri={"search:all:"+term}>
<URILink unencoded type="search" uri={"search:all:"+this.state.term}>
Search
</URILink>
&nbsp; <Icon type="fontawesome" name="angle-right" />&nbsp;
@ -189,7 +197,7 @@ class Search extends React.Component{
return (
<div>
<h4>
<URILink unencoded type="search" uri={"search:all:"+term}>
<URILink unencoded type="search" uri={"search:all:"+this.state.term}>
Search
</URILink>
&nbsp; <Icon type="fontawesome" name="angle-right" />&nbsp;
@ -207,7 +215,7 @@ class Search extends React.Component{
return (
<div>
<h4>
<URILink unencoded type="search" uri={"search:all:"+term}>
<URILink unencoded type="search" uri={"search:all:"+this.state.term}>
Search
</URILink>
&nbsp; <Icon type="fontawesome" name="angle-right" />&nbsp;
@ -225,7 +233,7 @@ class Search extends React.Component{
return (
<div>
<h4>
<URILink unencoded type="search" uri={"search:all:"+term}>
<URILink unencoded type="search" uri={"search:all:"+this.state.term}>
Search
</URILink>
&nbsp; <Icon type="fontawesome" name="angle-right" />&nbsp;
@ -246,11 +254,11 @@ class Search extends React.Component{
var artists_section = (
<section>
<div className="inner">
<URILink unencoded type="search" uri={"search:artist:"+term}>
<URILink unencoded type="search" uri={"search:artist:"+this.state.term}>
<h4>Artists</h4>
</URILink>
<ArtistGrid show_source_icon artists={artists.slice(0,5)} />
{artists.length > 4 ? <URILink unencoded type="search" uri={"search:artist:"+term} className="button grey">
{artists.length > 4 ? <URILink unencoded type="search" uri={"search:artist:"+this.state.term} className="button grey">
All artists ({artists.length})
</URILink> : null}
</div>
@ -264,11 +272,11 @@ class Search extends React.Component{
var albums_section = (
<section>
<div className="inner">
<URILink unencoded type="search" uri={"search:album:"+term}>
<URILink unencoded type="search" uri={"search:album:"+this.state.term}>
<h4>Albums</h4>
</URILink>
<AlbumGrid show_source_icon albums={albums.slice(0,5)} />
{albums.length > 4 ? <URILink unencoded type="search" uri={"search:album:"+term} className="button grey">
{albums.length > 4 ? <URILink unencoded type="search" uri={"search:album:"+this.state.term} className="button grey">
All albums ({albums.length})
</URILink> : null}
</div>
@ -282,11 +290,11 @@ class Search extends React.Component{
var playlists_section = (
<section>
<div className="inner">
<URILink unencoded type="search" uri={"search:playlist:"+term}>
<URILink unencoded type="search" uri={"search:playlist:"+this.state.term}>
<h4>Playlists</h4>
</URILink>
<PlaylistGrid show_source_icon playlists={playlists.slice(0,5)} />
{playlists.length > 4 ? <URILink unencoded type="search" uri={"search:playlist:"+term} className="button grey">
{playlists.length > 4 ? <URILink unencoded type="search" uri={"search:playlist:"+this.state.term} className="button grey">
All playlists ({playlists.length})
</URILink> : null}
</div>
@ -321,6 +329,29 @@ class Search extends React.Component{
}
render(){
var type_options = [
{
value: 'all',
label: 'All'
},
{
value: 'artist',
label: 'Artist'
},
{
value: 'album',
label: 'Album'
},
{
value: 'playlist',
label: 'Playlist'
},
{
value: 'track',
label: 'Track'
}
];
var sort_options = [
{
value: 'followers.total',
@ -354,6 +385,13 @@ class Search extends React.Component{
var options = (
<span>
<DropdownField
icon="category"
name="Type"
value={this.state.type}
options={type_options}
handleChange={value => {this.setState({type: value}); this.search(value, this.state.term)}}
/>
<DropdownField
icon="sort"
name="Sort"
@ -379,8 +417,10 @@ class Search extends React.Component{
</Header>
<SearchForm
query={(this.props.params.query ? this.props.params.query : '')}
view={(this.props.params.view ? this.props.params.view : 'all')}
type={this.state.type}
term={this.state.term}
onChange={e => this.handleChange(e)}
onSubmit={e => this.search()}
/>
<div className="content-wrapper">

View File

@ -36,12 +36,12 @@ class Settings extends React.Component {
}
}
componentWillReceiveProps(newProps){
componentWillReceiveProps(nextProps){
var changed = false
var state = this.state
if (newProps.pusher.username != this.state.pusher_username && this.state.input_in_focus != 'pusher_username'){
state.pusher_username = newProps.pusher.username
if (nextProps.pusher.username != this.state.pusher_username && this.state.input_in_focus != 'pusher_username'){
state.pusher_username = nextProps.pusher.username
changed = true
}

View File

@ -5,7 +5,7 @@
position: absolute;
top: 30px;
left: 90px;
right: 250px;
right: 330px;
input {
@include feature_font();