Implemented search field for PVR views
* Implemented search field for PVR views. (#695) * Implemented search field for PVRChannelEPGListFragment. (#695)
This commit is contained in:
parent
a3ed983fee
commit
dd53f621e5
|
@ -0,0 +1,212 @@
|
||||||
|
package org.xbmc.kore.ui;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.support.annotation.NonNull;
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
|
import android.support.v4.app.Fragment;
|
||||||
|
import android.support.v4.view.MenuItemCompat;
|
||||||
|
import android.support.v7.widget.SearchView;
|
||||||
|
import android.text.TextUtils;
|
||||||
|
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 android.widget.EditText;
|
||||||
|
|
||||||
|
import org.xbmc.kore.R;
|
||||||
|
import org.xbmc.kore.jsonrpc.event.MediaSyncEvent;
|
||||||
|
|
||||||
|
public abstract class AbstractSearchableFragment extends Fragment implements SearchView.OnQueryTextListener {
|
||||||
|
|
||||||
|
private String searchFilter = null;
|
||||||
|
private String savedSearchFilter;
|
||||||
|
private boolean supportsSearch;
|
||||||
|
private boolean isPaused;
|
||||||
|
|
||||||
|
private SearchView searchView;
|
||||||
|
|
||||||
|
private final String BUNDLE_KEY_SEARCH_QUERY = "search_query";
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
||||||
|
View root = super.onCreateView(inflater, container, savedInstanceState);
|
||||||
|
|
||||||
|
if (savedInstanceState != null) {
|
||||||
|
savedSearchFilter = savedInstanceState.getString(BUNDLE_KEY_SEARCH_QUERY);
|
||||||
|
}
|
||||||
|
searchFilter = savedSearchFilter;
|
||||||
|
|
||||||
|
return root;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
||||||
|
inflater.inflate(R.menu.abstractcursorlistfragment, menu);
|
||||||
|
|
||||||
|
if (supportsSearch) {
|
||||||
|
setupSearchMenuItem(menu, inflater);
|
||||||
|
}
|
||||||
|
|
||||||
|
super.onCreateOptionsMenu(menu, inflater);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use this to indicate your fragment supports search queries.
|
||||||
|
* Get the entered search query using {@link #getSearchFilter()}
|
||||||
|
* <br/>
|
||||||
|
* Note: make sure this is set before {@link #onCreateOptionsMenu(Menu, MenuInflater)} is called.
|
||||||
|
* For instance in {@link #onAttach(Activity)}
|
||||||
|
*
|
||||||
|
* @param supportsSearch true if you support search queries, false otherwise
|
||||||
|
*/
|
||||||
|
public void setSupportsSearch(boolean supportsSearch) {
|
||||||
|
this.supportsSearch = supportsSearch;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Save the search state of the list fragment
|
||||||
|
*/
|
||||||
|
public void saveSearchState() {
|
||||||
|
savedSearchFilter = searchFilter;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return text entered in searchview
|
||||||
|
*/
|
||||||
|
public String getSearchFilter() {
|
||||||
|
return searchFilter;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setupSearchMenuItem(Menu menu, MenuInflater inflater) {
|
||||||
|
inflater.inflate(R.menu.media_search, menu);
|
||||||
|
MenuItem searchMenuItem = menu.findItem(R.id.action_search);
|
||||||
|
if (searchMenuItem != null) {
|
||||||
|
searchView = (SearchView) MenuItemCompat.getActionView(searchMenuItem);
|
||||||
|
searchView.setOnQueryTextListener(this);
|
||||||
|
searchView.setQueryHint(getString(R.string.action_search));
|
||||||
|
if (!TextUtils.isEmpty(savedSearchFilter)) {
|
||||||
|
searchMenuItem.expandActionView();
|
||||||
|
searchView.setQuery(savedSearchFilter, false);
|
||||||
|
//noinspection RestrictedApi
|
||||||
|
searchView.clearFocus();
|
||||||
|
}
|
||||||
|
|
||||||
|
MenuItemCompat.setOnActionExpandListener(searchMenuItem, new MenuItemCompat.OnActionExpandListener() {
|
||||||
|
@Override
|
||||||
|
public boolean onMenuItemActionExpand(MenuItem item) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onMenuItemActionCollapse(MenuItem item) {
|
||||||
|
searchFilter = savedSearchFilter = null;
|
||||||
|
refreshList();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
//Handle clearing search query using the close button (X button).
|
||||||
|
View view = searchView.findViewById(R.id.search_close_btn);
|
||||||
|
if (view != null) {
|
||||||
|
view.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
EditText editText = (EditText) searchView.findViewById(R.id.search_src_text);
|
||||||
|
editText.setText("");
|
||||||
|
searchView.setQuery("", false);
|
||||||
|
searchFilter = savedSearchFilter = "";
|
||||||
|
refreshList();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Search view callbacks
|
||||||
|
*/
|
||||||
|
/** {@inheritDoc} */
|
||||||
|
@Override
|
||||||
|
public boolean onQueryTextChange(String newText) {
|
||||||
|
if ((!searchView.hasFocus()) && TextUtils.isEmpty(newText)) {
|
||||||
|
//onQueryTextChange called as a result of manually expanding the searchView in setupSearchMenuItem(...)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When this fragment is paused, onQueryTextChange is called with an empty string.
|
||||||
|
* This causes problems restoring the list fragment when returning.
|
||||||
|
*/
|
||||||
|
if (isPaused)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
searchFilter = newText;
|
||||||
|
|
||||||
|
refreshList();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** {@inheritDoc} */
|
||||||
|
@Override
|
||||||
|
public boolean onQueryTextSubmit(String newText) {
|
||||||
|
// All is handled in onQueryTextChange
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
|
switch(item.getItemId()) {
|
||||||
|
case R.id.action_refresh:
|
||||||
|
refreshList();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return super.onOptionsItemSelected(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onResume() {
|
||||||
|
super.onResume();
|
||||||
|
isPaused = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPause() {
|
||||||
|
super.onPause();
|
||||||
|
isPaused = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSaveInstanceState(Bundle outState) {
|
||||||
|
if (!TextUtils.isEmpty(searchFilter)) {
|
||||||
|
savedSearchFilter = searchFilter;
|
||||||
|
}
|
||||||
|
outState.putString(BUNDLE_KEY_SEARCH_QUERY, savedSearchFilter);
|
||||||
|
super.onSaveInstanceState(outState);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Event bus post. Called when the syncing process ended
|
||||||
|
*
|
||||||
|
* @param event Refreshes data
|
||||||
|
*/
|
||||||
|
public void onEventMainThread(MediaSyncEvent event) {
|
||||||
|
onSyncProcessEnded(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void onSyncProcessEnded(MediaSyncEvent event) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use this to reload the items in the list
|
||||||
|
*/
|
||||||
|
protected abstract void refreshList();
|
||||||
|
}
|
|
@ -20,6 +20,7 @@ import android.os.Bundle;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.support.v4.app.Fragment;
|
import android.support.v4.app.Fragment;
|
||||||
import android.support.v4.widget.SwipeRefreshLayout;
|
import android.support.v4.widget.SwipeRefreshLayout;
|
||||||
|
import android.text.TextUtils;
|
||||||
import android.text.format.DateUtils;
|
import android.text.format.DateUtils;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
@ -34,6 +35,7 @@ import org.xbmc.kore.host.HostManager;
|
||||||
import org.xbmc.kore.jsonrpc.ApiCallback;
|
import org.xbmc.kore.jsonrpc.ApiCallback;
|
||||||
import org.xbmc.kore.jsonrpc.method.PVR;
|
import org.xbmc.kore.jsonrpc.method.PVR;
|
||||||
import org.xbmc.kore.jsonrpc.type.PVRType;
|
import org.xbmc.kore.jsonrpc.type.PVRType;
|
||||||
|
import org.xbmc.kore.ui.AbstractSearchableFragment;
|
||||||
import org.xbmc.kore.utils.LogUtils;
|
import org.xbmc.kore.utils.LogUtils;
|
||||||
import org.xbmc.kore.utils.UIUtils;
|
import org.xbmc.kore.utils.UIUtils;
|
||||||
|
|
||||||
|
@ -49,7 +51,7 @@ import butterknife.Unbinder;
|
||||||
/**
|
/**
|
||||||
* Fragment that presents the Guide for a channel
|
* Fragment that presents the Guide for a channel
|
||||||
*/
|
*/
|
||||||
public class PVRChannelEPGListFragment extends Fragment
|
public class PVRChannelEPGListFragment extends AbstractSearchableFragment
|
||||||
implements SwipeRefreshLayout.OnRefreshListener {
|
implements SwipeRefreshLayout.OnRefreshListener {
|
||||||
private static final String TAG = LogUtils.makeLogTag(PVRChannelEPGListFragment.class);
|
private static final String TAG = LogUtils.makeLogTag(PVRChannelEPGListFragment.class);
|
||||||
|
|
||||||
|
@ -113,13 +115,16 @@ public class PVRChannelEPGListFragment extends Fragment
|
||||||
});
|
});
|
||||||
listView.setEmptyView(emptyView);
|
listView.setEmptyView(emptyView);
|
||||||
|
|
||||||
|
super.onCreateView(inflater, container, savedInstanceState);
|
||||||
|
|
||||||
return root;
|
return root;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onActivityCreated (Bundle savedInstanceState) {
|
public void onActivityCreated (Bundle savedInstanceState) {
|
||||||
super.onActivityCreated(savedInstanceState);
|
super.onActivityCreated(savedInstanceState);
|
||||||
setHasOptionsMenu(false);
|
setHasOptionsMenu(true);
|
||||||
|
setSupportsSearch(true);
|
||||||
browseEPG();
|
browseEPG();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -144,6 +149,11 @@ public class PVRChannelEPGListFragment extends Fragment
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void refreshList() {
|
||||||
|
onRefresh();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the EPF for the channel and setup the listview
|
* Get the EPF for the channel and setup the listview
|
||||||
*/
|
*/
|
||||||
|
@ -155,7 +165,10 @@ public class PVRChannelEPGListFragment extends Fragment
|
||||||
if (!isAdded()) return;
|
if (!isAdded()) return;
|
||||||
// To prevent the empty text from appearing on the first load, set it now
|
// To prevent the empty text from appearing on the first load, set it now
|
||||||
emptyView.setText(getString(R.string.no_broadcasts_found_refresh));
|
emptyView.setText(getString(R.string.no_broadcasts_found_refresh));
|
||||||
setupEPGListview(result);
|
|
||||||
|
List<PVRType.DetailsBroadcast> finalResult = filter(result);
|
||||||
|
|
||||||
|
setupEPGListview(finalResult);
|
||||||
swipeRefreshLayout.setRefreshing(false);
|
swipeRefreshLayout.setRefreshing(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -173,6 +186,47 @@ public class PVRChannelEPGListFragment extends Fragment
|
||||||
}, callbackHandler);
|
}, callbackHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private List<PVRType.DetailsBroadcast> filter(List<PVRType.DetailsBroadcast> itemList) {
|
||||||
|
String searchFilter = getSearchFilter();
|
||||||
|
|
||||||
|
if (TextUtils.isEmpty(searchFilter)) {
|
||||||
|
return itemList;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Split searchFilter to multiple lowercase words
|
||||||
|
String[] lcWords = searchFilter.toLowerCase().split(" ");;
|
||||||
|
|
||||||
|
List<PVRType.DetailsBroadcast> result = new ArrayList<>(itemList.size());
|
||||||
|
for (PVRType.DetailsBroadcast item:itemList) {
|
||||||
|
// Require all words to match the item:
|
||||||
|
boolean allWordsMatch = true;
|
||||||
|
for (String lcWord:lcWords) {
|
||||||
|
if (!searchFilterWordMatches(lcWord, item)) {
|
||||||
|
allWordsMatch = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!allWordsMatch) {
|
||||||
|
continue; // skip this item
|
||||||
|
}
|
||||||
|
|
||||||
|
result.add(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean searchFilterWordMatches(String lcWord, PVRType.DetailsBroadcast item) {
|
||||||
|
if (item.title.toLowerCase().contains(lcWord)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (item.plot.toLowerCase().contains(lcWord)){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when we get the Guide
|
* Called when we get the Guide
|
||||||
*
|
*
|
||||||
|
|
|
@ -20,8 +20,8 @@ import android.content.Context;
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.support.v4.app.Fragment;
|
|
||||||
import android.support.v4.widget.SwipeRefreshLayout;
|
import android.support.v4.widget.SwipeRefreshLayout;
|
||||||
|
import android.text.TextUtils;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
@ -41,10 +41,12 @@ import org.xbmc.kore.jsonrpc.ApiException;
|
||||||
import org.xbmc.kore.jsonrpc.method.PVR;
|
import org.xbmc.kore.jsonrpc.method.PVR;
|
||||||
import org.xbmc.kore.jsonrpc.method.Player;
|
import org.xbmc.kore.jsonrpc.method.Player;
|
||||||
import org.xbmc.kore.jsonrpc.type.PVRType;
|
import org.xbmc.kore.jsonrpc.type.PVRType;
|
||||||
|
import org.xbmc.kore.ui.AbstractSearchableFragment;
|
||||||
import org.xbmc.kore.ui.OnBackPressedListener;
|
import org.xbmc.kore.ui.OnBackPressedListener;
|
||||||
import org.xbmc.kore.utils.LogUtils;
|
import org.xbmc.kore.utils.LogUtils;
|
||||||
import org.xbmc.kore.utils.UIUtils;
|
import org.xbmc.kore.utils.UIUtils;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import butterknife.BindView;
|
import butterknife.BindView;
|
||||||
|
@ -54,7 +56,7 @@ import butterknife.Unbinder;
|
||||||
/**
|
/**
|
||||||
* Fragment that presents the movie list
|
* Fragment that presents the movie list
|
||||||
*/
|
*/
|
||||||
public class PVRChannelsListFragment extends Fragment
|
public class PVRChannelsListFragment extends AbstractSearchableFragment
|
||||||
implements SwipeRefreshLayout.OnRefreshListener, OnBackPressedListener {
|
implements SwipeRefreshLayout.OnRefreshListener, OnBackPressedListener {
|
||||||
private static final String TAG = LogUtils.makeLogTag(PVRChannelsListFragment.class);
|
private static final String TAG = LogUtils.makeLogTag(PVRChannelsListFragment.class);
|
||||||
|
|
||||||
|
@ -118,13 +120,16 @@ public class PVRChannelsListFragment extends Fragment
|
||||||
});
|
});
|
||||||
gridView.setEmptyView(emptyView);
|
gridView.setEmptyView(emptyView);
|
||||||
|
|
||||||
|
super.onCreateView(inflater, container, savedInstanceState);
|
||||||
|
|
||||||
return root;
|
return root;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onActivityCreated (Bundle savedInstanceState) {
|
public void onActivityCreated (Bundle savedInstanceState) {
|
||||||
super.onActivityCreated(savedInstanceState);
|
super.onActivityCreated(savedInstanceState);
|
||||||
setHasOptionsMenu(false);
|
setHasOptionsMenu(true);
|
||||||
|
setSupportsSearch(true);
|
||||||
|
|
||||||
if (selectedChannelGroupId == -1) {
|
if (selectedChannelGroupId == -1) {
|
||||||
if ((channelGroupAdapter == null) ||
|
if ((channelGroupAdapter == null) ||
|
||||||
|
@ -174,6 +179,11 @@ public class PVRChannelsListFragment extends Fragment
|
||||||
unbinder.unbind();
|
unbinder.unbind();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void refreshList() {
|
||||||
|
onRefresh();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Swipe refresh layout callback
|
* Swipe refresh layout callback
|
||||||
*/
|
*/
|
||||||
|
@ -252,6 +262,46 @@ public class PVRChannelsListFragment extends Fragment
|
||||||
}, callbackHandler);
|
}, callbackHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private List<PVRType.DetailsChannel> filter(List<PVRType.DetailsChannel> itemList) {
|
||||||
|
String searchFilter = getSearchFilter();
|
||||||
|
|
||||||
|
if (TextUtils.isEmpty(searchFilter)) {
|
||||||
|
return itemList;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Split searchFilter to multiple lowercase words
|
||||||
|
String[] lcWords = searchFilter.toLowerCase().split(" ");;
|
||||||
|
|
||||||
|
List<PVRType.DetailsChannel> result = new ArrayList<>(itemList.size());
|
||||||
|
for (PVRType.DetailsChannel item:itemList) {
|
||||||
|
// Require all words to match the item:
|
||||||
|
boolean allWordsMatch = true;
|
||||||
|
for (String lcWord:lcWords) {
|
||||||
|
if (!searchFilterWordMatches(lcWord, item)) {
|
||||||
|
allWordsMatch = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!allWordsMatch) {
|
||||||
|
continue; // skip this item
|
||||||
|
}
|
||||||
|
|
||||||
|
result.add(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean searchFilterWordMatches(String lcWord, PVRType.DetailsChannel item) {
|
||||||
|
if (item.label.toLowerCase().contains(lcWord)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (item.broadcastnow != null && item.broadcastnow.title.toLowerCase().contains(lcWord)){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when we get the channel groups
|
* Called when we get the channel groups
|
||||||
*
|
*
|
||||||
|
@ -296,7 +346,10 @@ public class PVRChannelsListFragment extends Fragment
|
||||||
|
|
||||||
// To prevent the empty text from appearing on the first load, set it now
|
// To prevent the empty text from appearing on the first load, set it now
|
||||||
emptyView.setText(getString(R.string.no_channels_found_refresh));
|
emptyView.setText(getString(R.string.no_channels_found_refresh));
|
||||||
setupChannelsGridview(result);
|
|
||||||
|
List<PVRType.DetailsChannel> finalResult = filter(result);
|
||||||
|
|
||||||
|
setupChannelsGridview(finalResult);
|
||||||
swipeRefreshLayout.setRefreshing(false);
|
swipeRefreshLayout.setRefreshing(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,8 +21,8 @@ import android.content.res.Resources;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.preference.PreferenceManager;
|
import android.preference.PreferenceManager;
|
||||||
import android.support.v4.app.Fragment;
|
|
||||||
import android.support.v4.widget.SwipeRefreshLayout;
|
import android.support.v4.widget.SwipeRefreshLayout;
|
||||||
|
import android.text.TextUtils;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuInflater;
|
import android.view.MenuInflater;
|
||||||
|
@ -43,6 +43,7 @@ import org.xbmc.kore.jsonrpc.ApiCallback;
|
||||||
import org.xbmc.kore.jsonrpc.method.PVR;
|
import org.xbmc.kore.jsonrpc.method.PVR;
|
||||||
import org.xbmc.kore.jsonrpc.method.Player;
|
import org.xbmc.kore.jsonrpc.method.Player;
|
||||||
import org.xbmc.kore.jsonrpc.type.PVRType;
|
import org.xbmc.kore.jsonrpc.type.PVRType;
|
||||||
|
import org.xbmc.kore.ui.AbstractSearchableFragment;
|
||||||
import org.xbmc.kore.utils.LogUtils;
|
import org.xbmc.kore.utils.LogUtils;
|
||||||
import org.xbmc.kore.utils.UIUtils;
|
import org.xbmc.kore.utils.UIUtils;
|
||||||
|
|
||||||
|
@ -58,7 +59,7 @@ import butterknife.Unbinder;
|
||||||
/**
|
/**
|
||||||
* Fragment that presents the PVR recordings list
|
* Fragment that presents the PVR recordings list
|
||||||
*/
|
*/
|
||||||
public class PVRRecordingsListFragment extends Fragment
|
public class PVRRecordingsListFragment extends AbstractSearchableFragment
|
||||||
implements SwipeRefreshLayout.OnRefreshListener {
|
implements SwipeRefreshLayout.OnRefreshListener {
|
||||||
private static final String TAG = LogUtils.makeLogTag(PVRRecordingsListFragment.class);
|
private static final String TAG = LogUtils.makeLogTag(PVRRecordingsListFragment.class);
|
||||||
|
|
||||||
|
@ -85,6 +86,7 @@ public class PVRRecordingsListFragment extends Fragment
|
||||||
@Override
|
@Override
|
||||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||||
ViewGroup root = (ViewGroup) inflater.inflate(R.layout.fragment_pvr_list, container, false);
|
ViewGroup root = (ViewGroup) inflater.inflate(R.layout.fragment_pvr_list, container, false);
|
||||||
|
|
||||||
unbinder = ButterKnife.bind(this, root);
|
unbinder = ButterKnife.bind(this, root);
|
||||||
|
|
||||||
hostManager = HostManager.getInstance(getActivity());
|
hostManager = HostManager.getInstance(getActivity());
|
||||||
|
@ -99,6 +101,8 @@ public class PVRRecordingsListFragment extends Fragment
|
||||||
});
|
});
|
||||||
gridView.setEmptyView(emptyView);
|
gridView.setEmptyView(emptyView);
|
||||||
|
|
||||||
|
super.onCreateView(inflater, container, savedInstanceState);
|
||||||
|
|
||||||
return root;
|
return root;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,6 +110,7 @@ public class PVRRecordingsListFragment extends Fragment
|
||||||
public void onActivityCreated (Bundle savedInstanceState) {
|
public void onActivityCreated (Bundle savedInstanceState) {
|
||||||
super.onActivityCreated(savedInstanceState);
|
super.onActivityCreated(savedInstanceState);
|
||||||
setHasOptionsMenu(true);
|
setHasOptionsMenu(true);
|
||||||
|
setSupportsSearch(true);
|
||||||
browseRecordings();
|
browseRecordings();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -153,9 +158,7 @@ public class PVRRecordingsListFragment extends Fragment
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* Use this to reload the items in the list
|
|
||||||
*/
|
|
||||||
public void refreshList() {
|
public void refreshList() {
|
||||||
onRefresh();
|
onRefresh();
|
||||||
}
|
}
|
||||||
|
@ -199,7 +202,6 @@ public class PVRRecordingsListFragment extends Fragment
|
||||||
return super.onOptionsItemSelected(item);
|
return super.onOptionsItemSelected(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Swipe refresh layout callback
|
* Swipe refresh layout callback
|
||||||
*/
|
*/
|
||||||
|
@ -243,7 +245,12 @@ public class PVRRecordingsListFragment extends Fragment
|
||||||
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getActivity());
|
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getActivity());
|
||||||
boolean hideWatched = preferences.getBoolean(Settings.KEY_PREF_PVR_RECORDINGS_FILTER_HIDE_WATCHED, Settings.DEFAULT_PREF_PVR_RECORDINGS_FILTER_HIDE_WATCHED);
|
boolean hideWatched = preferences.getBoolean(Settings.KEY_PREF_PVR_RECORDINGS_FILTER_HIDE_WATCHED, Settings.DEFAULT_PREF_PVR_RECORDINGS_FILTER_HIDE_WATCHED);
|
||||||
|
|
||||||
if (!hideWatched) {
|
String searchFilter = getSearchFilter();
|
||||||
|
boolean hasSearchFilter = !TextUtils.isEmpty(searchFilter);
|
||||||
|
// Split searchFilter to multiple lowercase words
|
||||||
|
String[] lcWords = hasSearchFilter ? searchFilter.toLowerCase().split(" ") : null;
|
||||||
|
|
||||||
|
if (!(hideWatched || hasSearchFilter)) {
|
||||||
return itemList;
|
return itemList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -268,7 +275,19 @@ public class PVRRecordingsListFragment extends Fragment
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// more conditions may be added here
|
if (hasSearchFilter) {
|
||||||
|
// Require all lowercase words to match the item:
|
||||||
|
boolean allWordsMatch = true;
|
||||||
|
for (String lcWord:lcWords) {
|
||||||
|
if (!searchFilterWordMatches(lcWord, item)) {
|
||||||
|
allWordsMatch = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!allWordsMatch) {
|
||||||
|
continue; // skip this item
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
result.add(item);
|
result.add(item);
|
||||||
}
|
}
|
||||||
|
@ -276,6 +295,14 @@ public class PVRRecordingsListFragment extends Fragment
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean searchFilterWordMatches(String lcWord, PVRType.DetailsRecording item) {
|
||||||
|
if (item.title.toLowerCase().contains(lcWord)
|
||||||
|
|| item.channel.toLowerCase().contains(lcWord)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
private void sort(List<PVRType.DetailsRecording> itemList) {
|
private void sort(List<PVRType.DetailsRecording> itemList) {
|
||||||
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getActivity());
|
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getActivity());
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue