@ -16,12 +16,17 @@
package org.xbmc.kore.ui.sections.video ;
import android.content.Context ;
import android.content.SharedPreferences ;
import android.content.res.Resources ;
import android.os.Bundle ;
import android.os.Handler ;
import android.preference.PreferenceManager ;
import android.support.v4.app.Fragment ;
import android.support.v4.widget.SwipeRefreshLayout ;
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.AdapterView ;
@ -32,6 +37,7 @@ import android.widget.TextView;
import android.widget.Toast ;
import org.xbmc.kore.R ;
import org.xbmc.kore.Settings ;
import org.xbmc.kore.host.HostManager ;
import org.xbmc.kore.jsonrpc.ApiCallback ;
import org.xbmc.kore.jsonrpc.method.PVR ;
@ -40,6 +46,9 @@ import org.xbmc.kore.jsonrpc.type.PVRType;
import org.xbmc.kore.utils.LogUtils ;
import org.xbmc.kore.utils.UIUtils ;
import java.util.ArrayList ;
import java.util.Collections ;
import java.util.Comparator ;
import java.util.List ;
import butterknife.BindView ;
@ -96,7 +105,7 @@ public class PVRRecordingsListFragment extends Fragment
@Override
public void onActivityCreated ( Bundle savedInstanceState ) {
super . onActivityCreated ( savedInstanceState ) ;
setHasOptionsMenu ( fals e) ;
setHasOptionsMenu ( tru e) ;
browseRecordings ( ) ;
}
@ -106,6 +115,91 @@ public class PVRRecordingsListFragment extends Fragment
unbinder . unbind ( ) ;
}
@Override
public void onCreateOptionsMenu ( Menu menu , MenuInflater inflater ) {
if ( ! isAdded ( ) ) {
// HACK: Fix crash reported on Play Store. Why does this is necessary is beyond me
// copied from MovieListFragment#onCreateOptionsMenu
super . onCreateOptionsMenu ( menu , inflater ) ;
return ;
}
inflater . inflate ( R . menu . pvr_recording_list , menu ) ;
// Setup filters
MenuItem hideWatched = menu . findItem ( R . id . action_hide_watched ) ,
sortByNameAndDate = menu . findItem ( R . id . action_sort_by_name_and_date_added ) ,
sortByDateAdded = menu . findItem ( R . id . action_sort_by_date_added ) ,
unsorted = menu . findItem ( R . id . action_unsorted ) ;
SharedPreferences preferences = PreferenceManager . getDefaultSharedPreferences ( getActivity ( ) ) ;
hideWatched . setChecked ( preferences . getBoolean ( Settings . KEY_PREF_PVR_RECORDINGS_FILTER_HIDE_WATCHED , Settings . DEFAULT_PREF_PVR_RECORDINGS_FILTER_HIDE_WATCHED ) ) ;
int sortOrder = preferences . getInt ( Settings . KEY_PREF_PVR_RECORDINGS_SORT_ORDER , Settings . DEFAULT_PREF_PVR_RECORDINGS_SORT_ORDER ) ;
switch ( sortOrder ) {
case Settings . SORT_BY_DATE_ADDED :
sortByDateAdded . setChecked ( true ) ;
break ;
case Settings . SORT_BY_NAME :
sortByNameAndDate . setChecked ( true ) ;
break ;
default :
unsorted . setChecked ( true ) ;
break ;
}
super . onCreateOptionsMenu ( menu , inflater ) ;
}
/ * *
* Use this to reload the items in the list
* /
public void refreshList ( ) {
onRefresh ( ) ;
}
@Override
public boolean onOptionsItemSelected ( MenuItem item ) {
SharedPreferences preferences = PreferenceManager . getDefaultSharedPreferences ( getActivity ( ) ) ;
switch ( item . getItemId ( ) ) {
case R . id . action_hide_watched :
item . setChecked ( ! item . isChecked ( ) ) ;
preferences . edit ( )
. putBoolean ( Settings . KEY_PREF_PVR_RECORDINGS_FILTER_HIDE_WATCHED , item . isChecked ( ) )
. apply ( ) ;
refreshList ( ) ;
break ;
case R . id . action_sort_by_name_and_date_added :
item . setChecked ( true ) ;
preferences . edit ( )
. putInt ( Settings . KEY_PREF_PVR_RECORDINGS_SORT_ORDER , Settings . SORT_BY_NAME )
. apply ( ) ;
refreshList ( ) ;
break ;
case R . id . action_sort_by_date_added :
item . setChecked ( true ) ;
preferences . edit ( )
. putInt ( Settings . KEY_PREF_PVR_RECORDINGS_SORT_ORDER , Settings . SORT_BY_DATE_ADDED )
. apply ( ) ;
refreshList ( ) ;
break ;
case R . id . action_unsorted :
item . setChecked ( true ) ;
preferences . edit ( )
. putInt ( Settings . KEY_PREF_PVR_RECORDINGS_SORT_ORDER , Settings . UNSORTED )
. apply ( ) ;
refreshList ( ) ;
break ;
default :
break ;
}
return super . onOptionsItemSelected ( item ) ;
}
/ * *
* Swipe refresh layout callback
* /
@ -134,10 +228,90 @@ public class PVRRecordingsListFragment extends Fragment
// To prevent the empty text from appearing on the first load, set it now
emptyView . setText ( getString ( R . string . no_recordings_found_refresh ) ) ;
setupRecordingsGridview ( result ) ;
// As the JSON RPC API does not support sorting or filter parameters for PVR.GetRecordings
// we apply the sorting and filtering right here.
// See https://kodi.wiki/view/JSON-RPC_API/v9#PVR.GetRecordings
List < PVRType . DetailsRecording > finalResult = filter ( result ) ;
sort ( finalResult ) ;
setupRecordingsGridview ( finalResult ) ;
swipeRefreshLayout . setRefreshing ( false ) ;
}
private List < PVRType . DetailsRecording > filter ( List < PVRType . DetailsRecording > itemList ) {
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 ) ;
if ( ! hideWatched ) {
return itemList ;
}
List < PVRType . DetailsRecording > result = new ArrayList < > ( itemList . size ( ) ) ;
for ( PVRType . DetailsRecording item : itemList ) {
if ( hideWatched ) {
if ( item . playcount > 0 ) {
continue ; // Skip this item as it is played.
} else {
// Heuristic: Try to guess if it's play from resume timestamp.
double resumePosition = item . resume . position ;
int runtime = item . runtime ;
if ( runtime < resumePosition ) {
// Tv show duration is smaller than resume position.
// The tv show likely has been watched.
// It's still possible some minutes have not yet been watched
// at the end of the show as some minutes at the
// recording start do not belong to the show.
// Never the less skip this item.
continue ;
}
}
}
// more conditions may be added here
result . add ( item ) ;
}
return result ;
}
private void sort ( List < PVRType . DetailsRecording > itemList ) {
SharedPreferences preferences = PreferenceManager . getDefaultSharedPreferences ( getActivity ( ) ) ;
int sortOrder = preferences . getInt ( Settings . KEY_PREF_PVR_RECORDINGS_SORT_ORDER , Settings . DEFAULT_PREF_PVR_RECORDINGS_SORT_ORDER ) ;
Comparator < PVRType . DetailsRecording > comparator ;
switch ( sortOrder ) {
case Settings . SORT_BY_DATE_ADDED :
// sort by recording start time descending (most current first)
// luckily the starttime is in sortable format yyyy-MM-dd hh:mm:ss
comparator = new Comparator < PVRType . DetailsRecording > ( ) {
@Override
public int compare ( PVRType . DetailsRecording a , PVRType . DetailsRecording b ) {
return b . starttime . compareTo ( a . starttime ) ;
}
} ;
Collections . sort ( itemList , comparator ) ;
break ;
case Settings . SORT_BY_NAME :
// sort by recording title and start time
comparator = new Comparator < PVRType . DetailsRecording > ( ) {
@Override
public int compare ( PVRType . DetailsRecording a , PVRType . DetailsRecording b ) {
int result = a . title . compareToIgnoreCase ( b . title ) ;
if ( 0 = = result ) { // note the yoda condition ;)
// sort by starttime descending (most current first)
result = b . starttime . compareTo ( a . starttime ) ;
}
return result ;
}
} ;
Collections . sort ( itemList , comparator ) ;
break ;
}
}
@Override
public void onError ( int errorCode , String description ) {
if ( ! isAdded ( ) ) return ;