implement search functionality

This commit is contained in:
dkanada 2020-05-02 17:00:27 +09:00
commit ce2f3104ab
2 changed files with 104 additions and 68 deletions

View file

@ -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
@ -91,7 +99,7 @@ public class SearchActivity extends AbsMusicServiceActivity implements SearchVie
private void setUpToolBar() { private void setUpToolBar() {
toolbar.setBackgroundColor(ThemeStore.primaryColor(this)); toolbar.setBackgroundColor(ThemeStore.primaryColor(this));
setSupportActionBar(toolbar); setSupportActionBar(toolbar);
//noinspection ConstantConditions // noinspection ConstantConditions
getSupportActionBar().setDisplayHomeAsUpEnabled(true); getSupportActionBar().setDisplayHomeAsUpEnabled(true);
} }
@ -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) {
search(newText); handler.removeCallbacksAndMessages(null);
handler.postDelayed(new Runnable() {
@Override
public void run() {
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;
}
}
} }

View file

@ -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();
}
});
}
} }