Merge branch 'arkon-playlist-length'

This commit is contained in:
Karim Abou Zeid 2017-07-24 19:16:04 +02:00
commit cadc7ac469
7 changed files with 303 additions and 213 deletions

View file

@ -0,0 +1,110 @@
package com.kabouzeid.gramophone.adapter.song;
import android.support.annotation.LayoutRes;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.kabouzeid.gramophone.R;
import com.kabouzeid.gramophone.helper.MusicPlayerRemote;
import com.kabouzeid.gramophone.interfaces.CabHolder;
import com.kabouzeid.gramophone.model.Song;
import java.util.ArrayList;
/**
* @author Eugene Cheung (arkon)
*/
public abstract class AbsOffsetSongAdapter extends SongAdapter {
protected static final int OFFSET_ITEM = 0;
protected static final int SONG = 1;
public AbsOffsetSongAdapter(AppCompatActivity activity, ArrayList<Song> dataSet, @LayoutRes int itemLayoutRes, boolean usePalette, @Nullable CabHolder cabHolder) {
super(activity, dataSet, itemLayoutRes, usePalette, cabHolder);
}
public AbsOffsetSongAdapter(AppCompatActivity activity, ArrayList<Song> dataSet, @LayoutRes int itemLayoutRes, boolean usePalette, @Nullable CabHolder cabHolder, boolean showSectionName) {
super(activity, dataSet, itemLayoutRes, usePalette, cabHolder, showSectionName);
}
@NonNull
@Override
public SongAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (viewType == OFFSET_ITEM) {
View view = LayoutInflater.from(activity).inflate(R.layout.item_list_single_row, parent, false);
return createViewHolder(view);
}
return super.onCreateViewHolder(parent, viewType);
}
@Override
protected SongAdapter.ViewHolder createViewHolder(View view) {
return new AbsOffsetSongAdapter.ViewHolder(view);
}
@Override
public long getItemId(int position) {
position--;
if (position < 0) return -2;
return super.getItemId(position);
}
@Override
protected Song getIdentifier(int position) {
position--;
if (position < 0) return Song.EMPTY_SONG;
return super.getIdentifier(position);
}
@Override
public int getItemCount() {
int superItemCount = super.getItemCount();
return superItemCount == 0 ? 0 : superItemCount + 1;
}
@Override
public int getItemViewType(int position) {
return position == 0 ? OFFSET_ITEM : SONG;
}
@NonNull
@Override
public String getSectionName(int position) {
position--;
if (position < 0) return "";
return super.getSectionName(position);
}
public class ViewHolder extends SongAdapter.ViewHolder {
public ViewHolder(@NonNull View itemView) {
super(itemView);
}
@Override
protected Song getSong() {
if (getItemViewType() == OFFSET_ITEM) return Song.EMPTY_SONG;
return dataSet.get(getAdapterPosition() - 1);
}
@Override
public void onClick(View v) {
if (isInQuickSelectMode() && getItemViewType() != OFFSET_ITEM) {
toggleChecked(getAdapterPosition());
} else {
MusicPlayerRemote.openQueue(dataSet, getAdapterPosition() - 1, true);
}
}
@Override
public boolean onLongClick(View view) {
if (getItemViewType() == OFFSET_ITEM) return false;
toggleChecked(getAdapterPosition());
return true;
}
}
}

View file

@ -1,57 +0,0 @@
package com.kabouzeid.gramophone.adapter.song;
import android.support.annotation.LayoutRes;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.util.Pair;
import android.support.v7.app.AppCompatActivity;
import android.view.MenuItem;
import android.view.View;
import com.kabouzeid.gramophone.R;
import com.kabouzeid.gramophone.interfaces.CabHolder;
import com.kabouzeid.gramophone.model.Song;
import com.kabouzeid.gramophone.util.NavigationUtil;
import java.util.ArrayList;
/**
* @author Karim Abou Zeid (kabouzeid)
*/
public class CustomPlaylistSongAdapter extends SongAdapter {
public static final String TAG = CustomPlaylistSongAdapter.class.getSimpleName();
public CustomPlaylistSongAdapter(AppCompatActivity activity, @NonNull ArrayList<Song> dataSet, @LayoutRes int itemLayoutRes, boolean usePalette, @Nullable CabHolder cabHolder) {
super(activity, dataSet, itemLayoutRes, usePalette, cabHolder, false);
overrideMultiSelectMenuRes(R.menu.menu_cannot_delete_single_songs_playlist_songs_selection);
}
@Override
protected SongAdapter.ViewHolder createViewHolder(View view) {
return new ViewHolder(view);
}
public class ViewHolder extends SongAdapter.ViewHolder {
public ViewHolder(@NonNull View itemView) {
super(itemView);
}
@Override
protected int getSongMenuRes() {
return R.menu.menu_item_cannot_delete_single_songs_playlist_song;
}
@Override
protected boolean onSongMenuItemClick(MenuItem item) {
if (item.getItemId() == R.id.action_go_to_album) {
Pair[] albumPairs = new Pair[]{
Pair.create(image, activity.getString(R.string.transition_album_art))
};
NavigationUtil.goToAlbum(activity, dataSet.get(getAdapterPosition()).albumId, albumPairs);
return true;
}
return super.onSongMenuItemClick(item);
}
}
}

View file

@ -0,0 +1,129 @@
package com.kabouzeid.gramophone.adapter.song;
import android.support.annotation.LayoutRes;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.view.MenuItem;
import android.view.View;
import com.h6ah4i.android.widget.advrecyclerview.draggable.DraggableItemAdapter;
import com.h6ah4i.android.widget.advrecyclerview.draggable.DraggableItemViewHolder;
import com.h6ah4i.android.widget.advrecyclerview.draggable.ItemDraggableRange;
import com.h6ah4i.android.widget.advrecyclerview.draggable.annotation.DraggableItemStateFlags;
import com.kabouzeid.gramophone.R;
import com.kabouzeid.gramophone.dialogs.RemoveFromPlaylistDialog;
import com.kabouzeid.gramophone.interfaces.CabHolder;
import com.kabouzeid.gramophone.model.PlaylistSong;
import com.kabouzeid.gramophone.model.Song;
import com.kabouzeid.gramophone.util.ViewUtil;
import java.util.ArrayList;
import java.util.List;
/**
* @author Karim Abou Zeid (kabouzeid)
*/
@SuppressWarnings("unchecked")
public class OrderablePlaylistSongAdapter extends PlaylistSongAdapter implements DraggableItemAdapter<OrderablePlaylistSongAdapter.ViewHolder> {
public static final String TAG = OrderablePlaylistSongAdapter.class.getSimpleName();
private OnMoveItemListener onMoveItemListener;
public OrderablePlaylistSongAdapter(@NonNull AppCompatActivity activity, @NonNull ArrayList<PlaylistSong> dataSet, @LayoutRes int itemLayoutRes, boolean usePalette, @Nullable CabHolder cabHolder, @Nullable OnMoveItemListener onMoveItemListener) {
super(activity, (ArrayList<Song>) (List) dataSet, itemLayoutRes, usePalette, cabHolder);
overrideMultiSelectMenuRes(R.menu.menu_playlists_songs_selection);
this.onMoveItemListener = onMoveItemListener;
}
@Override
protected SongAdapter.ViewHolder createViewHolder(View view) {
return new OrderablePlaylistSongAdapter.ViewHolder(view);
}
@Override
public long getItemId(int position) {
position--;
if (position < 0) return -2;
return ((ArrayList<PlaylistSong>) (List) dataSet).get(position).idInPlayList; // important!
}
@Override
protected void onMultipleItemAction(@NonNull MenuItem menuItem, @NonNull ArrayList<Song> selection) {
switch (menuItem.getItemId()) {
case R.id.action_remove_from_playlist:
RemoveFromPlaylistDialog.create((ArrayList<PlaylistSong>) (List) selection).show(activity.getSupportFragmentManager(), "ADD_PLAYLIST");
return;
}
super.onMultipleItemAction(menuItem, selection);
}
@Override
public boolean onCheckCanStartDrag(ViewHolder holder, int position, int x, int y) {
return onMoveItemListener != null && position > 0 && ViewUtil.hitTest(holder.dragView, x, y);
}
@Override
public ItemDraggableRange onGetItemDraggableRange(ViewHolder holder, int position) {
return new ItemDraggableRange(1, dataSet.size());
}
@Override
public void onMoveItem(int fromPosition, int toPosition) {
if (onMoveItemListener != null && fromPosition != toPosition) {
onMoveItemListener.onMoveItem(fromPosition - 1, toPosition - 1);
}
}
@Override
public boolean onCheckCanDrop(int draggingPosition, int dropPosition) {
return dropPosition > 0;
}
public interface OnMoveItemListener {
void onMoveItem(int fromPosition, int toPosition);
}
public class ViewHolder extends PlaylistSongAdapter.ViewHolder implements DraggableItemViewHolder {
@DraggableItemStateFlags
private int mDragStateFlags;
public ViewHolder(@NonNull View itemView) {
super(itemView);
if (dragView != null) {
if (onMoveItemListener != null) {
dragView.setVisibility(View.VISIBLE);
} else {
dragView.setVisibility(View.GONE);
}
}
}
@Override
protected int getSongMenuRes() {
return R.menu.menu_item_playlist_song;
}
@Override
protected boolean onSongMenuItemClick(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_remove_from_playlist:
RemoveFromPlaylistDialog.create((PlaylistSong) getSong()).show(activity.getSupportFragmentManager(), "REMOVE_FROM_PLAYLIST");
return true;
}
return super.onSongMenuItemClick(item);
}
@Override
public void setDragStateFlags(@DraggableItemStateFlags int flags) {
mDragStateFlags = flags;
}
@Override
@DraggableItemStateFlags
public int getDragStateFlags() {
return mDragStateFlags;
}
}
}

View file

@ -3,126 +3,84 @@ package com.kabouzeid.gramophone.adapter.song;
import android.support.annotation.LayoutRes;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.util.Pair;
import android.support.v7.app.AppCompatActivity;
import android.view.MenuItem;
import android.view.View;
import com.h6ah4i.android.widget.advrecyclerview.draggable.DraggableItemAdapter;
import com.h6ah4i.android.widget.advrecyclerview.draggable.DraggableItemViewHolder;
import com.h6ah4i.android.widget.advrecyclerview.draggable.ItemDraggableRange;
import com.h6ah4i.android.widget.advrecyclerview.draggable.annotation.DraggableItemStateFlags;
import com.kabouzeid.appthemehelper.ThemeStore;
import com.kabouzeid.gramophone.R;
import com.kabouzeid.gramophone.dialogs.RemoveFromPlaylistDialog;
import com.kabouzeid.gramophone.interfaces.CabHolder;
import com.kabouzeid.gramophone.model.PlaylistSong;
import com.kabouzeid.gramophone.model.Song;
import com.kabouzeid.gramophone.util.ViewUtil;
import com.kabouzeid.gramophone.util.MusicUtil;
import com.kabouzeid.gramophone.util.NavigationUtil;
import java.util.ArrayList;
import java.util.List;
/**
* @author Karim Abou Zeid (kabouzeid)
*/
@SuppressWarnings("unchecked")
public class PlaylistSongAdapter extends SongAdapter implements DraggableItemAdapter<PlaylistSongAdapter.ViewHolder> {
public class PlaylistSongAdapter extends AbsOffsetSongAdapter {
public static final String TAG = PlaylistSongAdapter.class.getSimpleName();
private OnMoveItemListener onMoveItemListener;
public PlaylistSongAdapter(@NonNull AppCompatActivity activity, @NonNull ArrayList<PlaylistSong> dataSet, @LayoutRes int itemLayoutRes, boolean usePalette, @Nullable CabHolder cabHolder, @Nullable OnMoveItemListener onMoveItemListener) {
super(activity, (ArrayList<Song>) (List) dataSet, itemLayoutRes, usePalette, cabHolder);
overrideMultiSelectMenuRes(R.menu.menu_playlists_songs_selection);
this.onMoveItemListener = onMoveItemListener;
}
@Override
public long getItemId(int position) {
return ((ArrayList<PlaylistSong>) (List) dataSet).get(position).idInPlayList; // important!
public PlaylistSongAdapter(AppCompatActivity activity, @NonNull ArrayList<Song> dataSet, @LayoutRes int itemLayoutRes, boolean usePalette, @Nullable CabHolder cabHolder) {
super(activity, dataSet, itemLayoutRes, usePalette, cabHolder, false);
overrideMultiSelectMenuRes(R.menu.menu_cannot_delete_single_songs_playlist_songs_selection);
}
@Override
protected SongAdapter.ViewHolder createViewHolder(View view) {
return new ViewHolder(view);
return new PlaylistSongAdapter.ViewHolder(view);
}
@Override
protected void onMultipleItemAction(@NonNull MenuItem menuItem, @NonNull ArrayList<Song> selection) {
switch (menuItem.getItemId()) {
case R.id.action_remove_from_playlist:
RemoveFromPlaylistDialog.create((ArrayList<PlaylistSong>) (List) selection).show(activity.getSupportFragmentManager(), "ADD_PLAYLIST");
return;
}
super.onMultipleItemAction(menuItem, selection);
}
@Override
public boolean onCheckCanStartDrag(ViewHolder holder, int position, int x, int y) {
return onMoveItemListener != null && ViewUtil.hitTest(holder.dragView, x, y);
}
@Override
public ItemDraggableRange onGetItemDraggableRange(ViewHolder holder, int position) {
return null;
}
@Override
public void onMoveItem(int fromPosition, int toPosition) {
if (onMoveItemListener != null && fromPosition != toPosition) {
onMoveItemListener.onMoveItem(fromPosition, toPosition);
public void onBindViewHolder(@NonNull final SongAdapter.ViewHolder holder, int position) {
if (holder.getItemViewType() == OFFSET_ITEM) {
if (holder.title != null) {
holder.title.setText(MusicUtil.getPlaylistInfoString(activity, dataSet));
holder.title.setTextColor(ThemeStore.textColorSecondary(activity));
}
if (holder.text != null) {
holder.text.setVisibility(View.GONE);
}
if (holder.menu != null) {
holder.menu.setVisibility(View.GONE);
}
if (holder.dragView != null) {
holder.dragView.setVisibility(View.GONE);
}
if (holder.separator != null) {
holder.separator.setVisibility(View.VISIBLE);
}
if (holder.shortSeparator != null) {
holder.shortSeparator.setVisibility(View.GONE);
}
} else {
super.onBindViewHolder(holder, position - 1);
}
}
@Override
public boolean onCheckCanDrop(int draggingPosition, int dropPosition) {
return true;
}
public interface OnMoveItemListener {
void onMoveItem(int fromPosition, int toPosition);
}
public class ViewHolder extends SongAdapter.ViewHolder implements DraggableItemViewHolder {
@DraggableItemStateFlags
private int mDragStateFlags;
public class ViewHolder extends AbsOffsetSongAdapter.ViewHolder {
public ViewHolder(@NonNull View itemView) {
super(itemView);
if (dragView != null) {
if (onMoveItemListener != null) {
dragView.setVisibility(View.VISIBLE);
} else {
dragView.setVisibility(View.GONE);
}
}
}
@Override
protected int getSongMenuRes() {
return R.menu.menu_item_playlist_song;
return R.menu.menu_item_cannot_delete_single_songs_playlist_song;
}
@Override
protected boolean onSongMenuItemClick(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_remove_from_playlist:
RemoveFromPlaylistDialog.create((PlaylistSong) getSong()).show(activity.getSupportFragmentManager(), "REMOVE_FROM_PLAYLIST");
return true;
if (item.getItemId() == R.id.action_go_to_album) {
Pair[] albumPairs = new Pair[]{
Pair.create(image, activity.getString(R.string.transition_album_art))
};
NavigationUtil.goToAlbum(activity, dataSet.get(getAdapterPosition() - 1).albumId, albumPairs);
return true;
}
return super.onSongMenuItemClick(item);
}
@Override
public void setDragStateFlags(@DraggableItemStateFlags int flags) {
mDragStateFlags = flags;
}
@Override
@DraggableItemStateFlags
public int getDragStateFlags() {
return mDragStateFlags;
}
}
}
}

View file

@ -5,9 +5,7 @@ import android.support.annotation.LayoutRes;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.kabouzeid.appthemehelper.ThemeStore;
import com.kabouzeid.gramophone.R;
@ -20,57 +18,20 @@ import java.util.ArrayList;
/**
* @author Karim Abou Zeid (kabouzeid)
*/
public class ShuffleButtonSongAdapter extends SongAdapter {
private static final int SHUFFLE_BUTTON = 0;
private static final int SONG = 1;
public class ShuffleButtonSongAdapter extends AbsOffsetSongAdapter {
public ShuffleButtonSongAdapter(AppCompatActivity activity, ArrayList<Song> dataSet, @LayoutRes int itemLayoutRes, boolean usePalette, @Nullable CabHolder cabHolder) {
super(activity, dataSet, itemLayoutRes, usePalette, cabHolder);
}
@NonNull
@Override
public SongAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (viewType == SHUFFLE_BUTTON) {
View view = LayoutInflater.from(activity).inflate(R.layout.item_list_single_row, parent, false);
return createViewHolder(view);
}
return super.onCreateViewHolder(parent, viewType);
}
@Override
protected SongAdapter.ViewHolder createViewHolder(View view) {
return new ViewHolder(view);
}
@Override
public long getItemId(int position) {
position--;
if (position < 0) return -2;
return super.getItemId(position);
}
@Override
protected Song getIdentifier(int position) {
position--;
if (position < 0) return Song.EMPTY_SONG;
return super.getIdentifier(position);
}
@Override
public int getItemCount() {
int superItemCount = super.getItemCount();
return superItemCount == 0 ? 0 : superItemCount + 1;
}
@Override
public int getItemViewType(int position) {
return position == 0 ? SHUFFLE_BUTTON : SONG;
return new ShuffleButtonSongAdapter.ViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull final SongAdapter.ViewHolder holder, int position) {
if (holder.getItemViewType() == SHUFFLE_BUTTON) {
if (holder.getItemViewType() == OFFSET_ITEM) {
int accentColor = ThemeStore.accentColor(activity);
if (holder.title != null) {
holder.title.setText(activity.getResources().getString(R.string.action_shuffle_all).toUpperCase());
@ -100,44 +61,19 @@ public class ShuffleButtonSongAdapter extends SongAdapter {
}
}
@NonNull
@Override
public String getSectionName(int position) {
position--;
if (position < 0) return "";
return super.getSectionName(position);
}
public class ViewHolder extends SongAdapter.ViewHolder {
public class ViewHolder extends AbsOffsetSongAdapter.ViewHolder {
public ViewHolder(@NonNull View itemView) {
super(itemView);
}
@Override
protected Song getSong() {
if (getItemViewType() == SHUFFLE_BUTTON) return Song.EMPTY_SONG;
return dataSet.get(getAdapterPosition() - 1);
}
@Override
public void onClick(View v) {
if (getItemViewType() == SHUFFLE_BUTTON) {
if (getItemViewType() == OFFSET_ITEM) {
MusicPlayerRemote.openAndShuffleQueue(dataSet, true);
return;
}
if (isInQuickSelectMode()) {
toggleChecked(getAdapterPosition());
} else {
MusicPlayerRemote.openQueue(dataSet, getAdapterPosition() - 1, true);
}
}
@Override
public boolean onLongClick(View view) {
if (getItemViewType() == SHUFFLE_BUTTON) return false;
toggleChecked(getAdapterPosition());
return true;
super.onClick(v);
}
}
}

View file

@ -20,8 +20,8 @@ import com.h6ah4i.android.widget.advrecyclerview.draggable.RecyclerViewDragDropM
import com.h6ah4i.android.widget.advrecyclerview.utils.WrapperAdapterUtils;
import com.kabouzeid.appthemehelper.ThemeStore;
import com.kabouzeid.gramophone.R;
import com.kabouzeid.gramophone.adapter.song.CustomPlaylistSongAdapter;
import com.kabouzeid.gramophone.adapter.song.PlaylistSongAdapter;
import com.kabouzeid.gramophone.adapter.song.OrderablePlaylistSongAdapter;
import com.kabouzeid.gramophone.adapter.song.SongAdapter;
import com.kabouzeid.gramophone.dialogs.SleepTimerDialog;
import com.kabouzeid.gramophone.helper.MusicPlayerRemote;
@ -98,12 +98,12 @@ public class PlaylistDetailActivity extends AbsSlidingMusicPanelActivity impleme
ViewUtil.setUpFastScrollRecyclerViewColor(this, ((FastScrollRecyclerView) recyclerView), ThemeStore.accentColor(this));
recyclerView.setLayoutManager(new LinearLayoutManager(this));
if (playlist instanceof AbsCustomPlaylist) {
adapter = new CustomPlaylistSongAdapter(this, new ArrayList<Song>(), R.layout.item_list, false, this);
adapter = new PlaylistSongAdapter(this, new ArrayList<Song>(), R.layout.item_list, false, this);
recyclerView.setAdapter(adapter);
} else {
recyclerViewDragDropManager = new RecyclerViewDragDropManager();
final GeneralItemAnimator animator = new RefactoredDefaultItemAnimator();
adapter = new PlaylistSongAdapter(this, new ArrayList<PlaylistSong>(), R.layout.item_list, false, this, new PlaylistSongAdapter.OnMoveItemListener() {
adapter = new OrderablePlaylistSongAdapter(this, new ArrayList<PlaylistSong>(), R.layout.item_list, false, this, new OrderablePlaylistSongAdapter.OnMoveItemListener() {
@Override
public void onMoveItem(int fromPosition, int toPosition) {
if (PlaylistsUtil.moveItem(PlaylistDetailActivity.this, playlist.id, fromPosition, toPosition)) {

View file

@ -23,6 +23,7 @@ import com.kabouzeid.gramophone.loader.PlaylistLoader;
import com.kabouzeid.gramophone.loader.SongLoader;
import com.kabouzeid.gramophone.model.Artist;
import com.kabouzeid.gramophone.model.Playlist;
import com.kabouzeid.gramophone.model.PlaylistSong;
import com.kabouzeid.gramophone.model.Song;
import com.kabouzeid.gramophone.model.lyrics.AbsSynchronizedLyrics;
@ -104,6 +105,19 @@ public class MusicUtil {
return albumCount + " " + albumString + "" + songCount + " " + songString;
}
@NonNull
public static String getPlaylistInfoString(@NonNull final Context context, @NonNull List<Song> songs) {
final int songCount = songs.size();
final String songString = songCount == 1 ? context.getResources().getString(R.string.song) : context.getResources().getString(R.string.songs);
long duration = 0;
for (int i = 0; i < songs.size(); i++) {
duration += songs.get(i).duration;
}
return songCount + " " + songString + "" + MusicUtil.getReadableDurationString(duration);
}
public static String getReadableDurationString(long songDurationMillis) {
long minutes = (songDurationMillis / 1000) / 60;
long seconds = (songDurationMillis / 1000) % 60;