implement search functionality
This commit is contained in:
parent
5826430751
commit
ce2f3104ab
2 changed files with 104 additions and 68 deletions
|
|
@ -1,14 +1,13 @@
|
||||||
package com.kabouzeid.gramophone.ui.activities;
|
package com.kabouzeid.gramophone.ui.activities;
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.loader.app.LoaderManager;
|
|
||||||
import androidx.loader.content.Loader;
|
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
import androidx.appcompat.widget.SearchView;
|
import androidx.appcompat.widget.SearchView;
|
||||||
import androidx.appcompat.widget.Toolbar;
|
import androidx.appcompat.widget.Toolbar;
|
||||||
|
|
||||||
|
import android.os.Handler;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
|
@ -18,31 +17,40 @@ import com.kabouzeid.appthemehelper.ThemeStore;
|
||||||
import com.kabouzeid.gramophone.R;
|
import com.kabouzeid.gramophone.R;
|
||||||
import com.kabouzeid.gramophone.adapter.SearchAdapter;
|
import com.kabouzeid.gramophone.adapter.SearchAdapter;
|
||||||
import com.kabouzeid.gramophone.interfaces.LoaderIds;
|
import com.kabouzeid.gramophone.interfaces.LoaderIds;
|
||||||
import com.kabouzeid.gramophone.misc.WrappedAsyncTaskLoader;
|
import com.kabouzeid.gramophone.interfaces.MediaCallback;
|
||||||
|
import com.kabouzeid.gramophone.model.Album;
|
||||||
|
import com.kabouzeid.gramophone.model.Artist;
|
||||||
|
import com.kabouzeid.gramophone.model.Song;
|
||||||
import com.kabouzeid.gramophone.ui.activities.base.AbsMusicServiceActivity;
|
import com.kabouzeid.gramophone.ui.activities.base.AbsMusicServiceActivity;
|
||||||
|
import com.kabouzeid.gramophone.util.QueryUtil;
|
||||||
import com.kabouzeid.gramophone.util.Util;
|
import com.kabouzeid.gramophone.util.Util;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import org.jellyfin.apiclient.model.querying.ItemQuery;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.Comparator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import butterknife.BindView;
|
import butterknife.BindView;
|
||||||
import butterknife.ButterKnife;
|
import butterknife.ButterKnife;
|
||||||
|
|
||||||
public class SearchActivity extends AbsMusicServiceActivity implements SearchView.OnQueryTextListener, LoaderManager.LoaderCallbacks<List<Object>> {
|
public class SearchActivity extends AbsMusicServiceActivity implements SearchView.OnQueryTextListener {
|
||||||
|
|
||||||
public static final String QUERY = "query";
|
public static final String QUERY = "query";
|
||||||
private static final int LOADER_ID = LoaderIds.SEARCH_ACTIVITY;
|
|
||||||
|
|
||||||
@BindView(R.id.recycler_view)
|
@BindView(R.id.recycler_view)
|
||||||
RecyclerView recyclerView;
|
RecyclerView recyclerView;
|
||||||
|
|
||||||
@BindView(R.id.toolbar)
|
@BindView(R.id.toolbar)
|
||||||
Toolbar toolbar;
|
Toolbar toolbar;
|
||||||
|
|
||||||
@BindView(android.R.id.empty)
|
@BindView(android.R.id.empty)
|
||||||
TextView empty;
|
TextView empty;
|
||||||
|
|
||||||
SearchView searchView;
|
SearchView searchView;
|
||||||
|
|
||||||
|
private Handler handler;
|
||||||
|
|
||||||
private SearchAdapter adapter;
|
private SearchAdapter adapter;
|
||||||
private String query;
|
private String query;
|
||||||
|
|
||||||
|
|
@ -66,8 +74,8 @@ public class SearchActivity extends AbsMusicServiceActivity implements SearchVie
|
||||||
empty.setVisibility(adapter.getItemCount() < 1 ? View.VISIBLE : View.GONE);
|
empty.setVisibility(adapter.getItemCount() < 1 ? View.VISIBLE : View.GONE);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
recyclerView.setAdapter(adapter);
|
|
||||||
|
|
||||||
|
recyclerView.setAdapter(adapter);
|
||||||
recyclerView.setOnTouchListener((v, event) -> {
|
recyclerView.setOnTouchListener((v, event) -> {
|
||||||
hideSoftKeyboard();
|
hideSoftKeyboard();
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -75,11 +83,11 @@ public class SearchActivity extends AbsMusicServiceActivity implements SearchVie
|
||||||
|
|
||||||
setUpToolBar();
|
setUpToolBar();
|
||||||
|
|
||||||
|
handler = new Handler();
|
||||||
if (savedInstanceState != null) {
|
if (savedInstanceState != null) {
|
||||||
query = savedInstanceState.getString(QUERY);
|
query = savedInstanceState.getString(QUERY);
|
||||||
|
search(query);
|
||||||
}
|
}
|
||||||
|
|
||||||
getSupportLoaderManager().initLoader(LOADER_ID, null, this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -129,18 +137,39 @@ public class SearchActivity extends AbsMusicServiceActivity implements SearchVie
|
||||||
if (item.getItemId() == android.R.id.home) {
|
if (item.getItemId() == android.R.id.home) {
|
||||||
onBackPressed();
|
onBackPressed();
|
||||||
}
|
}
|
||||||
|
|
||||||
return super.onOptionsItemSelected(item);
|
return super.onOptionsItemSelected(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void search(@NonNull String query) {
|
private void search(@NonNull String query) {
|
||||||
this.query = query;
|
this.query = query;
|
||||||
getSupportLoaderManager().restartLoader(LOADER_ID, null, this);
|
ItemQuery itemQuery = new ItemQuery();
|
||||||
|
itemQuery.setSearchTerm(query);
|
||||||
|
QueryUtil.getItems(itemQuery, new MediaCallback() {
|
||||||
|
@Override
|
||||||
|
public void onLoadMedia(List<?> media) {
|
||||||
|
Collections.sort(media, new Comparator<Object>() {
|
||||||
|
public int compare(Object one, Object two) {
|
||||||
|
if (one.getClass() == Album.class || one.getClass() == Artist.class) {
|
||||||
|
if (two.getClass() == Song.class) return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (two.getClass() == Album.class || two.getClass() == Artist.class) {
|
||||||
|
if (one.getClass() == Song.class) return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
adapter.swapDataSet((List<Object>) media);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onMediaStoreChanged() {
|
public void onMediaStoreChanged() {
|
||||||
super.onMediaStoreChanged();
|
super.onMediaStoreChanged();
|
||||||
getSupportLoaderManager().restartLoader(LOADER_ID, null, this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -151,7 +180,14 @@ public class SearchActivity extends AbsMusicServiceActivity implements SearchVie
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onQueryTextChange(String newText) {
|
public boolean onQueryTextChange(String newText) {
|
||||||
|
handler.removeCallbacksAndMessages(null);
|
||||||
|
handler.postDelayed(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
search(newText);
|
search(newText);
|
||||||
|
}
|
||||||
|
}, 1000);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -161,34 +197,4 @@ public class SearchActivity extends AbsMusicServiceActivity implements SearchVie
|
||||||
searchView.clearFocus();
|
searchView.clearFocus();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Loader<List<Object>> onCreateLoader(int id, Bundle args) {
|
|
||||||
return new AsyncSearchResultLoader(this, query);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onLoadFinished(Loader<List<Object>> loader, List<Object> data) {
|
|
||||||
adapter.swapDataSet(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onLoaderReset(Loader<List<Object>> loader) {
|
|
||||||
adapter.swapDataSet(Collections.emptyList());
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class AsyncSearchResultLoader extends WrappedAsyncTaskLoader<List<Object>> {
|
|
||||||
private final String query;
|
|
||||||
|
|
||||||
public AsyncSearchResultLoader(Context context, String query) {
|
|
||||||
super(context);
|
|
||||||
this.query = query;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<Object> loadInBackground() {
|
|
||||||
List<Object> results = new ArrayList<>();
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ import com.kabouzeid.gramophone.model.Song;
|
||||||
|
|
||||||
import org.jellyfin.apiclient.interaction.Response;
|
import org.jellyfin.apiclient.interaction.Response;
|
||||||
import org.jellyfin.apiclient.model.dto.BaseItemDto;
|
import org.jellyfin.apiclient.model.dto.BaseItemDto;
|
||||||
|
import org.jellyfin.apiclient.model.dto.BaseItemType;
|
||||||
import org.jellyfin.apiclient.model.querying.ArtistsQuery;
|
import org.jellyfin.apiclient.model.querying.ArtistsQuery;
|
||||||
import org.jellyfin.apiclient.model.querying.ItemFields;
|
import org.jellyfin.apiclient.model.querying.ItemFields;
|
||||||
import org.jellyfin.apiclient.model.querying.ItemQuery;
|
import org.jellyfin.apiclient.model.querying.ItemQuery;
|
||||||
|
|
@ -92,6 +93,35 @@ public class QueryUtil {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void getItems(ItemQuery query, MediaCallback callback) {
|
||||||
|
query.setIncludeItemTypes(new String[]{"MusicArtist", "MusicAlbum", "Audio"});
|
||||||
|
query.setUserId(App.getApiClient().getCurrentUserId());
|
||||||
|
query.setLimit(40);
|
||||||
|
query.setRecursive(true);
|
||||||
|
App.getApiClient().GetItemsAsync(query, new Response<ItemsResult>() {
|
||||||
|
@Override
|
||||||
|
public void onResponse(ItemsResult result) {
|
||||||
|
List<Object> items = new ArrayList<>();
|
||||||
|
for (BaseItemDto itemDto : result.getItems()) {
|
||||||
|
if (itemDto.getBaseItemType() == BaseItemType.MusicArtist) {
|
||||||
|
items.add(new Artist(itemDto));
|
||||||
|
} else if (itemDto.getBaseItemType() == BaseItemType.MusicAlbum) {
|
||||||
|
items.add(new Album(itemDto));
|
||||||
|
} else {
|
||||||
|
items.add(new Song(itemDto));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
callback.onLoadMedia(items);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onError(Exception exception) {
|
||||||
|
exception.printStackTrace();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
public static void getAlbums(ItemQuery query, MediaCallback callback) {
|
public static void getAlbums(ItemQuery query, MediaCallback callback) {
|
||||||
query.setIncludeItemTypes(new String[]{"MusicAlbum"});
|
query.setIncludeItemTypes(new String[]{"MusicAlbum"});
|
||||||
query.setUserId(App.getApiClient().getCurrentUserId());
|
query.setUserId(App.getApiClient().getCurrentUserId());
|
||||||
|
|
@ -132,30 +162,6 @@ public class QueryUtil {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void getSongs(ItemQuery query, MediaCallback callback) {
|
|
||||||
query.setIncludeItemTypes(new String[]{"Audio"});
|
|
||||||
query.setUserId(App.getApiClient().getCurrentUserId());
|
|
||||||
query.setLimit(100);
|
|
||||||
query.setRecursive(true);
|
|
||||||
if (currentLibrary != null && query.getParentId() == null) query.setParentId(currentLibrary.getId());
|
|
||||||
App.getApiClient().GetItemsAsync(query, new Response<ItemsResult>() {
|
|
||||||
@Override
|
|
||||||
public void onResponse(ItemsResult result) {
|
|
||||||
List<Song> songs = new ArrayList<>();
|
|
||||||
for (BaseItemDto itemDto : result.getItems()) {
|
|
||||||
songs.add(new Song(itemDto));
|
|
||||||
}
|
|
||||||
|
|
||||||
callback.onLoadMedia(songs);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onError(Exception exception) {
|
|
||||||
exception.printStackTrace();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void getArtists(MediaCallback callback) {
|
public static void getArtists(MediaCallback callback) {
|
||||||
ArtistsQuery query = new ArtistsQuery();
|
ArtistsQuery query = new ArtistsQuery();
|
||||||
query.setFields(new ItemFields[]{ItemFields.Genres});
|
query.setFields(new ItemFields[]{ItemFields.Genres});
|
||||||
|
|
@ -196,4 +202,28 @@ public class QueryUtil {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void getSongs(ItemQuery query, MediaCallback callback) {
|
||||||
|
query.setIncludeItemTypes(new String[]{"Audio"});
|
||||||
|
query.setUserId(App.getApiClient().getCurrentUserId());
|
||||||
|
query.setLimit(100);
|
||||||
|
query.setRecursive(true);
|
||||||
|
if (currentLibrary != null && query.getParentId() == null) query.setParentId(currentLibrary.getId());
|
||||||
|
App.getApiClient().GetItemsAsync(query, new Response<ItemsResult>() {
|
||||||
|
@Override
|
||||||
|
public void onResponse(ItemsResult result) {
|
||||||
|
List<Song> songs = new ArrayList<>();
|
||||||
|
for (BaseItemDto itemDto : result.getItems()) {
|
||||||
|
songs.add(new Song(itemDto));
|
||||||
|
}
|
||||||
|
|
||||||
|
callback.onLoadMedia(songs);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onError(Exception exception) {
|
||||||
|
exception.printStackTrace();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue