Add a new smart playlist "Not played lately" playlist (#613)

* Add "Not played lately" playlist (#1)

* Fix bad recent playlist construction (#6)

* Revert History rename

* Code review
This commit is contained in:
soncaokim 2018-12-02 18:30:01 +01:00 committed by Eugene
commit 764751381a
9 changed files with 126 additions and 8 deletions

View file

@ -18,7 +18,7 @@ public class LastAddedLoader {
}
public static Cursor makeLastAddedCursor(@NonNull final Context context) {
long cutoff = PreferenceUtil.getInstance(context).getLastAddedCutoff();
long cutoff = PreferenceUtil.getInstance(context).getLastAddedCutoffTimeSecs();
return SongLoader.makeSongCursor(
context,

View file

@ -19,6 +19,7 @@ package com.kabouzeid.gramophone.loader;
import android.content.Context;
import android.database.Cursor;
import android.provider.BaseColumns;
import android.provider.MediaStore;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
@ -26,6 +27,8 @@ import com.kabouzeid.gramophone.model.Song;
import com.kabouzeid.gramophone.provider.HistoryStore;
import com.kabouzeid.gramophone.provider.SongPlayCountStore;
import com.kabouzeid.gramophone.util.PreferenceUtil;
import java.util.ArrayList;
public class TopAndRecentlyPlayedTracksLoader {
@ -36,6 +39,23 @@ public class TopAndRecentlyPlayedTracksLoader {
return SongLoader.getSongs(makeRecentTracksCursorAndClearUpDatabase(context));
}
@NonNull
public static ArrayList<Song> getNotRecentlyPlayedTracks
(@NonNull Context context) {
ArrayList<Song> allSongs = SongLoader.getSongs(
SongLoader.makeSongCursor(
context,
null, null,
MediaStore.Audio.Media.DATE_ADDED + " ASC"));
ArrayList<Song> recentlyPlayedSongs = SongLoader.getSongs(
makeRecentTracksCursorAndClearUpDatabase(context));
allSongs.removeAll(recentlyPlayedSongs);
return allSongs;
}
@NonNull
public static ArrayList<Song> getTopTracks(@NonNull Context context) {
return SongLoader.getSongs(makeTopTracksCursorAndClearUpDatabase(context));
@ -76,7 +96,8 @@ public class TopAndRecentlyPlayedTracksLoader {
@Nullable
private static SortedLongCursor makeRecentTracksCursorImpl(@NonNull final Context context) {
// first get the top results ids from the internal database
Cursor songs = HistoryStore.getInstance(context).queryRecentIds();
final long cutoff = PreferenceUtil.getInstance(context).getRecentlyPlayedCutoffTimeMillis();
Cursor songs = HistoryStore.getInstance(context).queryRecentIds(cutoff);
try {
return makeSortedCursor(context, songs,

View file

@ -0,0 +1,53 @@
package com.kabouzeid.gramophone.model.smartplaylist;
import android.content.Context;
import android.os.Parcel;
import android.support.annotation.NonNull;
import com.kabouzeid.gramophone.R;
import com.kabouzeid.gramophone.loader.TopAndRecentlyPlayedTracksLoader;
import com.kabouzeid.gramophone.model.Song;
import com.kabouzeid.gramophone.provider.HistoryStore;
import java.util.ArrayList;
/**
* @author SC (soncaokim)
*/
public class NotRecentlyPlayedPlaylist extends AbsSmartPlaylist {
public NotRecentlyPlayedPlaylist(@NonNull Context context) {
super(context.getString(R.string.not_recently_played), R.drawable.ic_library_music_white_24dp);
}
@NonNull
@Override
public ArrayList<Song> getSongs(@NonNull Context context) {
return TopAndRecentlyPlayedTracksLoader.getNotRecentlyPlayedTracks(context);
}
@Override
public void clear(@NonNull Context context) {
HistoryStore.getInstance(context).clear();
}
@Override
public int describeContents() {
return 0;
}
protected NotRecentlyPlayedPlaylist(Parcel in) {
super(in);
}
public static final Creator<NotRecentlyPlayedPlaylist> CREATOR = new Creator<NotRecentlyPlayedPlaylist>() {
public NotRecentlyPlayedPlaylist createFromParcel(Parcel source) {
return new NotRecentlyPlayedPlaylist(source);
}
public NotRecentlyPlayedPlaylist[] newArray(int size) {
return new NotRecentlyPlayedPlaylist[size];
}
};
}

View file

@ -25,7 +25,7 @@ import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
public class HistoryStore extends SQLiteOpenHelper {
private static final int MAX_ITEMS_IN_DB = 100;
private static final int MAX_ITEMS_IN_DB = 5000;
public static final String DATABASE_NAME = "history.db";
private static final int VERSION = 1;
@ -136,10 +136,14 @@ public class HistoryStore extends SQLiteOpenHelper {
return containsId;
}
public Cursor queryRecentIds() {
public Cursor queryRecentIds(long cutoff) {
final SQLiteDatabase database = getReadableDatabase();
return database.query(RecentStoreColumns.NAME,
new String[]{RecentStoreColumns.ID}, null, null, null, null,
new String[]{RecentStoreColumns.ID},
RecentStoreColumns.TIME_PLAYED + ">?",
new String[]{String.valueOf(cutoff)},
null, null,
RecentStoreColumns.TIME_PLAYED + " DESC");
}

View file

@ -16,6 +16,7 @@ import com.kabouzeid.gramophone.model.Playlist;
import com.kabouzeid.gramophone.model.smartplaylist.HistoryPlaylist;
import com.kabouzeid.gramophone.model.smartplaylist.LastAddedPlaylist;
import com.kabouzeid.gramophone.model.smartplaylist.MyTopTracksPlaylist;
import com.kabouzeid.gramophone.model.smartplaylist.NotRecentlyPlayedPlaylist;
import java.util.ArrayList;
@ -80,6 +81,7 @@ public class PlaylistsFragment extends AbsLibraryPagerRecyclerViewFragment<Playl
playlists.add(new LastAddedPlaylist(context));
playlists.add(new HistoryPlaylist(context));
playlists.add(new NotRecentlyPlayedPlaylist(context));
playlists.add(new MyTopTracksPlaylist(context));
playlists.addAll(PlaylistLoader.getAllPlaylists(context));

View file

@ -60,6 +60,7 @@ public final class PreferenceUtil {
public static final String GAPLESS_PLAYBACK = "gapless_playback";
public static final String LAST_ADDED_CUTOFF = "last_added_interval";
public static final String RECENTLY_PLAYED_CUTOFF = "recently_played_interval";
public static final String ALBUM_ART_ON_LOCKSCREEN = "album_art_on_lockscreen";
public static final String BLURRED_ALBUM_ART = "blurred_album_art";
@ -266,11 +267,21 @@ public final class PreferenceUtil {
return mPreferences.getString(GENRE_SORT_ORDER, SortOrder.GenreSortOrder.GENRE_A_Z);
}
public long getLastAddedCutoff() {
// The last added cutoff time is compared against the Android media store timestamps, which is seconds based.
public long getLastAddedCutoffTimeSecs() {
return getCutoffTimeMillis(LAST_ADDED_CUTOFF) / 1000;
}
// The recently played cutoff time is compared against the internal (private) database timestamps, which is milliseconds based.
public long getRecentlyPlayedCutoffTimeMillis() {
return getCutoffTimeMillis(RECENTLY_PLAYED_CUTOFF);
}
private long getCutoffTimeMillis(final String cutoff) {
final CalendarUtil calendarUtil = new CalendarUtil();
long interval;
switch (mPreferences.getString(LAST_ADDED_CUTOFF, "")) {
switch (mPreferences.getString(cutoff, "")) {
case "today":
interval = calendarUtil.getElapsedToday();
break;
@ -293,7 +304,7 @@ public final class PreferenceUtil {
break;
}
return (System.currentTimeMillis() - interval) / 1000;
return (System.currentTimeMillis() - interval);
}
public int getLastSleepTimerValue() {