286 lines
10 KiB
Java
286 lines
10 KiB
Java
package net.nullsum.audinaut.fragments;
|
|
|
|
import android.os.Bundle;
|
|
import android.support.v4.view.MenuItemCompat;
|
|
import android.support.v7.widget.GridLayoutManager;
|
|
import android.support.v7.widget.RecyclerView;
|
|
import android.view.LayoutInflater;
|
|
import android.view.Menu;
|
|
import android.view.MenuInflater;
|
|
import android.view.MenuItem;
|
|
import android.view.View;
|
|
import android.view.ViewGroup;
|
|
|
|
import net.nullsum.audinaut.R;
|
|
import net.nullsum.audinaut.adapter.ArtistAdapter;
|
|
import net.nullsum.audinaut.adapter.EntryGridAdapter;
|
|
import net.nullsum.audinaut.adapter.SearchAdapter;
|
|
import net.nullsum.audinaut.adapter.SectionAdapter;
|
|
import net.nullsum.audinaut.domain.Artist;
|
|
import net.nullsum.audinaut.domain.MusicDirectory;
|
|
import net.nullsum.audinaut.domain.SearchCritera;
|
|
import net.nullsum.audinaut.domain.SearchResult;
|
|
import net.nullsum.audinaut.service.DownloadService;
|
|
import net.nullsum.audinaut.service.MusicService;
|
|
import net.nullsum.audinaut.service.MusicServiceFactory;
|
|
import net.nullsum.audinaut.util.BackgroundTask;
|
|
import net.nullsum.audinaut.util.Constants;
|
|
import net.nullsum.audinaut.util.TabBackgroundTask;
|
|
import net.nullsum.audinaut.util.Util;
|
|
import net.nullsum.audinaut.view.UpdateView;
|
|
|
|
import java.io.Serializable;
|
|
import java.util.ArrayList;
|
|
import java.util.Collections;
|
|
import java.util.List;
|
|
|
|
public class SearchFragment extends SubsonicFragment implements SectionAdapter.OnItemClickedListener<Serializable> {
|
|
|
|
private static final int MAX_ARTISTS = 20;
|
|
private static final int MAX_ALBUMS = 20;
|
|
private static final int MAX_SONGS = 50;
|
|
private static final int MIN_CLOSENESS = 1;
|
|
|
|
private RecyclerView recyclerView;
|
|
private SearchAdapter adapter;
|
|
private boolean largeAlbums = false;
|
|
|
|
private SearchResult searchResult;
|
|
private boolean skipSearch = false;
|
|
private String currentQuery;
|
|
|
|
public SearchFragment() {
|
|
super();
|
|
alwaysStartFullscreen = true;
|
|
}
|
|
|
|
@Override
|
|
public void onCreate(Bundle savedInstanceState) {
|
|
super.onCreate(savedInstanceState);
|
|
|
|
if (savedInstanceState != null) {
|
|
searchResult = (SearchResult) savedInstanceState.getSerializable(Constants.FRAGMENT_LIST);
|
|
}
|
|
largeAlbums = Util.getPreferences(context).getBoolean(Constants.PREFERENCES_KEY_LARGE_ALBUM_ART, true);
|
|
}
|
|
|
|
@Override
|
|
public void onSaveInstanceState(Bundle outState) {
|
|
super.onSaveInstanceState(outState);
|
|
outState.putSerializable(Constants.FRAGMENT_LIST, searchResult);
|
|
}
|
|
|
|
@Override
|
|
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle bundle) {
|
|
rootView = inflater.inflate(R.layout.abstract_recycler_fragment, container, false);
|
|
setTitle(R.string.search_title);
|
|
|
|
refreshLayout = rootView.findViewById(R.id.refresh_layout);
|
|
refreshLayout.setEnabled(false);
|
|
|
|
recyclerView = rootView.findViewById(R.id.fragment_recycler);
|
|
setupLayoutManager(recyclerView, largeAlbums);
|
|
|
|
registerForContextMenu(recyclerView);
|
|
context.onNewIntent(context.getIntent());
|
|
|
|
if (searchResult != null) {
|
|
skipSearch = true;
|
|
recyclerView.setAdapter(adapter = new SearchAdapter(context, searchResult, getImageLoader(), largeAlbums, this));
|
|
}
|
|
|
|
return rootView;
|
|
}
|
|
|
|
@Override
|
|
public void setIsOnlyVisible(boolean isOnlyVisible) {
|
|
boolean update = this.isOnlyVisible != isOnlyVisible;
|
|
super.setIsOnlyVisible(isOnlyVisible);
|
|
if (update && adapter != null) {
|
|
RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();
|
|
if (layoutManager instanceof GridLayoutManager) {
|
|
((GridLayoutManager) layoutManager).setSpanCount(getRecyclerColumnCount());
|
|
}
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public GridLayoutManager.SpanSizeLookup getSpanSizeLookup(final GridLayoutManager gridLayoutManager) {
|
|
return new GridLayoutManager.SpanSizeLookup() {
|
|
@Override
|
|
public int getSpanSize(int position) {
|
|
int viewType = adapter.getItemViewType(position);
|
|
if (viewType == EntryGridAdapter.VIEW_TYPE_SONG || viewType == EntryGridAdapter.VIEW_TYPE_HEADER || viewType == ArtistAdapter.VIEW_TYPE_ARTIST) {
|
|
return gridLayoutManager.getSpanCount();
|
|
} else {
|
|
return 1;
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
@Override
|
|
public void onCreateOptionsMenu(Menu menu, MenuInflater menuInflater) {
|
|
menuInflater.inflate(R.menu.search, menu);
|
|
onFinishSetupOptionsMenu(menu);
|
|
}
|
|
|
|
@Override
|
|
public void onCreateContextMenu(Menu menu, MenuInflater menuInflater, UpdateView<Serializable> updateView, Serializable item) {
|
|
onCreateContextMenuSupport(menu, menuInflater, updateView, item);
|
|
if (item instanceof MusicDirectory.Entry && !Util.isOffline(context)) {
|
|
menu.removeItem(R.id.song_menu_remove_playlist);
|
|
}
|
|
recreateContextMenu(menu);
|
|
}
|
|
|
|
@Override
|
|
public boolean onContextItemSelected(MenuItem menuItem, UpdateView<Serializable> updateView, Serializable item) {
|
|
return onContextItemSelected(menuItem, item);
|
|
}
|
|
|
|
@Override
|
|
public void refresh(boolean refresh) {
|
|
context.onNewIntent(context.getIntent());
|
|
}
|
|
|
|
@Override
|
|
public void onItemClicked(UpdateView<Serializable> updateView, Serializable item) {
|
|
if (item instanceof Artist) {
|
|
onArtistSelected((Artist) item, false);
|
|
} else if (item instanceof MusicDirectory.Entry) {
|
|
MusicDirectory.Entry entry = (MusicDirectory.Entry) item;
|
|
if (entry.isDirectory()) {
|
|
onAlbumSelected(entry, false);
|
|
} else {
|
|
onSongSelected(entry, true);
|
|
}
|
|
}
|
|
}
|
|
|
|
@Override
|
|
protected List<MusicDirectory.Entry> getSelectedEntries() {
|
|
List<Serializable> selected = adapter.getSelected();
|
|
List<MusicDirectory.Entry> selectedMedia = new ArrayList<>();
|
|
for (Serializable ser : selected) {
|
|
if (ser instanceof MusicDirectory.Entry) {
|
|
selectedMedia.add((MusicDirectory.Entry) ser);
|
|
}
|
|
}
|
|
|
|
return selectedMedia;
|
|
}
|
|
|
|
@Override
|
|
protected boolean isShowArtistEnabled() {
|
|
return true;
|
|
}
|
|
|
|
public void search(final String query, final boolean autoplay) {
|
|
if (skipSearch) {
|
|
skipSearch = false;
|
|
return;
|
|
}
|
|
currentQuery = query;
|
|
|
|
BackgroundTask<SearchResult> task = new TabBackgroundTask<SearchResult>(this) {
|
|
@Override
|
|
protected SearchResult doInBackground() throws Throwable {
|
|
SearchCritera criteria = new SearchCritera(query, MAX_ARTISTS, MAX_ALBUMS, MAX_SONGS);
|
|
MusicService service = MusicServiceFactory.getMusicService(context);
|
|
return service.search(criteria, context, this);
|
|
}
|
|
|
|
@Override
|
|
protected void done(SearchResult result) {
|
|
searchResult = result;
|
|
recyclerView.setAdapter(adapter = new SearchAdapter(context, searchResult, getImageLoader(), largeAlbums, SearchFragment.this));
|
|
if (autoplay) {
|
|
autoplay(query);
|
|
}
|
|
|
|
}
|
|
};
|
|
task.execute();
|
|
|
|
if (searchItem != null) {
|
|
MenuItemCompat.collapseActionView(searchItem);
|
|
}
|
|
}
|
|
|
|
protected String getCurrentQuery() {
|
|
return currentQuery;
|
|
}
|
|
|
|
private void onArtistSelected(Artist artist, boolean autoplay) {
|
|
SubsonicFragment fragment = new SelectDirectoryFragment();
|
|
Bundle args = new Bundle();
|
|
args.putString(Constants.INTENT_EXTRA_NAME_ID, artist.getId());
|
|
args.putString(Constants.INTENT_EXTRA_NAME_NAME, artist.getName());
|
|
if (autoplay) {
|
|
args.putBoolean(Constants.INTENT_EXTRA_NAME_AUTOPLAY, true);
|
|
}
|
|
args.putBoolean(Constants.INTENT_EXTRA_NAME_ARTIST, true);
|
|
fragment.setArguments(args);
|
|
|
|
replaceFragment(fragment);
|
|
}
|
|
|
|
private void onAlbumSelected(MusicDirectory.Entry album, boolean autoplay) {
|
|
SubsonicFragment fragment = new SelectDirectoryFragment();
|
|
Bundle args = new Bundle();
|
|
args.putString(Constants.INTENT_EXTRA_NAME_ID, album.getId());
|
|
args.putString(Constants.INTENT_EXTRA_NAME_NAME, album.getTitle());
|
|
if (autoplay) {
|
|
args.putBoolean(Constants.INTENT_EXTRA_NAME_AUTOPLAY, true);
|
|
}
|
|
fragment.setArguments(args);
|
|
|
|
replaceFragment(fragment);
|
|
}
|
|
|
|
private void onSongSelected(MusicDirectory.Entry song, boolean append) {
|
|
DownloadService downloadService = getDownloadService();
|
|
if (downloadService != null) {
|
|
if (!append) {
|
|
downloadService.clear();
|
|
}
|
|
downloadService.download(Collections.singletonList(song), false, false, false, false);
|
|
downloadService.play(downloadService.size() - 1);
|
|
|
|
Util.toast(context, getResources().getQuantityString(R.plurals.select_album_n_songs_added, 1, 1));
|
|
}
|
|
}
|
|
|
|
private void autoplay(String query) {
|
|
query = query.toLowerCase();
|
|
|
|
Artist artist = null;
|
|
if (!searchResult.getArtists().isEmpty()) {
|
|
artist = searchResult.getArtists().get(0);
|
|
artist.setCloseness(Util.getStringDistance(artist.getName().toLowerCase(), query));
|
|
}
|
|
MusicDirectory.Entry album = null;
|
|
if (!searchResult.getAlbums().isEmpty()) {
|
|
album = searchResult.getAlbums().get(0);
|
|
album.setCloseness(Util.getStringDistance(album.getTitle().toLowerCase(), query));
|
|
}
|
|
MusicDirectory.Entry song = null;
|
|
if (!searchResult.getSongs().isEmpty()) {
|
|
song = searchResult.getSongs().get(0);
|
|
song.setCloseness(Util.getStringDistance(song.getTitle().toLowerCase(), query));
|
|
}
|
|
|
|
if (artist != null && (artist.getCloseness() <= MIN_CLOSENESS ||
|
|
(album == null || artist.getCloseness() <= album.getCloseness()) &&
|
|
(song == null || artist.getCloseness() <= song.getCloseness()))) {
|
|
onArtistSelected(artist, true);
|
|
} else if (album != null && (album.getCloseness() <= MIN_CLOSENESS ||
|
|
song == null || album.getCloseness() <= song.getCloseness())) {
|
|
onAlbumSelected(album, true);
|
|
} else if (song != null) {
|
|
onSongSelected(song, false);
|
|
}
|
|
}
|
|
}
|