Last added playlist half working. More to come tomorrow.

This commit is contained in:
Karim Abou Zeid 2015-06-21 01:23:27 +02:00
commit 65c879d64e
47 changed files with 1000 additions and 317 deletions

View file

@ -29,6 +29,10 @@ public abstract class AbsMultiSelectAdapter<VH extends RecyclerView.ViewHolder,
this.context = context;
}
protected void setMultiSelectMenuRes(int menuRes) {
this.menuRes = menuRes;
}
protected void toggleChecked(final int position) {
if (cabHolder != null) {
openCabIfNecessary();
@ -52,7 +56,7 @@ public abstract class AbsMultiSelectAdapter<VH extends RecyclerView.ViewHolder,
}
}
private void uncheckAll() {
private void unCheckAll() {
checked.clear();
notifyDataSetChanged();
}
@ -74,13 +78,13 @@ public abstract class AbsMultiSelectAdapter<VH extends RecyclerView.ViewHolder,
public boolean onCabItemClicked(MenuItem menuItem) {
onMultipleItemAction(menuItem, new ArrayList<>(checked));
cab.finish();
uncheckAll();
unCheckAll();
return true;
}
@Override
public boolean onCabFinished(MaterialCab materialCab) {
uncheckAll();
unCheckAll();
return true;
}

View file

@ -8,6 +8,7 @@ import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.PopupMenu;
import android.widget.TextView;
@ -21,7 +22,9 @@ import com.kabouzeid.gramophone.interfaces.CabHolder;
import com.kabouzeid.gramophone.loader.PlaylistLoader;
import com.kabouzeid.gramophone.loader.PlaylistSongLoader;
import com.kabouzeid.gramophone.model.DataBaseChangedEvent;
import com.kabouzeid.gramophone.model.LastAddedPlaylist;
import com.kabouzeid.gramophone.model.Playlist;
import com.kabouzeid.gramophone.model.SmartPlaylist;
import com.kabouzeid.gramophone.model.Song;
import com.kabouzeid.gramophone.ui.activities.base.AbsFabActivity;
import com.kabouzeid.gramophone.util.NavigationUtil;
@ -30,12 +33,19 @@ import com.squareup.otto.Subscribe;
import java.util.ArrayList;
import java.util.List;
import butterknife.ButterKnife;
import butterknife.InjectView;
/**
* @author Karim Abou Zeid (kabouzeid)
*/
public class PlaylistAdapter extends AbsMultiSelectAdapter<PlaylistAdapter.ViewHolder, Playlist> {
public static final String TAG = PlaylistAdapter.class.getSimpleName();
private int VIEW_TYPE_SMART = 0;
private int VIEW_TYPE_DEFAULT = 1;
protected final AppCompatActivity activity;
protected List<Playlist> dataSet;
@ -46,12 +56,15 @@ public class PlaylistAdapter extends AbsMultiSelectAdapter<PlaylistAdapter.ViewH
}
public void loadDataSet() {
dataSet = PlaylistLoader.getAllPlaylists(activity);
dataSet = new ArrayList<>();
dataSet.add(new LastAddedPlaylist(activity));
dataSet.addAll(PlaylistLoader.getAllPlaylists(activity));
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(activity).inflate(R.layout.item_list_playlist, parent, false);
int layoutRes = viewType == VIEW_TYPE_DEFAULT ? R.layout.item_list_playlist : R.layout.item_list_smart_playlist;
View view = LayoutInflater.from(activity).inflate(layoutRes, parent, false);
return new ViewHolder(view);
}
@ -60,6 +73,19 @@ public class PlaylistAdapter extends AbsMultiSelectAdapter<PlaylistAdapter.ViewH
final Playlist playlist = dataSet.get(position);
holder.playlistName.setText(playlist.name);
holder.view.setActivated(isChecked(playlist));
holder.icon.setImageResource(getIconRes(playlist));
}
private int getIconRes(Playlist playlist) {
if (playlist instanceof SmartPlaylist) {
return ((SmartPlaylist) playlist).iconRes;
}
return R.drawable.ic_queue_music_white_24dp;
}
@Override
public int getItemViewType(int position) {
return dataSet.get(position) instanceof SmartPlaylist ? VIEW_TYPE_SMART : VIEW_TYPE_DEFAULT;
}
@Override
@ -90,28 +116,35 @@ public class PlaylistAdapter extends AbsMultiSelectAdapter<PlaylistAdapter.ViewH
private ArrayList<Song> getSongList(List<Playlist> playlists) {
final ArrayList<Song> songs = new ArrayList<>();
for (Playlist playlist : playlists) {
songs.addAll(PlaylistSongLoader.getPlaylistSongList(activity, playlist.id));
if (playlist instanceof SmartPlaylist) {
songs.addAll(((SmartPlaylist) playlist).getSongs(activity));
} else {
songs.addAll(PlaylistSongLoader.getPlaylistSongList(activity, playlist.id));
}
}
return songs;
}
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener {
public final TextView playlistName;
private final View menu;
private final View view;
@InjectView(R.id.playlist_name)
TextView playlistName;
@InjectView(R.id.menu)
View menu;
@InjectView(R.id.playlist_icon)
ImageView icon;
View view;
public ViewHolder(View itemView) {
super(itemView);
ButterKnife.inject(this, itemView);
view = itemView;
playlistName = (TextView) itemView.findViewById(R.id.playlist_name);
menu = itemView.findViewById(R.id.menu);
view.setOnClickListener(this);
view.setOnLongClickListener(this);
menu.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
PopupMenu popupMenu = new PopupMenu(activity, view);
popupMenu.inflate(R.menu.menu_item_playlist);
popupMenu.inflate(getItemViewType() == VIEW_TYPE_SMART ? R.menu.menu_item_smart_playlist : R.menu.menu_item_playlist);
popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
@ -132,7 +165,8 @@ public class PlaylistAdapter extends AbsMultiSelectAdapter<PlaylistAdapter.ViewH
Pair[] sharedViews = null;
if (activity instanceof AbsFabActivity)
sharedViews = ((AbsFabActivity) activity).getSharedViewsWithFab(null);
NavigationUtil.goToPlaylist(activity, dataSet.get(getAdapterPosition()).id, sharedViews);
Playlist playlist = dataSet.get(getAdapterPosition());
NavigationUtil.goToPlaylist(activity, playlist, sharedViews);
}
}

View file

@ -0,0 +1,156 @@
package com.kabouzeid.gramophone.adapter.songadapter;
import android.support.annotation.Nullable;
import android.support.v4.util.Pair;
import android.support.v7.app.AppCompatActivity;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import com.kabouzeid.gramophone.R;
import com.kabouzeid.gramophone.adapter.AbsMultiSelectAdapter;
import com.kabouzeid.gramophone.dialogs.AddToPlaylistDialog;
import com.kabouzeid.gramophone.helper.MenuItemClickHelper;
import com.kabouzeid.gramophone.helper.MusicPlayerRemote;
import com.kabouzeid.gramophone.interfaces.CabHolder;
import com.kabouzeid.gramophone.model.Song;
import com.kabouzeid.gramophone.ui.activities.base.AbsFabActivity;
import com.kabouzeid.gramophone.util.MusicUtil;
import com.kabouzeid.gramophone.util.NavigationUtil;
import com.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.ImageLoader;
import java.util.ArrayList;
import java.util.List;
/**
* @author Karim Abou Zeid (kabouzeid)
*/
public abstract class AbsPlaylistSongAdapter<S extends Song> extends AbsMultiSelectAdapter<PlaylistSongViewHolder, S> implements PlaylistSongViewHolder.onViewHolderClickListener, PlaylistSongViewHolder.onViewHolderLongClickListener, PlaylistSongViewHolder.onViewHolderMenuItemClickListener {
public static final String TAG = AlbumSongAdapter.class.getSimpleName();
protected final AppCompatActivity activity;
protected ArrayList<S> dataSet;
public AbsPlaylistSongAdapter(AppCompatActivity activity, ArrayList<S> objects, @Nullable CabHolder cabHolder) {
super(activity, cabHolder, R.menu.menu_playlists_songs_selection);
setMultiSelectMenuRes(getMultiSelectMenuRes());
this.activity = activity;
dataSet = objects;
}
public void updateDataSet(ArrayList<S> objects) {
dataSet = objects;
notifyDataSetChanged();
}
protected int getMultiSelectMenuRes() {
return R.menu.menu_playlists_songs_selection;
}
protected int getSongMenuRes() {
return R.menu.menu_item_playlist_song;
}
@Override
public PlaylistSongViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(activity).inflate(R.layout.item_list_song, parent, false);
return new PlaylistSongViewHolder(this, view, getSongMenuRes());
}
@Override
public void onBindViewHolder(final PlaylistSongViewHolder holder, int position) {
final S song = dataSet.get(position);
holder.view.setActivated(isChecked(song));
holder.songTitle.setText(song.title);
holder.songInfo.setText(song.artistName);
ImageLoader.getInstance().displayImage(
MusicUtil.getAlbumArtUri(song.albumId).toString(),
holder.albumArt,
new DisplayImageOptions.Builder()
.cacheInMemory(true)
.showImageOnFail(R.drawable.default_album_art)
.resetViewBeforeLoading(true)
.build()
);
}
@Override
public int getItemCount() {
return dataSet.size();
}
@Override
protected S getIdentifier(int position) {
return dataSet.get(position);
}
@Override
protected void onMultipleItemAction(MenuItem menuItem, ArrayList<S> selection) {
switch (menuItem.getItemId()) {
case R.id.action_delete_from_playlist:
onDeleteFromPlaylist(selection);
break;
case R.id.action_add_to_playlist:
onAddToPlaylist(selection);
break;
case R.id.action_add_to_current_playing:
onAddToCurrentPlaying(selection);
break;
}
}
@Override
public void onClick(View v, int adapterPosition) {
if (isInQuickSelectMode()) {
toggleChecked(adapterPosition);
} else {
//noinspection unchecked
MusicPlayerRemote.openQueue((ArrayList<Song>) (List) dataSet, adapterPosition, true);
}
}
@Override
public boolean onLongClick(View v, int adapterPosition) {
toggleChecked(adapterPosition);
return true;
}
@Override
public boolean onMenuItemClick(MenuItem item, PlaylistSongViewHolder viewHolder, int adapterPosition) {
switch (item.getItemId()) {
case R.id.action_delete_from_playlist:
onDeleteFromPlaylist(dataSet.get(adapterPosition));
return true;
case R.id.action_go_to_album:
Pair[] albumPairs = new Pair[]{
Pair.create(viewHolder.albumArt, activity.getString(R.string.transition_album_cover))
};
if (activity instanceof AbsFabActivity)
albumPairs = ((AbsFabActivity) activity).getSharedViewsWithFab(albumPairs);
NavigationUtil.goToAlbum(activity, dataSet.get(adapterPosition).albumId, albumPairs);
return true;
}
return MenuItemClickHelper.handleSongMenuClick(activity, dataSet.get(adapterPosition), item);
}
protected void onDeleteFromPlaylist(S song) {
}
protected void onDeleteFromPlaylist(ArrayList<S> songs) {
}
protected void onAddToPlaylist(ArrayList<S> songs) {
//noinspection unchecked
AddToPlaylistDialog.create((ArrayList<Song>) (List) songs).show(activity.getSupportFragmentManager(), "ADD_PLAYLIST");
}
protected void onAddToCurrentPlaying(ArrayList<S> songs) {
//noinspection unchecked
MusicPlayerRemote.enqueue((ArrayList<Song>) (List) songs);
}
}

View file

@ -1,165 +1,32 @@
package com.kabouzeid.gramophone.adapter.songadapter;
import android.support.annotation.Nullable;
import android.support.v4.util.Pair;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.PopupMenu;
import android.widget.TextView;
import com.kabouzeid.gramophone.R;
import com.kabouzeid.gramophone.adapter.AbsMultiSelectAdapter;
import com.kabouzeid.gramophone.dialogs.AddToPlaylistDialog;
import com.kabouzeid.gramophone.dialogs.RemoveFromPlaylistDialog;
import com.kabouzeid.gramophone.helper.MenuItemClickHelper;
import com.kabouzeid.gramophone.helper.MusicPlayerRemote;
import com.kabouzeid.gramophone.interfaces.CabHolder;
import com.kabouzeid.gramophone.model.PlaylistSong;
import com.kabouzeid.gramophone.model.Song;
import com.kabouzeid.gramophone.ui.activities.base.AbsFabActivity;
import com.kabouzeid.gramophone.util.MusicUtil;
import com.kabouzeid.gramophone.util.NavigationUtil;
import com.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.ImageLoader;
import java.util.ArrayList;
import java.util.List;
/**
* @author Karim Abou Zeid (kabouzeid)
*/
public class PlaylistSongAdapter extends AbsMultiSelectAdapter<PlaylistSongAdapter.ViewHolder, PlaylistSong> {
public static final String TAG = AlbumSongAdapter.class.getSimpleName();
protected final AppCompatActivity activity;
protected ArrayList<PlaylistSong> dataSet;
public class PlaylistSongAdapter extends AbsPlaylistSongAdapter<PlaylistSong> {
public PlaylistSongAdapter(AppCompatActivity activity, ArrayList<PlaylistSong> objects, @Nullable CabHolder cabHolder) {
super(activity, cabHolder, R.menu.menu_playlists_songs_selection);
this.activity = activity;
dataSet = objects;
}
public void updateDataSet(ArrayList<PlaylistSong> objects) {
dataSet = objects;
notifyDataSetChanged();
super(activity, objects, cabHolder);
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(activity).inflate(R.layout.item_list_song, parent, false);
return new ViewHolder(view);
protected void onDeleteFromPlaylist(ArrayList<PlaylistSong> songs) {
super.onDeleteFromPlaylist(songs);
RemoveFromPlaylistDialog.create(songs).show(activity.getSupportFragmentManager(), "ADD_PLAYLIST");
}
@Override
public void onBindViewHolder(final ViewHolder holder, int position) {
final PlaylistSong song = dataSet.get(position);
holder.view.setActivated(isChecked(song));
holder.songTitle.setText(song.title);
holder.songInfo.setText(song.artistName);
ImageLoader.getInstance().displayImage(
MusicUtil.getAlbumArtUri(song.albumId).toString(),
holder.albumArt,
new DisplayImageOptions.Builder()
.cacheInMemory(true)
.showImageOnFail(R.drawable.default_album_art)
.resetViewBeforeLoading(true)
.build()
);
}
@Override
public int getItemCount() {
return dataSet.size();
}
@Override
protected PlaylistSong getIdentifier(int position) {
return dataSet.get(position);
}
@Override
protected void onMultipleItemAction(MenuItem menuItem, ArrayList<PlaylistSong> selection) {
switch (menuItem.getItemId()) {
case R.id.action_delete_from_playlist:
RemoveFromPlaylistDialog.create(selection).show(activity.getSupportFragmentManager(), "DELETE_FROM_PLAYLIST");
break;
case R.id.action_add_to_playlist:
//noinspection unchecked
AddToPlaylistDialog.create((ArrayList<Song>) (List) selection).show(activity.getSupportFragmentManager(), "ADD_PLAYLIST");
break;
case R.id.action_add_to_current_playing:
//noinspection unchecked
MusicPlayerRemote.enqueue((ArrayList<Song>) (List) selection);
break;
}
}
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener {
final TextView songTitle;
final TextView songInfo;
final ImageView overflowButton;
final ImageView albumArt;
final View view;
public ViewHolder(View itemView) {
super(itemView);
view = itemView;
songTitle = (TextView) itemView.findViewById(R.id.song_title);
songInfo = (TextView) itemView.findViewById(R.id.song_info);
albumArt = (ImageView) itemView.findViewById(R.id.album_art);
view.setOnClickListener(this);
view.setOnLongClickListener(this);
overflowButton = (ImageView) itemView.findViewById(R.id.menu);
overflowButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
PopupMenu popupMenu = new PopupMenu(activity, v);
popupMenu.inflate(R.menu.menu_item_playlist_song);
popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_delete_from_playlist:
RemoveFromPlaylistDialog.create(dataSet.get(getAdapterPosition())).show(activity.getSupportFragmentManager(), "DELETE_FROM_PLAYLIST");
return true;
case R.id.action_go_to_album:
Pair[] albumPairs = new Pair[]{
Pair.create(albumArt, activity.getResources().getString(R.string.transition_album_cover))
};
if (activity instanceof AbsFabActivity)
albumPairs = ((AbsFabActivity) activity).getSharedViewsWithFab(albumPairs);
NavigationUtil.goToAlbum(activity, dataSet.get(getAdapterPosition()).albumId, albumPairs);
return true;
}
return MenuItemClickHelper.handleSongMenuClick(activity, dataSet.get(getAdapterPosition()), item);
}
});
popupMenu.show();
}
});
}
@Override
public void onClick(View v) {
if (isInQuickSelectMode()) {
toggleChecked(getAdapterPosition());
} else {
//noinspection unchecked
MusicPlayerRemote.openQueue((ArrayList<Song>) (List) dataSet, getAdapterPosition(), true);
}
}
@Override
public boolean onLongClick(View view) {
toggleChecked(getAdapterPosition());
return true;
}
protected void onDeleteFromPlaylist(PlaylistSong song) {
super.onDeleteFromPlaylist(song);
RemoveFromPlaylistDialog.create(song).show(activity.getSupportFragmentManager(), "ADD_PLAYLIST");
}
}

View file

@ -0,0 +1,71 @@
package com.kabouzeid.gramophone.adapter.songadapter;
import android.support.v7.widget.RecyclerView;
import android.view.MenuItem;
import android.view.View;
import android.widget.ImageView;
import android.widget.PopupMenu;
import android.widget.TextView;
import com.kabouzeid.gramophone.R;
/**
* @author Karim Abou Zeid (kabouzeid)
*/
public class PlaylistSongViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener {
final TextView songTitle;
final TextView songInfo;
final ImageView overflowButton;
final ImageView albumArt;
final View view;
final AbsPlaylistSongAdapter adapter;
public PlaylistSongViewHolder(final AbsPlaylistSongAdapter adapter, View itemView, final int songMenu) {
super(itemView);
this.adapter = adapter;
view = itemView;
songTitle = (TextView) itemView.findViewById(R.id.song_title);
songInfo = (TextView) itemView.findViewById(R.id.song_info);
albumArt = (ImageView) itemView.findViewById(R.id.album_art);
view.setOnClickListener(this);
view.setOnLongClickListener(this);
overflowButton = (ImageView) itemView.findViewById(R.id.menu);
overflowButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
PopupMenu popupMenu = new PopupMenu(adapter.activity, v);
popupMenu.inflate(songMenu);
popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
return adapter.onMenuItemClick(item, PlaylistSongViewHolder.this, getAdapterPosition());
}
});
popupMenu.show();
}
});
}
@Override
public void onClick(View v) {
adapter.onClick(v, getAdapterPosition());
}
@Override
public boolean onLongClick(View v) {
return adapter.onLongClick(v, getAdapterPosition());
}
protected interface onViewHolderMenuItemClickListener {
boolean onMenuItemClick(MenuItem item, PlaylistSongViewHolder viewHolder, int adapterPosition);
}
protected interface onViewHolderClickListener {
void onClick(View v, int adapterPosition);
}
protected interface onViewHolderLongClickListener {
boolean onLongClick(View v, int adapterPosition);
}
}

View file

@ -0,0 +1,28 @@
package com.kabouzeid.gramophone.adapter.songadapter.smartplaylist;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import com.kabouzeid.gramophone.R;
import com.kabouzeid.gramophone.interfaces.CabHolder;
import com.kabouzeid.gramophone.model.LastAddedPlaylist;
/**
* @author Karim Abou Zeid (kabouzeid)
*/
public class LastAddedSongAdapter extends SmartPlaylistSongAdapter {
public LastAddedSongAdapter(AppCompatActivity activity, @Nullable CabHolder cabHolder) {
super(activity, new LastAddedPlaylist(activity), cabHolder);
}
@Override
protected int getMultiSelectMenuRes() {
return R.menu.menu_last_added_playlist_songs_selection;
}
@Override
protected int getSongMenuRes() {
return R.menu.menu_item_last_added_playlist_song;
}
}

View file

@ -0,0 +1,26 @@
package com.kabouzeid.gramophone.adapter.songadapter.smartplaylist;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import com.kabouzeid.gramophone.adapter.songadapter.AbsPlaylistSongAdapter;
import com.kabouzeid.gramophone.interfaces.CabHolder;
import com.kabouzeid.gramophone.model.SmartPlaylist;
import com.kabouzeid.gramophone.model.Song;
/**
* @author Karim Abou Zeid (kabouzeid)
*/
public abstract class SmartPlaylistSongAdapter extends AbsPlaylistSongAdapter<Song> {
private SmartPlaylist playlist;
public SmartPlaylistSongAdapter(AppCompatActivity activity, SmartPlaylist playlist, @Nullable CabHolder cabHolder) {
super(activity, playlist.getSongs(activity), cabHolder);
this.playlist = playlist;
}
public void updateDataSet() {
updateDataSet(playlist.getSongs(activity));
}
}

View file

@ -1,5 +1,6 @@
package com.kabouzeid.gramophone.helper;
import android.app.Activity;
import android.content.Intent;
import android.support.v4.util.Pair;
import android.support.v7.app.AppCompatActivity;
@ -12,9 +13,11 @@ import com.kabouzeid.gramophone.dialogs.DeleteSongsDialog;
import com.kabouzeid.gramophone.dialogs.RenamePlaylistDialog;
import com.kabouzeid.gramophone.dialogs.SongDetailDialog;
import com.kabouzeid.gramophone.interfaces.PaletteColorHolder;
import com.kabouzeid.gramophone.loader.PlaylistSongLoader;
import com.kabouzeid.gramophone.loader.SongFilePathLoader;
import com.kabouzeid.gramophone.misc.AppKeys;
import com.kabouzeid.gramophone.model.Playlist;
import com.kabouzeid.gramophone.model.SmartPlaylist;
import com.kabouzeid.gramophone.model.Song;
import com.kabouzeid.gramophone.ui.activities.base.AbsFabActivity;
import com.kabouzeid.gramophone.ui.activities.tageditor.SongTagEditorActivity;
@ -22,6 +25,7 @@ import com.kabouzeid.gramophone.util.MusicUtil;
import com.kabouzeid.gramophone.util.NavigationUtil;
import java.io.File;
import java.util.ArrayList;
/**
* @author Karim Abou Zeid (kabouzeid), Aidan Follestad (afollestad)
@ -78,6 +82,12 @@ public class MenuItemClickHelper {
public static boolean handlePlaylistMenuClick(AppCompatActivity activity, Playlist playlist, MenuItem item) {
switch (item.getItemId()) {
case R.id.action_play:
MusicPlayerRemote.openQueue(new ArrayList<>(getPlaylistSongs(activity, playlist)), 0, true);
return true;
case R.id.action_add_to_current_playing:
MusicPlayerRemote.enqueue(new ArrayList<>(getPlaylistSongs(activity, playlist)));
return true;
case R.id.action_rename_playlist:
RenamePlaylistDialog.create(playlist.id).show(activity.getSupportFragmentManager(), "RENAME_PLAYLIST");
return true;
@ -87,4 +97,10 @@ public class MenuItemClickHelper {
}
return false;
}
private static ArrayList<? extends Song> getPlaylistSongs(Activity activity, Playlist playlist) {
return playlist instanceof SmartPlaylist ?
((SmartPlaylist) playlist).getSongs(activity) :
PlaylistSongLoader.getPlaylistSongList(activity, playlist.id);
}
}

View file

@ -14,7 +14,6 @@ import com.kabouzeid.gramophone.model.Song;
import com.kabouzeid.gramophone.service.MusicService;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
/**
@ -207,7 +206,7 @@ public class MusicPlayerRemote {
return false;
}
public static boolean enqueue(List<Song> songs) {
public static boolean enqueue(ArrayList<Song> songs) {
if (musicService != null) {
musicService.addSongs(songs);
final String toast = songs.size() == 1 ? musicService.getResources().getString(R.string.added_title_to_playing_queue) : musicService.getResources().getString(R.string.added_x_titles_to_playing_queue, songs.size());

View file

@ -0,0 +1,55 @@
package com.kabouzeid.gramophone.loader;
import android.content.Context;
import android.database.Cursor;
import android.provider.BaseColumns;
import android.provider.MediaStore;
import android.provider.MediaStore.Audio.AudioColumns;
import com.kabouzeid.gramophone.model.Song;
import com.kabouzeid.gramophone.util.PreferenceUtils;
import java.util.ArrayList;
public class LastAddedLoader {
public static ArrayList<Song> getLastAddedSongs(Context context) {
return SongLoader.getSongs(makeLastAddedCursor(context));
}
public static Cursor makeLastAddedCursor(final Context context) {
long fourWeeksAgo = (System.currentTimeMillis() / 1000) - (4 * 3600 * 24 * 7);
// possible saved timestamp caused by user "clearing" the last added playlist
long cutoff = PreferenceUtils.getInstance(context).getLastAddedCutOff() / 1000;
if (cutoff < fourWeeksAgo) {
cutoff = fourWeeksAgo;
}
//noinspection StringBufferReplaceableByString
final StringBuilder selection = new StringBuilder();
selection.append(AudioColumns.IS_MUSIC + "=1");
selection.append(" AND " + AudioColumns.TITLE + " != ''");
selection.append(" AND " + MediaStore.Audio.Media.DATE_ADDED + ">");
selection.append(cutoff);
return context.getContentResolver().query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
new String[]{
/* 0 */
BaseColumns._ID,
/* 1 */
MediaStore.Audio.AudioColumns.TITLE,
/* 2 */
MediaStore.Audio.AudioColumns.ARTIST,
/* 3 */
MediaStore.Audio.AudioColumns.ALBUM,
/* 4 */
MediaStore.Audio.AudioColumns.DURATION,
/* 5 */
MediaStore.Audio.AudioColumns.TRACK,
/* 6 */
MediaStore.Audio.AudioColumns.ARTIST_ID,
/* 7 */
MediaStore.Audio.AudioColumns.ALBUM_ID
}, selection.toString(), null, MediaStore.Audio.Media.DATE_ADDED + " DESC");
}
}

View file

@ -0,0 +1,23 @@
package com.kabouzeid.gramophone.model;
import android.content.Context;
import com.kabouzeid.gramophone.R;
import com.kabouzeid.gramophone.loader.LastAddedLoader;
import java.util.ArrayList;
/**
* @author Karim Abou Zeid (kabouzeid)
*/
public class LastAddedPlaylist extends SmartPlaylist {
public LastAddedPlaylist(Context context) {
super(context.getString(R.string.last_added), R.drawable.ic_queue_white_24dp);
}
@Override
public ArrayList<Song> getSongs(Context context) {
return LastAddedLoader.getLastAddedSongs(context);
}
}

View file

@ -0,0 +1,50 @@
package com.kabouzeid.gramophone.model;
import android.content.Context;
import android.support.annotation.DrawableRes;
import com.kabouzeid.gramophone.R;
import java.util.ArrayList;
/**
* @author Karim Abou Zeid (kabouzeid)
*/
public abstract class SmartPlaylist extends Playlist {
private static final long serialVersionUID = 3013701295356403681L;
@DrawableRes
public final int iconRes;
public SmartPlaylist(final String name, final int iconRes) {
super(-1, name);
this.iconRes = iconRes;
}
public SmartPlaylist() {
super();
this.iconRes = R.drawable.ic_queue_music_white_24dp;
}
public abstract ArrayList<Song> getSongs(Context context);
@Override
public int hashCode() {
final int prime = 31;
int result = super.hashCode();
result = prime * result + iconRes;
return result;
}
@Override
public boolean equals(final Object obj) {
if (super.equals(obj)) {
if (getClass() != obj.getClass()) {
return false;
}
final SmartPlaylist other = (SmartPlaylist) obj;
return iconRes == other.iconRes;
}
return false;
}
}

View file

@ -59,7 +59,6 @@ import com.nostra13.universalimageloader.core.ImageLoader;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import butterknife.ButterKnife;
@ -419,8 +418,9 @@ public class MainActivity extends AbsFabActivity
final int id = (int) parseIdFromIntent(intent, "playlistId", "playlist");
if (id >= 0) {
int position = intent.getIntExtra("position", 0);
//noinspection unchecked
MusicPlayerRemote.openQueue((ArrayList<Song>) (List<? extends Song>) PlaylistSongLoader.getPlaylistSongList(this, id), position, true);
ArrayList<Song> songs = new ArrayList<>();
songs.addAll(PlaylistSongLoader.getPlaylistSongList(this, id));
MusicPlayerRemote.openQueue(songs, position, true);
handled = true;
}
} else if (MediaStore.Audio.Albums.CONTENT_TYPE.equals(mimeType)) {

View file

@ -13,9 +13,7 @@ import com.kabouzeid.gramophone.App;
import com.kabouzeid.gramophone.R;
import com.kabouzeid.gramophone.adapter.songadapter.PlaylistSongAdapter;
import com.kabouzeid.gramophone.interfaces.CabHolder;
import com.kabouzeid.gramophone.loader.PlaylistLoader;
import com.kabouzeid.gramophone.loader.PlaylistSongLoader;
import com.kabouzeid.gramophone.misc.AppKeys;
import com.kabouzeid.gramophone.misc.DragSortRecycler;
import com.kabouzeid.gramophone.model.DataBaseChangedEvent;
import com.kabouzeid.gramophone.model.Playlist;
@ -32,6 +30,8 @@ public class PlaylistDetailActivity extends AbsFabActivity implements CabHolder
public static final String TAG = PlaylistDetailActivity.class.getSimpleName();
public static String EXTRA_PLAYLIST = "extra_playlist";
private Playlist playlist;
private MaterialCab cab;
private PlaylistSongAdapter adapter;
@ -86,8 +86,10 @@ public class PlaylistDetailActivity extends AbsFabActivity implements CabHolder
private void getIntentExtras() {
Bundle intentExtras = getIntent().getExtras();
final int playlistId = intentExtras.getInt(AppKeys.E_PLAYLIST);
playlist = PlaylistLoader.getPlaylist(this, playlistId);
try {
playlist = (Playlist) intentExtras.getSerializable(EXTRA_PLAYLIST);
} catch (ClassCastException ignored) {
}
if (playlist == null) {
finish();
}
@ -120,6 +122,9 @@ public class PlaylistDetailActivity extends AbsFabActivity implements CabHolder
case R.id.action_playing_queue:
NavigationUtil.openPlayingQueueDialog(this);
return true;
case R.id.action_clear_playlist:
//TODO
return true;
}
return super.onOptionsItemSelected(item);
}

View file

@ -0,0 +1,162 @@
package com.kabouzeid.gramophone.ui.activities;
import android.os.Bundle;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.TextView;
import com.afollestad.materialcab.MaterialCab;
import com.kabouzeid.gramophone.App;
import com.kabouzeid.gramophone.R;
import com.kabouzeid.gramophone.adapter.songadapter.smartplaylist.LastAddedSongAdapter;
import com.kabouzeid.gramophone.adapter.songadapter.smartplaylist.SmartPlaylistSongAdapter;
import com.kabouzeid.gramophone.interfaces.CabHolder;
import com.kabouzeid.gramophone.model.DataBaseChangedEvent;
import com.kabouzeid.gramophone.model.SmartPlaylist;
import com.kabouzeid.gramophone.ui.activities.base.AbsFabActivity;
import com.kabouzeid.gramophone.util.NavigationUtil;
import com.kabouzeid.gramophone.util.PreferenceUtils;
import com.squareup.otto.Subscribe;
import butterknife.ButterKnife;
import butterknife.InjectView;
public class SmartPlaylistDetailActivity extends AbsFabActivity implements CabHolder {
public static final String TAG = SmartPlaylistDetailActivity.class.getSimpleName();
@InjectView(R.id.recycler_view)
RecyclerView recyclerView;
@InjectView(R.id.toolbar)
Toolbar toolbar;
@InjectView(android.R.id.empty)
TextView empty;
private SmartPlaylist playlist;
private MaterialCab cab;
private SmartPlaylistSongAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_playlist_detail);
ButterKnife.inject(this);
getIntentExtras();
setUpRecyclerView();
checkIsEmpty();
setUpToolBar();
if (PreferenceUtils.getInstance(this).coloredNavigationBarPlaylist())
setNavigationBarThemeColor();
setStatusBarThemeColor();
App.bus.register(this);
}
private void setUpRecyclerView() {
adapter = new LastAddedSongAdapter(this, this);
recyclerView.setLayoutManager(new GridLayoutManager(this, 1));
recyclerView.setAdapter(adapter);
}
private void setUpToolBar() {
toolbar.setBackgroundColor(getThemeColorPrimary());
setSupportActionBar(toolbar);
//noinspection ConstantConditions
getSupportActionBar().setTitle(playlist.name);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}
private void getIntentExtras() {
Bundle intentExtras = getIntent().getExtras();
try {
playlist = (SmartPlaylist) intentExtras.getSerializable(PlaylistDetailActivity.EXTRA_PLAYLIST);
} catch (ClassCastException ignored) {
}
if (playlist == null) {
finish();
}
}
@Override
public String getTag() {
return TAG;
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_playlist_detail, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
switch (id) {
case R.id.action_equalizer:
NavigationUtil.openEqualizer(this);
return true;
case android.R.id.home:
super.onBackPressed();
return true;
case R.id.action_current_playing:
NavigationUtil.openCurrentPlayingIfPossible(this, getSharedViewsWithFab(null));
return true;
case R.id.action_playing_queue:
NavigationUtil.openPlayingQueueDialog(this);
return true;
case R.id.action_clear_playlist:
//TODO
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
public MaterialCab openCab(final int menu, final MaterialCab.Callback callback) {
if (cab != null && cab.isActive()) cab.finish();
cab = new MaterialCab(this, R.id.cab_stub)
.setMenu(menu)
.setBackgroundColor(PreferenceUtils.getInstance(this).getThemeColorPrimary())
.start(callback);
return cab;
}
@Override
protected void onDestroy() {
super.onDestroy();
App.bus.unregister(this);
}
@Subscribe
public void onDataBaseEvent(DataBaseChangedEvent event) {
switch (event.getAction()) {
case DataBaseChangedEvent.PLAYLISTS_CHANGED:
case DataBaseChangedEvent.DATABASE_CHANGED:
adapter.updateDataSet();
checkIsEmpty();
break;
}
}
@Override
public void onBackPressed() {
if (cab != null && cab.isActive()) cab.finish();
else super.onBackPressed();
}
private void checkIsEmpty() {
empty.setVisibility(
adapter.getItemCount() == 0 ? View.VISIBLE : View.GONE
);
}
}

View file

@ -1,6 +1,7 @@
package com.kabouzeid.gramophone.ui.fragments.mainactivityfragments;
import android.os.Bundle;
import android.support.annotation.LayoutRes;
import android.support.annotation.StringRes;
import android.support.design.widget.AppBarLayout;
import android.support.design.widget.AppBarLayout.OnOffsetChangedListener;
@ -15,38 +16,49 @@ import android.widget.TextView;
import com.kabouzeid.gramophone.R;
import com.kabouzeid.gramophone.views.FastScroller;
import butterknife.ButterKnife;
import butterknife.InjectView;
import butterknife.Optional;
/**
* @author Karim Abou Zeid (kabouzeid)
*/
public abstract class AbsMainActivityRecyclerViewFragment extends AbsMainActivityFragment implements OnOffsetChangedListener {
public static final String TAG = AbsMainActivityRecyclerViewFragment.class.getSimpleName();
private RecyclerView recyclerView;
@InjectView(R.id.recycler_view)
RecyclerView recyclerView;
@Optional
@InjectView(android.R.id.empty)
TextView empty;
@Optional
@InjectView(R.id.fast_scroller)
FastScroller fastScroller;
private RecyclerView.Adapter mAdapter;
private FastScroller fastScroller;
private TextView empty;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_main_activity_recycler_view, container, false);
View view = inflater.inflate(getLayoutRes(), container, false);
ButterKnife.inject(this, view);
return view;
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
recyclerView = (RecyclerView) view.findViewById(R.id.recycler_view);
fastScroller = (FastScroller) view.findViewById(R.id.fast_scroller);
empty = (TextView) view.findViewById(android.R.id.empty);
fastScroller.setRecyclerView(recyclerView);
fastScroller.setPressedHandleColor(getMainActivity().getThemeColorPrimary());
fastScroller.setOnHandleTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
return false;
}
});
if (fastScroller != null) {
fastScroller.setRecyclerView(recyclerView);
fastScroller.setPressedHandleColor(getMainActivity().getThemeColorPrimary());
fastScroller.setOnHandleTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
return false;
}
});
}
getMainActivity().addOnAppBarOffsetChangedListener(this);
@ -75,9 +87,11 @@ public abstract class AbsMainActivityRecyclerViewFragment extends AbsMainActivit
@Override
public void onOffsetChanged(AppBarLayout appBarLayout, int i) {
FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) fastScroller.getLayoutParams();
params.setMargins(params.leftMargin, params.topMargin, params.rightMargin, getMainActivity().getTotalAppBarScrollingRange() + i);
fastScroller.setLayoutParams(params);
if (fastScroller != null) {
FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) fastScroller.getLayoutParams();
params.setMargins(params.leftMargin, params.topMargin, params.rightMargin, getMainActivity().getTotalAppBarScrollingRange() + i);
fastScroller.setLayoutParams(params);
}
}
@Override
@ -93,10 +107,12 @@ public abstract class AbsMainActivityRecyclerViewFragment extends AbsMainActivit
}
private void showEmptyMessageIfEmpty() {
RecyclerView.Adapter adapter = getAdapter();
if (adapter != null) {
empty.setText(getEmptyMessage());
empty.setVisibility(adapter.getItemCount() == 0 ? View.VISIBLE : View.GONE);
if (empty != null) {
RecyclerView.Adapter adapter = getAdapter();
if (adapter != null) {
empty.setText(getEmptyMessage());
empty.setVisibility(adapter.getItemCount() == 0 ? View.VISIBLE : View.GONE);
}
}
}
@ -105,7 +121,22 @@ public abstract class AbsMainActivityRecyclerViewFragment extends AbsMainActivit
return R.string.empty;
}
@LayoutRes
protected int getLayoutRes() {
return R.layout.fragment_main_activity_recycler_view;
}
protected RecyclerView getRecyclerView() {
return recyclerView;
}
protected abstract RecyclerView.LayoutManager createLayoutManager();
protected abstract RecyclerView.Adapter createAdapter();
@Override
public void onDestroyView() {
super.onDestroyView();
ButterKnife.reset(this);
}
}

View file

@ -15,10 +15,13 @@ import com.kabouzeid.gramophone.dialogs.PlayingQueueDialog;
import com.kabouzeid.gramophone.helper.MusicPlayerRemote;
import com.kabouzeid.gramophone.interfaces.KabViewsDisableAble;
import com.kabouzeid.gramophone.misc.AppKeys;
import com.kabouzeid.gramophone.model.Playlist;
import com.kabouzeid.gramophone.model.SmartPlaylist;
import com.kabouzeid.gramophone.ui.activities.AlbumDetailActivity;
import com.kabouzeid.gramophone.ui.activities.ArtistDetailActivity;
import com.kabouzeid.gramophone.ui.activities.MusicControllerActivity;
import com.kabouzeid.gramophone.ui.activities.PlaylistDetailActivity;
import com.kabouzeid.gramophone.ui.activities.SmartPlaylistDetailActivity;
/**
* @author Karim Abou Zeid (kabouzeid)
@ -63,12 +66,19 @@ public class NavigationUtil {
}
}
public static void goToPlaylist(final Activity activity, final int playlistId, final Pair[] sharedViews) {
public static void goToPlaylist(final Activity activity, final Playlist playlist, final Pair[] sharedViews) {
if ((activity instanceof KabViewsDisableAble && ((KabViewsDisableAble) activity).areViewsEnabled()) || !(activity instanceof KabViewsDisableAble)) {
if (activity instanceof KabViewsDisableAble)
((KabViewsDisableAble) activity).disableViews();
final Intent intent = new Intent(activity, PlaylistDetailActivity.class);
intent.putExtra(AppKeys.E_PLAYLIST, playlistId);
final Intent intent;
if (playlist instanceof SmartPlaylist) {
intent = new Intent(activity, SmartPlaylistDetailActivity.class);
} else {
intent = new Intent(activity, PlaylistDetailActivity.class);
}
intent.putExtra(PlaylistDetailActivity.EXTRA_PLAYLIST, playlist);
if (sharedViews != null) {
@SuppressWarnings("unchecked") ActivityOptionsCompat optionsCompat = ActivityOptionsCompat.makeSceneTransitionAnimation(activity,
sharedViews

View file

@ -24,9 +24,6 @@ import java.util.List;
*/
public class PlaylistsUtil {
// public static final String MUSIC_ONLY_SELECTION = MediaStore.Audio.AudioColumns.IS_MUSIC + "=1"
// + " AND " + MediaStore.Audio.AudioColumns.TITLE + " != ''"; //$NON-NLS-2$
public static int createPlaylist(final Context context, final String name) {
if (name != null && name.length() > 0) {
final ContentResolver resolver = context.getContentResolver();
@ -61,13 +58,13 @@ public class PlaylistsUtil {
// context.getContentResolver().delete(uri, null, null);
// }
public static void deletePlaylists(final Context context, final long playlistId) {
final Uri uri = MediaStore.Audio.Playlists.EXTERNAL_CONTENT_URI;
String where = MediaStore.Audio.Playlists._ID + "=?";
String[] whereVal = {String.valueOf(playlistId)};
context.getContentResolver().delete(uri, where, whereVal);
App.bus.post(new DataBaseChangedEvent(DataBaseChangedEvent.PLAYLISTS_CHANGED));
}
// public static void deletePlaylists(final Context context, final long playlistId) {
// final Uri uri = MediaStore.Audio.Playlists.EXTERNAL_CONTENT_URI;
// String where = MediaStore.Audio.Playlists._ID + "=?";
// String[] whereVal = {String.valueOf(playlistId)};
// context.getContentResolver().delete(uri, where, whereVal);
// App.bus.post(new DataBaseChangedEvent(DataBaseChangedEvent.PLAYLISTS_CHANGED));
// }
public static void deletePlaylists(final Context context, final ArrayList<Playlist> playlists) {
final Uri uri = MediaStore.Audio.Playlists.EXTERNAL_CONTENT_URI;
@ -136,19 +133,20 @@ public class PlaylistsUtil {
return contentValues;
}
public static void removeFromPlaylist(final Context context, final PlaylistSong song) {
Uri uri = MediaStore.Audio.Playlists.Members.getContentUri(
"external", song.playlistId);
String selection = MediaStore.Audio.Playlists.Members._ID + " =?";
String[] selectionArgs = new String[]{String.valueOf(song.idInPlayList)};
context.getContentResolver().delete(uri, selection, selectionArgs);
App.bus.post(new DataBaseChangedEvent(DataBaseChangedEvent.PLAYLISTS_CHANGED));
}
// public static void removeFromPlaylist(final Context context, final PlaylistSong song) {
// Uri uri = MediaStore.Audio.Playlists.Members.getContentUri(
// "external", song.playlistId);
// String selection = MediaStore.Audio.Playlists.Members._ID + " =?";
// String[] selectionArgs = new String[]{String.valueOf(song.idInPlayList)};
//
// context.getContentResolver().delete(uri, selection, selectionArgs);
// App.bus.post(new DataBaseChangedEvent(DataBaseChangedEvent.PLAYLISTS_CHANGED));
// }
public static void removeFromPlaylist(final Context context, final List<PlaylistSong> songs) {
final int playlistId = songs.get(0).playlistId;
Uri uri = MediaStore.Audio.Playlists.Members.getContentUri(
"external", songs.get(0).playlistId);
"external", playlistId);
String selectionArgs[] = new String[songs.size()];
for (int i = 0; i < selectionArgs.length; i++) {
selectionArgs[i] = String.valueOf(songs.get(i).idInPlayList);

View file

@ -43,6 +43,7 @@ public final class PreferenceUtils {
public static final String FADE_PLAY_PAUSE = "fade_play_pause";
public static final String COLORED_NOTIFICATION = "colored_notification";
public static final String GAPLESS_PLAYBACK = "gapless_playback";
public static final String LAST_ADDED_CUTOFF_TIMESTAMP = "last_added_cutoff_timestamp";
private static PreferenceUtils sInstance;
@ -283,4 +284,15 @@ public final class PreferenceUtils {
public final int getAlbumGridColumnsLand() {
return mPreferences.getInt(ALBUM_GRID_COLUMNS_LAND, 3);
}
public long getLastAddedCutOff() {
return mPreferences.getLong(LAST_ADDED_CUTOFF_TIMESTAMP, 0L);
}
@SuppressLint("CommitPrefEdits")
public void setLastAddedCutoffTimestamp(final long timestamp) {
final SharedPreferences.Editor editor = mPreferences.edit();
editor.putLong(LAST_ADDED_CUTOFF_TIMESTAMP, timestamp);
editor.commit();
}
}