change application id for release
This commit is contained in:
parent
0cd75de1ee
commit
9d08253655
159 changed files with 801 additions and 801 deletions
|
|
@ -0,0 +1,154 @@
|
|||
package com.dkanada.gramophone.adapter;
|
||||
|
||||
import android.os.Bundle;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.dkanada.gramophone.R;
|
||||
import com.dkanada.gramophone.glide.CustomGlideRequest;
|
||||
import com.dkanada.gramophone.glide.CustomPaletteTarget;
|
||||
import com.dkanada.gramophone.misc.CustomFragmentStatePagerAdapter;
|
||||
import com.dkanada.gramophone.model.Song;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import butterknife.Unbinder;
|
||||
|
||||
public class AlbumCoverPagerAdapter extends CustomFragmentStatePagerAdapter {
|
||||
|
||||
private List<Song> dataSet;
|
||||
|
||||
private AlbumCoverFragment.ColorReceiver currentColorReceiver;
|
||||
private int currentColorReceiverPosition = -1;
|
||||
|
||||
public AlbumCoverPagerAdapter(FragmentManager fm, List<Song> dataSet) {
|
||||
super(fm);
|
||||
this.dataSet = dataSet;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Fragment getItem(final int position) {
|
||||
return AlbumCoverFragment.newInstance(dataSet.get(position));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
return dataSet.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
@NonNull
|
||||
public Object instantiateItem(ViewGroup container, int position) {
|
||||
Object o = super.instantiateItem(container, position);
|
||||
if (currentColorReceiver != null && currentColorReceiverPosition == position) {
|
||||
receiveColor(currentColorReceiver, currentColorReceiverPosition);
|
||||
}
|
||||
|
||||
return o;
|
||||
}
|
||||
|
||||
// only the latest ColorReceiver is guaranteed a response
|
||||
public void receiveColor(AlbumCoverFragment.ColorReceiver colorReceiver, int position) {
|
||||
AlbumCoverFragment fragment = (AlbumCoverFragment) getFragment(position);
|
||||
if (fragment != null) {
|
||||
currentColorReceiver = null;
|
||||
currentColorReceiverPosition = -1;
|
||||
fragment.receiveColor(colorReceiver, position);
|
||||
} else {
|
||||
currentColorReceiver = colorReceiver;
|
||||
currentColorReceiverPosition = position;
|
||||
}
|
||||
}
|
||||
|
||||
public static class AlbumCoverFragment extends Fragment {
|
||||
private static final String SONG_ARG = "song";
|
||||
|
||||
private Unbinder unbinder;
|
||||
|
||||
@BindView(R.id.player_image)
|
||||
ImageView albumCover;
|
||||
|
||||
private boolean isColorReady;
|
||||
private int color;
|
||||
private Song song;
|
||||
private ColorReceiver colorReceiver;
|
||||
private int request;
|
||||
|
||||
public static AlbumCoverFragment newInstance(final Song song) {
|
||||
AlbumCoverFragment frag = new AlbumCoverFragment();
|
||||
final Bundle args = new Bundle();
|
||||
args.putParcelable(SONG_ARG, song);
|
||||
frag.setArguments(args);
|
||||
return frag;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(final Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
song = getArguments().getParcelable(SONG_ARG);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
View view = inflater.inflate(R.layout.fragment_album_cover, container, false);
|
||||
unbinder = ButterKnife.bind(this, view);
|
||||
return view;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
loadAlbumCover();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
super.onDestroyView();
|
||||
unbinder.unbind();
|
||||
colorReceiver = null;
|
||||
}
|
||||
|
||||
private void loadAlbumCover() {
|
||||
CustomGlideRequest.Builder
|
||||
.from(Glide.with(getContext()), song.primary)
|
||||
.generatePalette(getActivity()).build()
|
||||
.into(new CustomPaletteTarget(albumCover) {
|
||||
@Override
|
||||
public void onColorReady(int color) {
|
||||
setColor(color);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void setColor(int color) {
|
||||
this.color = color;
|
||||
isColorReady = true;
|
||||
if (colorReceiver != null) {
|
||||
colorReceiver.onColorReady(color, request);
|
||||
colorReceiver = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void receiveColor(ColorReceiver colorReceiver, int request) {
|
||||
if (isColorReady) {
|
||||
colorReceiver.onColorReady(color, request);
|
||||
} else {
|
||||
this.colorReceiver = colorReceiver;
|
||||
this.request = request;
|
||||
}
|
||||
}
|
||||
|
||||
public interface ColorReceiver {
|
||||
void onColorReady(int color, int request);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,112 @@
|
|||
package com.dkanada.gramophone.adapter;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import androidx.recyclerview.widget.ItemTouchHelper;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.CheckBox;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.dkanada.gramophone.R;
|
||||
import com.dkanada.gramophone.model.CategoryInfo;
|
||||
import com.dkanada.gramophone.helper.SwipeAndDragHelper;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class CategoryInfoAdapter extends RecyclerView.Adapter<CategoryInfoAdapter.ViewHolder> implements SwipeAndDragHelper.ActionCompletionContract {
|
||||
private List<CategoryInfo> categoryInfos;
|
||||
private ItemTouchHelper touchHelper;
|
||||
|
||||
public CategoryInfoAdapter(List<CategoryInfo> categoryInfos) {
|
||||
this.categoryInfos = categoryInfos;
|
||||
SwipeAndDragHelper swipeAndDragHelper = new SwipeAndDragHelper(this);
|
||||
touchHelper = new ItemTouchHelper(swipeAndDragHelper);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NonNull
|
||||
public CategoryInfoAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.preference_dialog_library_categories_listitem, parent, false);
|
||||
return new ViewHolder(view);
|
||||
}
|
||||
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull CategoryInfoAdapter.ViewHolder holder, int position) {
|
||||
CategoryInfo categoryInfo = categoryInfos.get(position);
|
||||
|
||||
holder.checkBox.setChecked(categoryInfo.visible);
|
||||
holder.title.setText(holder.title.getResources().getString(categoryInfo.category.stringRes));
|
||||
|
||||
holder.itemView.setOnClickListener(v -> {
|
||||
if (!(categoryInfo.visible && isLastCheckedCategory(categoryInfo))) {
|
||||
categoryInfo.visible = !categoryInfo.visible;
|
||||
holder.checkBox.setChecked(categoryInfo.visible);
|
||||
} else {
|
||||
Toast.makeText(holder.itemView.getContext(), R.string.you_have_to_select_at_least_one_category, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
});
|
||||
|
||||
holder.dragView.setOnTouchListener((view, event) -> {
|
||||
if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
|
||||
touchHelper.startDrag(holder);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return categoryInfos.size();
|
||||
}
|
||||
|
||||
public void setCategoryInfos(List<CategoryInfo> categoryInfos) {
|
||||
this.categoryInfos = categoryInfos;
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewMoved(int oldPosition, int newPosition) {
|
||||
CategoryInfo categoryInfo = categoryInfos.get(oldPosition);
|
||||
categoryInfos.remove(oldPosition);
|
||||
categoryInfos.add(newPosition, categoryInfo);
|
||||
notifyItemMoved(oldPosition, newPosition);
|
||||
}
|
||||
|
||||
public void attachToRecyclerView(RecyclerView recyclerView) {
|
||||
touchHelper.attachToRecyclerView(recyclerView);
|
||||
}
|
||||
|
||||
public List<CategoryInfo> getCategoryInfos() {
|
||||
return categoryInfos;
|
||||
}
|
||||
|
||||
private boolean isLastCheckedCategory(CategoryInfo categoryInfo) {
|
||||
if (categoryInfo.visible) {
|
||||
for (CategoryInfo c : categoryInfos) {
|
||||
if (c != categoryInfo && c.visible) return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static class ViewHolder extends RecyclerView.ViewHolder {
|
||||
public CheckBox checkBox;
|
||||
public TextView title;
|
||||
public View dragView;
|
||||
|
||||
public ViewHolder(View view) {
|
||||
super(view);
|
||||
checkBox = view.findViewById(R.id.checkbox);
|
||||
title = view.findViewById(R.id.title);
|
||||
dragView = view.findViewById(R.id.drag_view);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,123 @@
|
|||
package com.dkanada.gramophone.adapter;
|
||||
|
||||
import androidx.annotation.LayoutRes;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.dkanada.gramophone.adapter.base.MediaEntryViewHolder;
|
||||
import com.dkanada.gramophone.glide.CustomGlideRequest;
|
||||
import com.dkanada.gramophone.glide.CustomPaletteTarget;
|
||||
import com.dkanada.gramophone.model.Genre;
|
||||
import com.dkanada.gramophone.util.MusicUtil;
|
||||
import com.dkanada.gramophone.util.NavigationUtil;
|
||||
import com.simplecityapps.recyclerview_fastscroll.views.FastScrollRecyclerView;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class GenreAdapter extends RecyclerView.Adapter<GenreAdapter.ViewHolder> implements FastScrollRecyclerView.SectionedAdapter {
|
||||
private final AppCompatActivity activity;
|
||||
private List<Genre> dataSet;
|
||||
|
||||
private int itemLayoutRes;
|
||||
|
||||
public GenreAdapter(@NonNull AppCompatActivity activity, List<Genre> dataSet, @LayoutRes int itemLayoutRes) {
|
||||
this.activity = activity;
|
||||
this.dataSet = dataSet;
|
||||
this.itemLayoutRes = itemLayoutRes;
|
||||
}
|
||||
|
||||
public List<Genre> getDataSet() {
|
||||
return dataSet;
|
||||
}
|
||||
|
||||
public void swapDataSet(List<Genre> dataSet) {
|
||||
this.dataSet = dataSet;
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getItemId(int position) {
|
||||
return dataSet.get(position).hashCode();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
View view = LayoutInflater.from(activity).inflate(itemLayoutRes, parent, false);
|
||||
return new ViewHolder(view);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
|
||||
final Genre genre = dataSet.get(position);
|
||||
|
||||
if (holder.getAdapterPosition() == getItemCount() - 1) {
|
||||
if (holder.shortSeparator != null) {
|
||||
holder.shortSeparator.setVisibility(View.GONE);
|
||||
}
|
||||
} else {
|
||||
if (holder.shortSeparator != null) {
|
||||
holder.shortSeparator.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
if (holder.menu != null) {
|
||||
holder.menu.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
if (holder.title != null) {
|
||||
holder.title.setText(genre.name);
|
||||
}
|
||||
|
||||
loadImage(genre, holder);
|
||||
}
|
||||
|
||||
protected void loadImage(Genre genre, final GenreAdapter.ViewHolder holder) {
|
||||
if (holder.image == null) return;
|
||||
|
||||
CustomGlideRequest.Builder
|
||||
.from(Glide.with(activity), genre.id)
|
||||
.generatePalette(activity).build()
|
||||
.into(new CustomPaletteTarget(holder.image) {
|
||||
@Override
|
||||
public void onLoadCleared(Drawable placeholder) {
|
||||
super.onLoadCleared(placeholder);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onColorReady(int color) {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return dataSet.size();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String getSectionName(int position) {
|
||||
final Genre genre = dataSet.get(position);
|
||||
return genre.id.hashCode() == -1 ? "" : MusicUtil.getSectionName(dataSet.get(position).name);
|
||||
}
|
||||
|
||||
public class ViewHolder extends MediaEntryViewHolder {
|
||||
public ViewHolder(@NonNull View itemView) {
|
||||
super(itemView);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
Genre genre = dataSet.get(getAdapterPosition());
|
||||
NavigationUtil.goToGenre(activity, genre);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,189 @@
|
|||
package com.dkanada.gramophone.adapter;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
import androidx.fragment.app.FragmentPagerAdapter;
|
||||
import android.util.SparseArray;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.dkanada.gramophone.model.CategoryInfo;
|
||||
import com.dkanada.gramophone.ui.fragments.mainactivity.library.pager.AlbumsFragment;
|
||||
import com.dkanada.gramophone.ui.fragments.mainactivity.library.pager.ArtistsFragment;
|
||||
import com.dkanada.gramophone.ui.fragments.mainactivity.library.pager.GenresFragment;
|
||||
import com.dkanada.gramophone.ui.fragments.mainactivity.library.pager.PlaylistsFragment;
|
||||
import com.dkanada.gramophone.ui.fragments.mainactivity.library.pager.SongsFragment;
|
||||
import com.dkanada.gramophone.util.PreferenceUtil;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
public class MusicLibraryPagerAdapter extends FragmentPagerAdapter {
|
||||
|
||||
private final SparseArray<WeakReference<Fragment>> mFragmentArray = new SparseArray<>();
|
||||
|
||||
private final List<Holder> mHolderList = new ArrayList<>();
|
||||
|
||||
@NonNull
|
||||
private final Context mContext;
|
||||
|
||||
public MusicLibraryPagerAdapter(@NonNull final Context context, final FragmentManager fragmentManager) {
|
||||
super(fragmentManager);
|
||||
mContext = context;
|
||||
setCategoryInfos(PreferenceUtil.getInstance(context).getLibraryCategories());
|
||||
}
|
||||
|
||||
public void setCategoryInfos(@NonNull List<CategoryInfo> categoryInfos) {
|
||||
mHolderList.clear();
|
||||
|
||||
for (CategoryInfo categoryInfo : categoryInfos) {
|
||||
if (categoryInfo.visible) {
|
||||
MusicFragments fragment = MusicFragments.valueOf(categoryInfo.category.toString());
|
||||
Holder holder = new Holder();
|
||||
holder.mClassName = fragment.getFragmentClass().getName();
|
||||
holder.title = mContext.getResources()
|
||||
.getString(categoryInfo.category.stringRes)
|
||||
.toUpperCase(Locale.getDefault());
|
||||
mHolderList.add(holder);
|
||||
}
|
||||
}
|
||||
|
||||
alignCache();
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
public Fragment getFragment(final int position) {
|
||||
final WeakReference<Fragment> mWeakFragment = mFragmentArray.get(position);
|
||||
if (mWeakFragment != null && mWeakFragment.get() != null) {
|
||||
return mWeakFragment.get();
|
||||
}
|
||||
|
||||
return getItem(position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemPosition(@NonNull Object fragment) {
|
||||
for (int i = 0, size = mHolderList.size(); i < size; i++) {
|
||||
Holder holder = mHolderList.get(i);
|
||||
if (holder.mClassName.equals(fragment.getClass().getName())) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return POSITION_NONE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getItemId(int position) {
|
||||
// as fragment position is not fixed, we can't use position as id
|
||||
return MusicFragments.of(getFragment(position).getClass()).ordinal();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Object instantiateItem(@NonNull final ViewGroup container, final int position) {
|
||||
final Fragment mFragment = (Fragment) super.instantiateItem(container, position);
|
||||
final WeakReference<Fragment> mWeakFragment = mFragmentArray.get(position);
|
||||
if (mWeakFragment != null) {
|
||||
mWeakFragment.clear();
|
||||
}
|
||||
|
||||
mFragmentArray.put(position, new WeakReference<>(mFragment));
|
||||
return mFragment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Fragment getItem(final int position) {
|
||||
final Holder mCurrentHolder = mHolderList.get(position);
|
||||
return Fragment.instantiate(mContext, mCurrentHolder.mClassName, mCurrentHolder.mParams);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroyItem(final ViewGroup container, final int position, final Object object) {
|
||||
super.destroyItem(container, position, object);
|
||||
final WeakReference<Fragment> mWeakFragment = mFragmentArray.get(position);
|
||||
if (mWeakFragment != null) {
|
||||
mWeakFragment.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
return mHolderList.size();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public CharSequence getPageTitle(final int position) {
|
||||
return mHolderList.get(position).title;
|
||||
}
|
||||
|
||||
/**
|
||||
* Aligns the fragment cache with the current category layout.
|
||||
*/
|
||||
private void alignCache() {
|
||||
if (mFragmentArray.size() == 0) return;
|
||||
|
||||
HashMap<String, WeakReference<Fragment>> mappings = new HashMap<>(mFragmentArray.size());
|
||||
for (int i = 0, size = mFragmentArray.size(); i < size; i++) {
|
||||
WeakReference<Fragment> ref = mFragmentArray.valueAt(i);
|
||||
Fragment fragment = ref.get();
|
||||
if (fragment != null) {
|
||||
mappings.put(fragment.getClass().getName(), ref);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0, size = mHolderList.size(); i < size; i++) {
|
||||
WeakReference<Fragment> ref = mappings.get(mHolderList.get(i).mClassName);
|
||||
if (ref != null) {
|
||||
mFragmentArray.put(i, ref);
|
||||
} else {
|
||||
mFragmentArray.remove(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public enum MusicFragments {
|
||||
SONGS(SongsFragment.class),
|
||||
ALBUMS(AlbumsFragment.class),
|
||||
ARTISTS(ArtistsFragment.class),
|
||||
GENRES(GenresFragment.class),
|
||||
PLAYLISTS(PlaylistsFragment.class);
|
||||
|
||||
private final Class<? extends Fragment> mFragmentClass;
|
||||
|
||||
MusicFragments(final Class<? extends Fragment> fragmentClass) {
|
||||
mFragmentClass = fragmentClass;
|
||||
}
|
||||
|
||||
public Class<? extends Fragment> getFragmentClass() {
|
||||
return mFragmentClass;
|
||||
}
|
||||
|
||||
public static MusicFragments of(Class<?> cl) {
|
||||
MusicFragments[] fragments = All.FRAGMENTS;
|
||||
for (MusicFragments fragment : fragments) {
|
||||
if (cl.equals(fragment.mFragmentClass)) {
|
||||
return fragment;
|
||||
}
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("Unknown music fragment " + cl);
|
||||
}
|
||||
|
||||
private static class All {
|
||||
public static final MusicFragments[] FRAGMENTS = values();
|
||||
}
|
||||
}
|
||||
|
||||
private final static class Holder {
|
||||
String mClassName;
|
||||
Bundle mParams;
|
||||
String title;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,175 @@
|
|||
package com.dkanada.gramophone.adapter;
|
||||
|
||||
import android.graphics.drawable.Drawable;
|
||||
import androidx.annotation.LayoutRes;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.PopupMenu;
|
||||
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.dkanada.gramophone.R;
|
||||
import com.dkanada.gramophone.adapter.base.AbsMultiSelectAdapter;
|
||||
import com.dkanada.gramophone.adapter.base.MediaEntryViewHolder;
|
||||
import com.dkanada.gramophone.dialogs.DeletePlaylistDialog;
|
||||
import com.dkanada.gramophone.glide.CustomGlideRequest;
|
||||
import com.dkanada.gramophone.glide.CustomPaletteTarget;
|
||||
import com.dkanada.gramophone.helper.menu.PlaylistMenuHelper;
|
||||
import com.dkanada.gramophone.helper.menu.SongsMenuHelper;
|
||||
import com.dkanada.gramophone.interfaces.CabHolder;
|
||||
import com.dkanada.gramophone.model.Playlist;
|
||||
import com.dkanada.gramophone.model.Song;
|
||||
import com.dkanada.gramophone.util.NavigationUtil;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class PlaylistAdapter extends AbsMultiSelectAdapter<PlaylistAdapter.ViewHolder, Playlist> {
|
||||
protected final AppCompatActivity activity;
|
||||
protected List<Playlist> dataSet;
|
||||
protected int itemLayoutRes;
|
||||
|
||||
public PlaylistAdapter(AppCompatActivity activity, List<Playlist> dataSet, @LayoutRes int itemLayoutRes, @Nullable CabHolder cabHolder) {
|
||||
super(activity, cabHolder, R.menu.menu_playlists_selection);
|
||||
this.activity = activity;
|
||||
this.dataSet = dataSet;
|
||||
this.itemLayoutRes = itemLayoutRes;
|
||||
setHasStableIds(true);
|
||||
}
|
||||
|
||||
public List<Playlist> getDataSet() {
|
||||
return dataSet;
|
||||
}
|
||||
|
||||
public void swapDataSet(List<Playlist> dataSet) {
|
||||
this.dataSet = dataSet;
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getItemId(int position) {
|
||||
return dataSet.get(position).hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
@NonNull
|
||||
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
View view = LayoutInflater.from(activity).inflate(itemLayoutRes, parent, false);
|
||||
return createViewHolder(view, viewType);
|
||||
}
|
||||
|
||||
protected ViewHolder createViewHolder(View view, int viewType) {
|
||||
return new ViewHolder(view, viewType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
|
||||
final Playlist playlist = dataSet.get(position);
|
||||
|
||||
holder.itemView.setActivated(isChecked(playlist));
|
||||
|
||||
if (holder.title != null) {
|
||||
holder.title.setText(playlist.name);
|
||||
}
|
||||
|
||||
if (holder.getAdapterPosition() == getItemCount() - 1) {
|
||||
if (holder.shortSeparator != null) {
|
||||
holder.shortSeparator.setVisibility(View.GONE);
|
||||
}
|
||||
} else {
|
||||
if (holder.shortSeparator != null) {
|
||||
holder.shortSeparator.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
loadImage(playlist, holder);
|
||||
}
|
||||
|
||||
protected void loadImage(Playlist playlist, final PlaylistAdapter.ViewHolder holder) {
|
||||
if (holder.image == null) return;
|
||||
|
||||
CustomGlideRequest.Builder
|
||||
.from(Glide.with(activity), playlist.id)
|
||||
.generatePalette(activity).build()
|
||||
.into(new CustomPaletteTarget(holder.image) {
|
||||
@Override
|
||||
public void onLoadCleared(Drawable placeholder) {
|
||||
super.onLoadCleared(placeholder);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onColorReady(int color) {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return dataSet.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Playlist getIdentifier(int position) {
|
||||
return dataSet.get(position);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getName(Playlist playlist) {
|
||||
return playlist.name;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMultipleItemAction(@NonNull MenuItem menuItem, @NonNull List<Playlist> selection) {
|
||||
switch (menuItem.getItemId()) {
|
||||
case R.id.action_delete_playlist:
|
||||
DeletePlaylistDialog.create(selection).show(activity.getSupportFragmentManager(), "DELETE_PLAYLIST");
|
||||
break;
|
||||
default:
|
||||
SongsMenuHelper.handleMenuClick(activity, getSongList(selection), menuItem.getItemId());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private List<Song> getSongList(@NonNull List<Playlist> playlists) {
|
||||
final List<Song> songs = new ArrayList<>();
|
||||
return songs;
|
||||
}
|
||||
|
||||
public class ViewHolder extends MediaEntryViewHolder {
|
||||
public ViewHolder(@NonNull View itemView, int itemViewType) {
|
||||
super(itemView);
|
||||
|
||||
if (menu != null) {
|
||||
menu.setOnClickListener(view -> {
|
||||
final PopupMenu popupMenu = new PopupMenu(activity, view);
|
||||
|
||||
popupMenu.inflate(R.menu.menu_item_playlist);
|
||||
popupMenu.setOnMenuItemClickListener(item -> PlaylistMenuHelper.handleMenuClick(activity, dataSet.get(getAdapterPosition()), item));
|
||||
|
||||
popupMenu.show();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
if (isInQuickSelectMode()) {
|
||||
toggleChecked(getAdapterPosition());
|
||||
} else {
|
||||
Playlist playlist = dataSet.get(getAdapterPosition());
|
||||
NavigationUtil.goToPlaylist(activity, playlist);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onLongClick(View view) {
|
||||
toggleChecked(getAdapterPosition());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,167 @@
|
|||
package com.dkanada.gramophone.adapter;
|
||||
|
||||
import android.os.Build;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.core.util.Pair;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.kabouzeid.appthemehelper.util.ATHUtil;
|
||||
import com.dkanada.gramophone.R;
|
||||
import com.dkanada.gramophone.adapter.base.MediaEntryViewHolder;
|
||||
import com.dkanada.gramophone.glide.CustomGlideRequest;
|
||||
import com.dkanada.gramophone.helper.MusicPlayerRemote;
|
||||
import com.dkanada.gramophone.helper.menu.SongMenuHelper;
|
||||
import com.dkanada.gramophone.model.Album;
|
||||
import com.dkanada.gramophone.model.Artist;
|
||||
import com.dkanada.gramophone.model.Song;
|
||||
import com.dkanada.gramophone.util.MusicUtil;
|
||||
import com.dkanada.gramophone.util.NavigationUtil;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class SearchAdapter extends RecyclerView.Adapter<SearchAdapter.ViewHolder> {
|
||||
|
||||
private static final int HEADER = 0;
|
||||
private static final int ALBUM = 1;
|
||||
private static final int ARTIST = 2;
|
||||
private static final int SONG = 3;
|
||||
|
||||
private final AppCompatActivity activity;
|
||||
private List<Object> dataSet;
|
||||
|
||||
public SearchAdapter(@NonNull AppCompatActivity activity, @NonNull List<Object> dataSet) {
|
||||
this.activity = activity;
|
||||
this.dataSet = dataSet;
|
||||
}
|
||||
|
||||
public void swapDataSet(@NonNull List<Object> dataSet) {
|
||||
this.dataSet = dataSet;
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemViewType(int position) {
|
||||
if (dataSet.get(position) instanceof Album) return ALBUM;
|
||||
if (dataSet.get(position) instanceof Artist) return ARTIST;
|
||||
if (dataSet.get(position) instanceof Song) return SONG;
|
||||
return HEADER;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NonNull
|
||||
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
if (viewType == HEADER)
|
||||
return new ViewHolder(LayoutInflater.from(activity).inflate(R.layout.sub_header, parent, false), viewType);
|
||||
return new ViewHolder(LayoutInflater.from(activity).inflate(R.layout.item_list, parent, false), viewType);
|
||||
}
|
||||
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull final ViewHolder holder, int position) {
|
||||
switch (getItemViewType(position)) {
|
||||
case ALBUM:
|
||||
final Album album = (Album) dataSet.get(position);
|
||||
holder.title.setText(album.getTitle());
|
||||
holder.text.setText(MusicUtil.getAlbumInfoString(activity, album));
|
||||
CustomGlideRequest.Builder
|
||||
.from(Glide.with(activity), album.primary)
|
||||
.build().into(holder.image);
|
||||
break;
|
||||
case ARTIST:
|
||||
final Artist artist = (Artist) dataSet.get(position);
|
||||
holder.title.setText(artist.getName());
|
||||
holder.text.setText(MusicUtil.getArtistInfoString(activity, artist));
|
||||
CustomGlideRequest.Builder
|
||||
.from(Glide.with(activity), artist.primary)
|
||||
.build().into(holder.image);
|
||||
break;
|
||||
case SONG:
|
||||
final Song song = (Song) dataSet.get(position);
|
||||
holder.title.setText(song.title);
|
||||
holder.text.setText(MusicUtil.getSongInfoString(song));
|
||||
break;
|
||||
default:
|
||||
holder.title.setText(dataSet.get(position).toString());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return dataSet.size();
|
||||
}
|
||||
|
||||
public class ViewHolder extends MediaEntryViewHolder {
|
||||
public ViewHolder(@NonNull View itemView, int itemViewType) {
|
||||
super(itemView);
|
||||
itemView.setOnLongClickListener(null);
|
||||
|
||||
if (itemViewType != HEADER) {
|
||||
itemView.setBackgroundColor(ATHUtil.resolveColor(activity, R.attr.cardBackgroundColor));
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
itemView.setElevation(activity.getResources().getDimensionPixelSize(R.dimen.card_elevation));
|
||||
}
|
||||
if (shortSeparator != null) {
|
||||
shortSeparator.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
if (menu != null) {
|
||||
if (itemViewType == SONG) {
|
||||
menu.setVisibility(View.VISIBLE);
|
||||
menu.setOnClickListener(new SongMenuHelper.OnClickSongMenu(activity) {
|
||||
@Override
|
||||
public Song getSong() {
|
||||
return (Song) dataSet.get(getAdapterPosition());
|
||||
}
|
||||
});
|
||||
} else {
|
||||
menu.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
switch (itemViewType) {
|
||||
case ALBUM:
|
||||
setImageTransitionName(activity.getString(R.string.transition_album_art));
|
||||
break;
|
||||
case ARTIST:
|
||||
setImageTransitionName(activity.getString(R.string.transition_artist_image));
|
||||
break;
|
||||
default:
|
||||
View container = itemView.findViewById(R.id.image_container);
|
||||
if (container != null) {
|
||||
container.setVisibility(View.GONE);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
Object item = dataSet.get(getAdapterPosition());
|
||||
switch (getItemViewType()) {
|
||||
case ALBUM:
|
||||
NavigationUtil.goToAlbum(activity,
|
||||
(Album) item,
|
||||
Pair.create(image, activity.getResources().getString(R.string.transition_album_art)));
|
||||
break;
|
||||
case ARTIST:
|
||||
NavigationUtil.goToArtist(activity,
|
||||
(Artist) item,
|
||||
Pair.create(image, activity.getResources().getString(R.string.transition_artist_image)));
|
||||
break;
|
||||
case SONG:
|
||||
List<Song> playList = new ArrayList<>();
|
||||
playList.add((Song) item);
|
||||
MusicPlayerRemote.openQueue(playList, 0, true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,232 @@
|
|||
package com.dkanada.gramophone.adapter.album;
|
||||
|
||||
import android.graphics.drawable.Drawable;
|
||||
import androidx.annotation.LayoutRes;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.util.Pair;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.kabouzeid.appthemehelper.util.ColorUtil;
|
||||
import com.kabouzeid.appthemehelper.util.MaterialValueHelper;
|
||||
import com.dkanada.gramophone.R;
|
||||
import com.dkanada.gramophone.adapter.base.AbsMultiSelectAdapter;
|
||||
import com.dkanada.gramophone.adapter.base.MediaEntryViewHolder;
|
||||
import com.dkanada.gramophone.glide.CustomGlideRequest;
|
||||
import com.dkanada.gramophone.glide.CustomPaletteTarget;
|
||||
import com.dkanada.gramophone.helper.menu.SongsMenuHelper;
|
||||
import com.dkanada.gramophone.helper.sort.SortMethod;
|
||||
import com.dkanada.gramophone.interfaces.CabHolder;
|
||||
import com.dkanada.gramophone.model.Album;
|
||||
import com.dkanada.gramophone.model.Song;
|
||||
import com.dkanada.gramophone.util.MusicUtil;
|
||||
import com.dkanada.gramophone.util.NavigationUtil;
|
||||
import com.dkanada.gramophone.util.PreferenceUtil;
|
||||
|
||||
import com.simplecityapps.recyclerview_fastscroll.views.FastScrollRecyclerView;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class AlbumAdapter extends AbsMultiSelectAdapter<AlbumAdapter.ViewHolder, Album> implements FastScrollRecyclerView.SectionedAdapter {
|
||||
protected final AppCompatActivity activity;
|
||||
protected List<Album> dataSet;
|
||||
|
||||
protected int itemLayoutRes;
|
||||
|
||||
protected boolean usePalette;
|
||||
|
||||
public AlbumAdapter(@NonNull AppCompatActivity activity, List<Album> dataSet, @LayoutRes int itemLayoutRes, boolean usePalette, @Nullable CabHolder cabHolder) {
|
||||
super(activity, cabHolder, R.menu.menu_media_selection);
|
||||
this.activity = activity;
|
||||
this.dataSet = dataSet;
|
||||
this.itemLayoutRes = itemLayoutRes;
|
||||
this.usePalette = usePalette;
|
||||
|
||||
setHasStableIds(true);
|
||||
}
|
||||
|
||||
public void usePalette(boolean usePalette) {
|
||||
this.usePalette = usePalette;
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
public void swapDataSet(List<Album> dataSet) {
|
||||
this.dataSet = dataSet;
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
public List<Album> getDataSet() {
|
||||
return dataSet;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NonNull
|
||||
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
View view = LayoutInflater.from(activity).inflate(itemLayoutRes, parent, false);
|
||||
return createViewHolder(view, viewType);
|
||||
}
|
||||
|
||||
protected ViewHolder createViewHolder(View view, int viewType) {
|
||||
return new ViewHolder(view);
|
||||
}
|
||||
|
||||
protected String getAlbumTitle(Album album) {
|
||||
return album.getTitle();
|
||||
}
|
||||
|
||||
protected String getAlbumText(Album album) {
|
||||
return MusicUtil.getAlbumInfoString(activity, album);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull final ViewHolder holder, int position) {
|
||||
final Album album = dataSet.get(position);
|
||||
|
||||
final boolean isChecked = isChecked(album);
|
||||
holder.itemView.setActivated(isChecked);
|
||||
|
||||
if (holder.getAdapterPosition() == getItemCount() - 1) {
|
||||
if (holder.shortSeparator != null) {
|
||||
holder.shortSeparator.setVisibility(View.GONE);
|
||||
}
|
||||
} else {
|
||||
if (holder.shortSeparator != null) {
|
||||
holder.shortSeparator.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
if (holder.title != null) {
|
||||
holder.title.setText(getAlbumTitle(album));
|
||||
}
|
||||
|
||||
if (holder.text != null) {
|
||||
holder.text.setText(getAlbumText(album));
|
||||
}
|
||||
|
||||
loadAlbumCover(album, holder);
|
||||
}
|
||||
|
||||
protected void setColors(int color, ViewHolder holder) {
|
||||
if (holder.paletteColorContainer != null) {
|
||||
holder.paletteColorContainer.setBackgroundColor(color);
|
||||
if (holder.title != null) {
|
||||
holder.title.setTextColor(MaterialValueHelper.getPrimaryTextColor(activity, ColorUtil.isColorLight(color)));
|
||||
}
|
||||
|
||||
if (holder.text != null) {
|
||||
holder.text.setTextColor(MaterialValueHelper.getSecondaryTextColor(activity, ColorUtil.isColorLight(color)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void loadAlbumCover(Album album, final ViewHolder holder) {
|
||||
if (holder.image == null) return;
|
||||
|
||||
CustomGlideRequest.Builder
|
||||
.from(Glide.with(activity), album.primary)
|
||||
.generatePalette(activity).build()
|
||||
.into(new CustomPaletteTarget(holder.image) {
|
||||
@Override
|
||||
public void onLoadCleared(Drawable placeholder) {
|
||||
super.onLoadCleared(placeholder);
|
||||
setColors(getDefaultFooterColor(), holder);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onColorReady(int color) {
|
||||
if (usePalette) {
|
||||
setColors(color, holder);
|
||||
} else {
|
||||
setColors(getDefaultFooterColor(), holder);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return dataSet.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getItemId(int position) {
|
||||
return dataSet.get(position).hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Album getIdentifier(int position) {
|
||||
return dataSet.get(position);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getName(Album album) {
|
||||
return album.getTitle();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMultipleItemAction(@NonNull MenuItem menuItem, @NonNull List<Album> selection) {
|
||||
SongsMenuHelper.handleMenuClick(activity, getSongList(selection), menuItem.getItemId());
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private List<Song> getSongList(@NonNull List<Album> albums) {
|
||||
final List<Song> songs = new ArrayList<>();
|
||||
for (Album album : albums) {
|
||||
songs.addAll(album.songs);
|
||||
}
|
||||
|
||||
return songs;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String getSectionName(int position) {
|
||||
@Nullable String sectionName = null;
|
||||
switch (PreferenceUtil.getInstance(activity).getAlbumSortMethod()) {
|
||||
case SortMethod.NAME:
|
||||
sectionName = dataSet.get(position).getTitle();
|
||||
break;
|
||||
case SortMethod.ARTIST:
|
||||
sectionName = dataSet.get(position).getArtistName();
|
||||
break;
|
||||
case SortMethod.YEAR:
|
||||
return MusicUtil.getYearString(dataSet.get(position).getYear());
|
||||
case SortMethod.RANDOM:
|
||||
return activity.getResources().getString(R.string.random);
|
||||
}
|
||||
|
||||
return MusicUtil.getSectionName(sectionName);
|
||||
}
|
||||
|
||||
public class ViewHolder extends MediaEntryViewHolder {
|
||||
public ViewHolder(@NonNull final View itemView) {
|
||||
super(itemView);
|
||||
setImageTransitionName(activity.getString(R.string.transition_album_art));
|
||||
if (menu != null) {
|
||||
menu.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (isInQuickSelectMode()) {
|
||||
toggleChecked(getAdapterPosition());
|
||||
} else {
|
||||
Pair[] albumPairs = new Pair[]{Pair.create(image, activity.getResources().getString(R.string.transition_album_art))};
|
||||
NavigationUtil.goToAlbum(activity, dataSet.get(getAdapterPosition()), albumPairs);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onLongClick(View view) {
|
||||
toggleChecked(getAdapterPosition());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,84 @@
|
|||
package com.dkanada.gramophone.adapter.album;
|
||||
|
||||
import android.graphics.drawable.Drawable;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.cardview.widget.CardView;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.kabouzeid.appthemehelper.util.ColorUtil;
|
||||
import com.kabouzeid.appthemehelper.util.MaterialValueHelper;
|
||||
import com.dkanada.gramophone.glide.CustomGlideRequest;
|
||||
import com.dkanada.gramophone.glide.CustomPaletteTarget;
|
||||
import com.dkanada.gramophone.helper.HorizontalAdapterHelper;
|
||||
import com.dkanada.gramophone.interfaces.CabHolder;
|
||||
import com.dkanada.gramophone.model.Album;
|
||||
import com.dkanada.gramophone.util.MusicUtil;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class HorizontalAlbumAdapter extends AlbumAdapter {
|
||||
public HorizontalAlbumAdapter(@NonNull AppCompatActivity activity, List<Album> dataSet, boolean usePalette, @Nullable CabHolder cabHolder) {
|
||||
super(activity, dataSet, HorizontalAdapterHelper.LAYOUT_RES, usePalette, cabHolder);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ViewHolder createViewHolder(View view, int viewType) {
|
||||
ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) view.getLayoutParams();
|
||||
HorizontalAdapterHelper.applyMarginToLayoutParams(activity, params, viewType);
|
||||
return new ViewHolder(view);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setColors(int color, ViewHolder holder) {
|
||||
if (holder.itemView != null) {
|
||||
CardView card=(CardView)holder.itemView;
|
||||
card.setCardBackgroundColor(color);
|
||||
if (holder.title != null) {
|
||||
holder.title.setTextColor(MaterialValueHelper.getPrimaryTextColor(activity, ColorUtil.isColorLight(color)));
|
||||
}
|
||||
|
||||
if (holder.text != null) {
|
||||
holder.text.setTextColor(MaterialValueHelper.getSecondaryTextColor(activity, ColorUtil.isColorLight(color)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void loadAlbumCover(Album album, final ViewHolder holder) {
|
||||
if (holder.image == null) return;
|
||||
|
||||
CustomGlideRequest.Builder
|
||||
.from(Glide.with(activity), album.primary)
|
||||
.generatePalette(activity).build()
|
||||
.into(new CustomPaletteTarget(holder.image) {
|
||||
@Override
|
||||
public void onLoadCleared(Drawable placeholder) {
|
||||
super.onLoadCleared(placeholder);
|
||||
setColors(getAlbumArtistFooterColor(), holder);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onColorReady(int color) {
|
||||
if (usePalette) {
|
||||
setColors(color, holder);
|
||||
} else {
|
||||
setColors(getAlbumArtistFooterColor(), holder);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getAlbumText(Album album) {
|
||||
return MusicUtil.getYearString(album.getYear());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemViewType(int position) {
|
||||
return HorizontalAdapterHelper.getItemViewtype(position, getItemCount());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,209 @@
|
|||
package com.dkanada.gramophone.adapter.artist;
|
||||
|
||||
import android.graphics.drawable.Drawable;
|
||||
import androidx.annotation.LayoutRes;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.util.Pair;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.kabouzeid.appthemehelper.util.ColorUtil;
|
||||
import com.kabouzeid.appthemehelper.util.MaterialValueHelper;
|
||||
import com.dkanada.gramophone.R;
|
||||
import com.dkanada.gramophone.adapter.base.AbsMultiSelectAdapter;
|
||||
import com.dkanada.gramophone.adapter.base.MediaEntryViewHolder;
|
||||
import com.dkanada.gramophone.glide.CustomGlideRequest;
|
||||
import com.dkanada.gramophone.glide.CustomPaletteTarget;
|
||||
import com.dkanada.gramophone.helper.menu.SongsMenuHelper;
|
||||
import com.dkanada.gramophone.helper.sort.SortMethod;
|
||||
import com.dkanada.gramophone.interfaces.CabHolder;
|
||||
import com.dkanada.gramophone.model.Artist;
|
||||
import com.dkanada.gramophone.model.Song;
|
||||
import com.dkanada.gramophone.util.MusicUtil;
|
||||
import com.dkanada.gramophone.util.NavigationUtil;
|
||||
import com.dkanada.gramophone.util.PreferenceUtil;
|
||||
import com.simplecityapps.recyclerview_fastscroll.views.FastScrollRecyclerView;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class ArtistAdapter extends AbsMultiSelectAdapter<ArtistAdapter.ViewHolder, Artist> implements FastScrollRecyclerView.SectionedAdapter {
|
||||
protected final AppCompatActivity activity;
|
||||
protected List<Artist> dataSet;
|
||||
|
||||
protected int itemLayoutRes;
|
||||
|
||||
protected boolean usePalette;
|
||||
|
||||
public ArtistAdapter(@NonNull AppCompatActivity activity, List<Artist> dataSet, @LayoutRes int itemLayoutRes, boolean usePalette, @Nullable CabHolder cabHolder) {
|
||||
super(activity, cabHolder, R.menu.menu_media_selection);
|
||||
this.activity = activity;
|
||||
this.dataSet = dataSet;
|
||||
this.itemLayoutRes = itemLayoutRes;
|
||||
this.usePalette = usePalette;
|
||||
setHasStableIds(true);
|
||||
}
|
||||
|
||||
public void swapDataSet(List<Artist> dataSet) {
|
||||
this.dataSet = dataSet;
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
public List<Artist> getDataSet() {
|
||||
return dataSet;
|
||||
}
|
||||
|
||||
public void usePalette(boolean usePalette) {
|
||||
this.usePalette = usePalette;
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getItemId(int position) {
|
||||
return dataSet.get(position).hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
@NonNull
|
||||
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
View view = LayoutInflater.from(activity).inflate(itemLayoutRes, parent, false);
|
||||
return createViewHolder(view);
|
||||
}
|
||||
|
||||
protected ViewHolder createViewHolder(View view) {
|
||||
return new ViewHolder(view);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull final ViewHolder holder, int position) {
|
||||
final Artist artist = dataSet.get(position);
|
||||
|
||||
boolean isChecked = isChecked(artist);
|
||||
holder.itemView.setActivated(isChecked);
|
||||
|
||||
if (holder.getAdapterPosition() == getItemCount() - 1) {
|
||||
if (holder.shortSeparator != null) {
|
||||
holder.shortSeparator.setVisibility(View.GONE);
|
||||
}
|
||||
} else {
|
||||
if (holder.shortSeparator != null) {
|
||||
holder.shortSeparator.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
if (holder.title != null) {
|
||||
holder.title.setText(artist.getName());
|
||||
}
|
||||
|
||||
if (holder.text != null) {
|
||||
holder.text.setText(MusicUtil.getArtistInfoString(activity, artist));
|
||||
}
|
||||
|
||||
holder.itemView.setActivated(isChecked(artist));
|
||||
loadArtistImage(artist, holder);
|
||||
}
|
||||
|
||||
private void setColors(int color, ViewHolder holder) {
|
||||
if (holder.paletteColorContainer != null) {
|
||||
holder.paletteColorContainer.setBackgroundColor(color);
|
||||
if (holder.title != null) {
|
||||
holder.title.setTextColor(MaterialValueHelper.getPrimaryTextColor(activity, ColorUtil.isColorLight(color)));
|
||||
}
|
||||
|
||||
if (holder.text != null) {
|
||||
holder.text.setTextColor(MaterialValueHelper.getSecondaryTextColor(activity, ColorUtil.isColorLight(color)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void loadArtistImage(Artist artist, final ViewHolder holder) {
|
||||
if (holder.image == null) return;
|
||||
|
||||
CustomGlideRequest.Builder
|
||||
.from(Glide.with(activity), artist.primary)
|
||||
.generatePalette(activity).build()
|
||||
.into(new CustomPaletteTarget(holder.image) {
|
||||
@Override
|
||||
public void onLoadCleared(Drawable placeholder) {
|
||||
super.onLoadCleared(placeholder);
|
||||
setColors(getDefaultFooterColor(), holder);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onColorReady(int color) {
|
||||
if (usePalette) {
|
||||
setColors(color, holder);
|
||||
} else {
|
||||
setColors(getDefaultFooterColor(), holder);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return dataSet.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Artist getIdentifier(int position) {
|
||||
return dataSet.get(position);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getName(Artist artist) {
|
||||
return artist.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMultipleItemAction(@NonNull MenuItem menuItem, @NonNull List<Artist> selection) {
|
||||
SongsMenuHelper.handleMenuClick(activity, getSongList(selection), menuItem.getItemId());
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private List<Song> getSongList(@NonNull List<Artist> artists) {
|
||||
final List<Song> songs = new ArrayList<>();
|
||||
for (Artist artist : artists) {
|
||||
songs.addAll(artist.getSongs());
|
||||
}
|
||||
|
||||
return songs;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String getSectionName(int position) {
|
||||
return MusicUtil.getSectionName(dataSet.get(position).getName());
|
||||
}
|
||||
|
||||
public class ViewHolder extends MediaEntryViewHolder {
|
||||
public ViewHolder(@NonNull View itemView) {
|
||||
super(itemView);
|
||||
setImageTransitionName(activity.getString(R.string.transition_artist_image));
|
||||
if (menu != null) {
|
||||
menu.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (isInQuickSelectMode()) {
|
||||
toggleChecked(getAdapterPosition());
|
||||
} else {
|
||||
Pair[] artistPairs = new Pair[]{Pair.create(image, activity.getResources().getString(R.string.transition_artist_image))};
|
||||
NavigationUtil.goToArtist(activity, dataSet.get(getAdapterPosition()), artistPairs);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onLongClick(View view) {
|
||||
toggleChecked(getAdapterPosition());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,125 @@
|
|||
package com.dkanada.gramophone.adapter.base;
|
||||
|
||||
import android.content.Context;
|
||||
import androidx.annotation.MenuRes;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
|
||||
import com.afollestad.materialcab.MaterialCab;
|
||||
import com.dkanada.gramophone.R;
|
||||
import com.dkanada.gramophone.interfaces.CabHolder;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public abstract class AbsMultiSelectAdapter<VH extends RecyclerView.ViewHolder, I> extends RecyclerView.Adapter<VH> implements MaterialCab.Callback {
|
||||
private final Context context;
|
||||
private final CabHolder cabHolder;
|
||||
private int menuRes;
|
||||
|
||||
private MaterialCab cab;
|
||||
private List<I> checked;
|
||||
|
||||
public AbsMultiSelectAdapter(Context context, @Nullable CabHolder cabHolder, @MenuRes int menuRes) {
|
||||
this.context = context;
|
||||
this.cabHolder = cabHolder;
|
||||
this.menuRes = menuRes;
|
||||
|
||||
this.checked = new ArrayList<>();
|
||||
}
|
||||
|
||||
protected void setMultiSelectMenuRes(@MenuRes int menuRes) {
|
||||
this.menuRes = menuRes;
|
||||
}
|
||||
|
||||
protected boolean toggleChecked(final int position) {
|
||||
if (cabHolder != null) {
|
||||
I identifier = getIdentifier(position);
|
||||
if (identifier == null) return false;
|
||||
|
||||
if (!checked.remove(identifier)) checked.add(identifier);
|
||||
|
||||
notifyItemChanged(position);
|
||||
updateCab();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected void checkAll() {
|
||||
if (cabHolder != null) {
|
||||
checked.clear();
|
||||
for (int i = 0; i < getItemCount(); i++) {
|
||||
I identifier = getIdentifier(i);
|
||||
if (identifier != null) {
|
||||
checked.add(identifier);
|
||||
}
|
||||
}
|
||||
|
||||
notifyDataSetChanged();
|
||||
updateCab();
|
||||
}
|
||||
}
|
||||
|
||||
private void updateCab() {
|
||||
if (cabHolder != null) {
|
||||
if (cab == null || !cab.isActive()) {
|
||||
cab = cabHolder.openCab(menuRes, this);
|
||||
}
|
||||
|
||||
final int size = checked.size();
|
||||
if (size <= 0) cab.finish();
|
||||
else if (size == 1) cab.setTitle(getName(checked.get(0)));
|
||||
else cab.setTitle(context.getString(R.string.x_selected, size));
|
||||
}
|
||||
}
|
||||
|
||||
private void clearChecked() {
|
||||
checked.clear();
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
protected boolean isChecked(I identifier) {
|
||||
return checked.contains(identifier);
|
||||
}
|
||||
|
||||
protected boolean isInQuickSelectMode() {
|
||||
return cab != null && cab.isActive();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCabCreated(MaterialCab materialCab, Menu menu) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCabItemClicked(MenuItem menuItem) {
|
||||
if (menuItem.getItemId() == R.id.action_multi_select_adapter_check_all) {
|
||||
checkAll();
|
||||
} else {
|
||||
onMultipleItemAction(menuItem, new ArrayList<>(checked));
|
||||
cab.finish();
|
||||
clearChecked();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCabFinished(MaterialCab materialCab) {
|
||||
clearChecked();
|
||||
return true;
|
||||
}
|
||||
|
||||
protected String getName(I object) {
|
||||
return object.toString();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected abstract I getIdentifier(int position);
|
||||
|
||||
protected abstract void onMultipleItemAction(MenuItem menuItem, List<I> selection);
|
||||
}
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
package com.dkanada.gramophone.adapter.base;
|
||||
|
||||
import android.os.Build;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.dkanada.gramophone.R;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
|
||||
public class MediaEntryViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener {
|
||||
@Nullable
|
||||
@BindView(R.id.image)
|
||||
public ImageView image;
|
||||
|
||||
@Nullable
|
||||
@BindView(R.id.image_text)
|
||||
public TextView imageText;
|
||||
|
||||
@Nullable
|
||||
@BindView(R.id.title)
|
||||
public TextView title;
|
||||
|
||||
@Nullable
|
||||
@BindView(R.id.text)
|
||||
public TextView text;
|
||||
|
||||
@Nullable
|
||||
@BindView(R.id.menu)
|
||||
public View menu;
|
||||
|
||||
@Nullable
|
||||
@BindView(R.id.separator)
|
||||
public View separator;
|
||||
|
||||
@Nullable
|
||||
@BindView(R.id.short_separator)
|
||||
public View shortSeparator;
|
||||
|
||||
@Nullable
|
||||
@BindView(R.id.drag_view)
|
||||
public View dragView;
|
||||
|
||||
@Nullable
|
||||
@BindView(R.id.palette_color_container)
|
||||
public View paletteColorContainer;
|
||||
|
||||
public MediaEntryViewHolder(View itemView) {
|
||||
super(itemView);
|
||||
ButterKnife.bind(this, itemView);
|
||||
|
||||
itemView.setOnClickListener(this);
|
||||
itemView.setOnLongClickListener(this);
|
||||
}
|
||||
|
||||
protected void setImageTransitionName(@NonNull String transitionName) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && image != null) {
|
||||
image.setTransitionName(transitionName);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onLongClick(View v) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,112 @@
|
|||
package com.dkanada.gramophone.adapter.song;
|
||||
|
||||
import androidx.annotation.LayoutRes;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.dkanada.gramophone.R;
|
||||
import com.dkanada.gramophone.helper.MusicPlayerRemote;
|
||||
import com.dkanada.gramophone.interfaces.CabHolder;
|
||||
import com.dkanada.gramophone.model.Song;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public abstract class AbsOffsetSongAdapter extends SongAdapter {
|
||||
|
||||
protected static final int OFFSET_ITEM = 0;
|
||||
protected static final int SONG = 1;
|
||||
|
||||
public AbsOffsetSongAdapter(AppCompatActivity activity, List<Song> dataSet, @LayoutRes int itemLayoutRes, boolean usePalette, @Nullable CabHolder cabHolder) {
|
||||
super(activity, dataSet, itemLayoutRes, usePalette, cabHolder);
|
||||
}
|
||||
|
||||
public AbsOffsetSongAdapter(AppCompatActivity activity, List<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);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
protected Song getIdentifier(int position) {
|
||||
position--;
|
||||
|
||||
if (position < 0) return null;
|
||||
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() {
|
||||
// return empty song just to be safe
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
package com.dkanada.gramophone.adapter.song;
|
||||
|
||||
import androidx.annotation.LayoutRes;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import android.view.View;
|
||||
|
||||
import com.dkanada.gramophone.interfaces.CabHolder;
|
||||
import com.dkanada.gramophone.model.Song;
|
||||
import com.dkanada.gramophone.util.MusicUtil;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class AlbumSongAdapter extends SongAdapter {
|
||||
public AlbumSongAdapter(AppCompatActivity activity, List<Song> dataSet, @LayoutRes int itemLayoutRes, boolean usePalette, @Nullable CabHolder cabHolder) {
|
||||
super(activity, dataSet, itemLayoutRes, usePalette, cabHolder);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SongAdapter.ViewHolder createViewHolder(View view) {
|
||||
return new ViewHolder(view);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull SongAdapter.ViewHolder holder, int position) {
|
||||
super.onBindViewHolder(holder, position);
|
||||
|
||||
final Song song = dataSet.get(position);
|
||||
|
||||
if (holder.imageText != null) {
|
||||
final int trackNumber = MusicUtil.getFixedTrackNumber(song.trackNumber);
|
||||
final String trackNumberString = trackNumber > 0 ? String.valueOf(trackNumber) : "-";
|
||||
holder.imageText.setText(trackNumberString);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getSongText(Song song) {
|
||||
return MusicUtil.getReadableDurationString(song.duration);
|
||||
}
|
||||
|
||||
public class ViewHolder extends SongAdapter.ViewHolder {
|
||||
|
||||
public ViewHolder(@NonNull View itemView) {
|
||||
super(itemView);
|
||||
|
||||
if (imageText != null) {
|
||||
imageText.setVisibility(View.VISIBLE);
|
||||
}
|
||||
if (image != null) {
|
||||
image.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void loadAlbumCover(Song song, SongAdapter.ViewHolder holder) {
|
||||
// don't want to load it in this adapter
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,188 @@
|
|||
package com.dkanada.gramophone.adapter.song;
|
||||
|
||||
import android.os.Build;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.util.Pair;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.afollestad.materialcab.MaterialCab;
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.dkanada.gramophone.R;
|
||||
import com.dkanada.gramophone.glide.CustomGlideRequest;
|
||||
import com.dkanada.gramophone.helper.MusicPlayerRemote;
|
||||
import com.dkanada.gramophone.helper.menu.SongMenuHelper;
|
||||
import com.dkanada.gramophone.helper.menu.SongsMenuHelper;
|
||||
import com.dkanada.gramophone.interfaces.CabHolder;
|
||||
import com.dkanada.gramophone.model.Album;
|
||||
import com.dkanada.gramophone.model.Song;
|
||||
import com.dkanada.gramophone.util.NavigationUtil;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class ArtistSongAdapter extends ArrayAdapter<Song> implements MaterialCab.Callback {
|
||||
@Nullable
|
||||
private final CabHolder cabHolder;
|
||||
private MaterialCab cab;
|
||||
private List<Song> dataSet;
|
||||
private List<Song> checked;
|
||||
|
||||
@NonNull
|
||||
private final AppCompatActivity activity;
|
||||
|
||||
public ArtistSongAdapter(@NonNull AppCompatActivity activity, @NonNull List<Song> dataSet, @Nullable CabHolder cabHolder) {
|
||||
super(activity, R.layout.item_list, dataSet);
|
||||
this.activity = activity;
|
||||
this.cabHolder = cabHolder;
|
||||
this.dataSet = dataSet;
|
||||
checked = new ArrayList<>();
|
||||
}
|
||||
|
||||
public List<Song> getDataSet() {
|
||||
return dataSet;
|
||||
}
|
||||
|
||||
public void swapDataSet(List<Song> dataSet) {
|
||||
this.dataSet = dataSet;
|
||||
clear();
|
||||
addAll(dataSet);
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
@NonNull
|
||||
public View getView(final int position, View convertView, @NonNull ViewGroup parent) {
|
||||
final Song song = getItem(position);
|
||||
if (convertView == null) {
|
||||
convertView = LayoutInflater.from(getContext()).inflate(R.layout.item_list, parent, false);
|
||||
}
|
||||
|
||||
final TextView songTitle = convertView.findViewById(R.id.title);
|
||||
final TextView songInfo = convertView.findViewById(R.id.text);
|
||||
final ImageView albumArt = convertView.findViewById(R.id.image);
|
||||
final View shortSeparator = convertView.findViewById(R.id.short_separator);
|
||||
|
||||
if (position == getCount() - 1) {
|
||||
if (shortSeparator != null) {
|
||||
shortSeparator.setVisibility(View.GONE);
|
||||
}
|
||||
} else {
|
||||
if (shortSeparator != null) {
|
||||
shortSeparator.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
songTitle.setText(song.title);
|
||||
songInfo.setText(song.albumName);
|
||||
|
||||
CustomGlideRequest.Builder
|
||||
.from(Glide.with(activity), song.primary)
|
||||
.build().into(albumArt);
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
albumArt.setTransitionName(activity.getString(R.string.transition_album_art));
|
||||
}
|
||||
|
||||
final ImageView overflowButton = convertView.findViewById(R.id.menu);
|
||||
overflowButton.setOnClickListener(new SongMenuHelper.OnClickSongMenu(activity) {
|
||||
@Override
|
||||
public Song getSong() {
|
||||
return song;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onMenuItemClick(MenuItem item) {
|
||||
if (item.getItemId() == R.id.action_go_to_album) {
|
||||
Pair[] albumPairs = new Pair[]{Pair.create(albumArt, activity.getResources().getString(R.string.transition_album_art))};
|
||||
NavigationUtil.goToAlbum(activity, new Album(song), albumPairs);
|
||||
return true;
|
||||
}
|
||||
|
||||
return super.onMenuItemClick(item);
|
||||
}
|
||||
});
|
||||
|
||||
convertView.setActivated(isChecked(song));
|
||||
convertView.setOnClickListener(view -> {
|
||||
if (isInQuickSelectMode()) {
|
||||
toggleChecked(song);
|
||||
} else {
|
||||
MusicPlayerRemote.openQueue(dataSet, position, true);
|
||||
}
|
||||
});
|
||||
|
||||
convertView.setOnLongClickListener(view -> {
|
||||
toggleChecked(song);
|
||||
return true;
|
||||
});
|
||||
|
||||
return convertView;
|
||||
}
|
||||
|
||||
private void onMultipleItemAction(@NonNull MenuItem menuItem, @NonNull List<Song> selection) {
|
||||
SongsMenuHelper.handleMenuClick(activity, selection, menuItem.getItemId());
|
||||
}
|
||||
|
||||
protected void toggleChecked(Song song) {
|
||||
if (cabHolder != null) {
|
||||
openCabIfNecessary();
|
||||
|
||||
if (!checked.remove(song)) checked.add(song);
|
||||
notifyDataSetChanged();
|
||||
|
||||
final int size = checked.size();
|
||||
if (size <= 0) cab.finish();
|
||||
else if (size == 1) cab.setTitle(checked.get(0).title);
|
||||
else if (size > 1) cab.setTitle(String.valueOf(size));
|
||||
}
|
||||
}
|
||||
|
||||
private void openCabIfNecessary() {
|
||||
if (cabHolder != null) {
|
||||
if (cab == null || !cab.isActive()) {
|
||||
cab = cabHolder.openCab(R.menu.menu_media_selection, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void unCheckAll() {
|
||||
checked.clear();
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
protected boolean isChecked(Song song) {
|
||||
return checked.contains(song);
|
||||
}
|
||||
|
||||
protected boolean isInQuickSelectMode() {
|
||||
return cab != null && cab.isActive();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCabCreated(MaterialCab materialCab, Menu menu) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCabItemClicked(@NonNull MenuItem menuItem) {
|
||||
onMultipleItemAction(menuItem, new ArrayList<>(checked));
|
||||
cab.finish();
|
||||
unCheckAll();
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCabFinished(MaterialCab materialCab) {
|
||||
unCheckAll();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,135 @@
|
|||
package com.dkanada.gramophone.adapter.song;
|
||||
|
||||
import androidx.annotation.LayoutRes;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.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.dkanada.gramophone.R;
|
||||
import com.dkanada.gramophone.dialogs.RemoveFromPlaylistDialog;
|
||||
import com.dkanada.gramophone.interfaces.CabHolder;
|
||||
import com.dkanada.gramophone.model.Song;
|
||||
import com.dkanada.gramophone.util.ViewUtil;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class OrderablePlaylistSongAdapter extends PlaylistSongAdapter implements DraggableItemAdapter<OrderablePlaylistSongAdapter.ViewHolder> {
|
||||
|
||||
private OnMoveItemListener onMoveItemListener;
|
||||
|
||||
public OrderablePlaylistSongAdapter(@NonNull AppCompatActivity activity, @NonNull List<Song> dataSet, @LayoutRes int itemLayoutRes, boolean usePalette, @Nullable CabHolder cabHolder, @Nullable OnMoveItemListener onMoveItemListener) {
|
||||
super(activity, dataSet, itemLayoutRes, usePalette, cabHolder);
|
||||
setMultiSelectMenuRes(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 dataSet.get(position).id.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMultipleItemAction(@NonNull MenuItem menuItem, @NonNull List<Song> selection) {
|
||||
switch (menuItem.getItemId()) {
|
||||
case R.id.action_remove_from_playlist:
|
||||
RemoveFromPlaylistDialog.create(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) || ViewUtil.hitTest(holder.image, 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;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onItemDragStarted(int position) {
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onItemDragFinished(int fromPosition, int toPosition, boolean result) {
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
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(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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,170 @@
|
|||
package com.dkanada.gramophone.adapter.song;
|
||||
|
||||
import androidx.annotation.LayoutRes;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.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.dkanada.gramophone.R;
|
||||
import com.dkanada.gramophone.helper.MusicPlayerRemote;
|
||||
import com.dkanada.gramophone.interfaces.CabHolder;
|
||||
import com.dkanada.gramophone.model.Song;
|
||||
import com.dkanada.gramophone.util.ViewUtil;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class PlayingQueueAdapter extends SongAdapter implements DraggableItemAdapter<PlayingQueueAdapter.ViewHolder> {
|
||||
private static final int HISTORY = 0;
|
||||
private static final int CURRENT = 1;
|
||||
private static final int UP_NEXT = 2;
|
||||
|
||||
private int current;
|
||||
|
||||
public PlayingQueueAdapter(AppCompatActivity activity, List<Song> dataSet, int current, @LayoutRes int itemLayoutRes, boolean usePalette, @Nullable CabHolder cabHolder) {
|
||||
super(activity, dataSet, itemLayoutRes, usePalette, cabHolder);
|
||||
this.current = current;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SongAdapter.ViewHolder createViewHolder(View view) {
|
||||
return new ViewHolder(view);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull SongAdapter.ViewHolder holder, int position) {
|
||||
super.onBindViewHolder(holder, position);
|
||||
if (holder.imageText != null) {
|
||||
holder.imageText.setText(String.valueOf(position - current));
|
||||
}
|
||||
if (holder.getItemViewType() == HISTORY || holder.getItemViewType() == CURRENT) {
|
||||
setAlpha(holder, 0.5f);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemViewType(int position) {
|
||||
if (position < current) {
|
||||
return HISTORY;
|
||||
} else if (position > current) {
|
||||
return UP_NEXT;
|
||||
}
|
||||
return CURRENT;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void loadAlbumCover(Song song, SongAdapter.ViewHolder holder) {
|
||||
// don't want to load it in this adapter
|
||||
}
|
||||
|
||||
public void swapDataSet(List<Song> dataSet, int position) {
|
||||
this.dataSet = dataSet;
|
||||
current = position;
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
public void setCurrent(int current) {
|
||||
this.current = current;
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
protected void setAlpha(SongAdapter.ViewHolder holder, float alpha) {
|
||||
if (holder.image != null) {
|
||||
holder.image.setAlpha(alpha);
|
||||
}
|
||||
|
||||
if (holder.title != null) {
|
||||
holder.title.setAlpha(alpha);
|
||||
}
|
||||
|
||||
if (holder.text != null) {
|
||||
holder.text.setAlpha(alpha);
|
||||
}
|
||||
|
||||
if (holder.imageText != null) {
|
||||
holder.imageText.setAlpha(alpha);
|
||||
}
|
||||
|
||||
if (holder.paletteColorContainer != null) {
|
||||
holder.paletteColorContainer.setAlpha(alpha);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCheckCanStartDrag(ViewHolder holder, int position, int x, int y) {
|
||||
return ViewUtil.hitTest(holder.imageText, x, y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemDraggableRange onGetItemDraggableRange(ViewHolder holder, int position) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMoveItem(int fromPosition, int toPosition) {
|
||||
MusicPlayerRemote.moveSong(fromPosition, toPosition);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCheckCanDrop(int draggingPosition, int dropPosition) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onItemDragStarted(int position) {
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onItemDragFinished(int fromPosition, int toPosition, boolean result) {
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
public class ViewHolder extends SongAdapter.ViewHolder implements DraggableItemViewHolder {
|
||||
@DraggableItemStateFlags
|
||||
private int mDragStateFlags;
|
||||
|
||||
public ViewHolder(@NonNull View itemView) {
|
||||
super(itemView);
|
||||
if (imageText != null) {
|
||||
imageText.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
if (image != null) {
|
||||
image.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getSongMenuRes() {
|
||||
return R.menu.menu_item_playing_queue_song;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean onSongMenuItemClick(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case R.id.action_remove_from_queue:
|
||||
MusicPlayerRemote.removeFromQueue(getAdapterPosition());
|
||||
return true;
|
||||
}
|
||||
|
||||
return super.onSongMenuItemClick(item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDragStateFlags(@DraggableItemStateFlags int flags) {
|
||||
mDragStateFlags = flags;
|
||||
}
|
||||
|
||||
@Override
|
||||
@DraggableItemStateFlags
|
||||
public int getDragStateFlags() {
|
||||
return mDragStateFlags;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,94 @@
|
|||
package com.dkanada.gramophone.adapter.song;
|
||||
|
||||
import androidx.annotation.LayoutRes;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.util.Pair;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
|
||||
import com.kabouzeid.appthemehelper.ThemeStore;
|
||||
import com.dkanada.gramophone.R;
|
||||
import com.dkanada.gramophone.interfaces.CabHolder;
|
||||
import com.dkanada.gramophone.model.Album;
|
||||
import com.dkanada.gramophone.model.Song;
|
||||
import com.dkanada.gramophone.util.MusicUtil;
|
||||
import com.dkanada.gramophone.util.NavigationUtil;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class PlaylistSongAdapter extends AbsOffsetSongAdapter {
|
||||
public PlaylistSongAdapter(AppCompatActivity activity, @NonNull List<Song> dataSet, @LayoutRes int itemLayoutRes, boolean usePalette, @Nullable CabHolder cabHolder) {
|
||||
super(activity, dataSet, itemLayoutRes, usePalette, cabHolder, false);
|
||||
setMultiSelectMenuRes(R.menu.menu_cannot_delete_single_songs_playlist_songs_selection);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SongAdapter.ViewHolder createViewHolder(View view) {
|
||||
return new PlaylistSongAdapter.ViewHolder(view);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull final SongAdapter.ViewHolder holder, int position) {
|
||||
if (holder.getItemViewType() == OFFSET_ITEM) {
|
||||
int textColor = ThemeStore.textColorSecondary(activity);
|
||||
if (holder.title != null) {
|
||||
holder.title.setText(MusicUtil.getPlaylistInfoString(activity, dataSet));
|
||||
holder.title.setTextColor(textColor);
|
||||
}
|
||||
|
||||
if (holder.text != null) {
|
||||
holder.text.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
if (holder.menu != null) {
|
||||
holder.menu.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
if (holder.image != null) {
|
||||
final int padding = activity.getResources().getDimensionPixelSize(R.dimen.default_item_margin) / 2;
|
||||
holder.image.setPadding(padding, padding, padding, padding);
|
||||
holder.image.setColorFilter(textColor);
|
||||
holder.image.setImageResource(R.drawable.ic_timer_white_24dp);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
public class ViewHolder extends AbsOffsetSongAdapter.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, new Album(dataSet.get(getAdapterPosition() - 1)), albumPairs);
|
||||
return true;
|
||||
}
|
||||
|
||||
return super.onSongMenuItemClick(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,82 @@
|
|||
package com.dkanada.gramophone.adapter.song;
|
||||
|
||||
import android.graphics.Typeface;
|
||||
import androidx.annotation.LayoutRes;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import android.view.View;
|
||||
|
||||
import com.kabouzeid.appthemehelper.ThemeStore;
|
||||
import com.dkanada.gramophone.R;
|
||||
import com.dkanada.gramophone.helper.MusicPlayerRemote;
|
||||
import com.dkanada.gramophone.interfaces.CabHolder;
|
||||
import com.dkanada.gramophone.model.Song;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class ShuffleButtonSongAdapter extends AbsOffsetSongAdapter {
|
||||
|
||||
public ShuffleButtonSongAdapter(AppCompatActivity activity, List<Song> dataSet, @LayoutRes int itemLayoutRes, boolean usePalette, @Nullable CabHolder cabHolder) {
|
||||
super(activity, dataSet, itemLayoutRes, usePalette, cabHolder);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SongAdapter.ViewHolder createViewHolder(View view) {
|
||||
return new ShuffleButtonSongAdapter.ViewHolder(view);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull final SongAdapter.ViewHolder holder, int position) {
|
||||
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());
|
||||
holder.title.setTextColor(accentColor);
|
||||
holder.title.setTypeface(Typeface.create("sans-serif-medium", Typeface.NORMAL));
|
||||
}
|
||||
|
||||
if (holder.text != null) {
|
||||
holder.text.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
if (holder.menu != null) {
|
||||
holder.menu.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
if (holder.image != null) {
|
||||
final int padding = activity.getResources().getDimensionPixelSize(R.dimen.default_item_margin) / 2;
|
||||
holder.image.setPadding(padding, padding, padding, padding);
|
||||
holder.image.setColorFilter(accentColor);
|
||||
holder.image.setImageResource(R.drawable.ic_shuffle_white_24dp);
|
||||
}
|
||||
|
||||
if (holder.separator != null) {
|
||||
holder.separator.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
if (holder.shortSeparator != null) {
|
||||
holder.shortSeparator.setVisibility(View.GONE);
|
||||
}
|
||||
} else {
|
||||
super.onBindViewHolder(holder, position - 1);
|
||||
}
|
||||
}
|
||||
|
||||
public class ViewHolder extends AbsOffsetSongAdapter.ViewHolder {
|
||||
public ViewHolder(@NonNull View itemView) {
|
||||
super(itemView);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (getItemViewType() == OFFSET_ITEM) {
|
||||
MusicPlayerRemote.openAndShuffleQueue(dataSet, true);
|
||||
return;
|
||||
}
|
||||
|
||||
super.onClick(v);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,276 @@
|
|||
package com.dkanada.gramophone.adapter.song;
|
||||
|
||||
import android.graphics.drawable.Drawable;
|
||||
import androidx.annotation.LayoutRes;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.util.Pair;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.afollestad.materialcab.MaterialCab;
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.kabouzeid.appthemehelper.util.ColorUtil;
|
||||
import com.kabouzeid.appthemehelper.util.MaterialValueHelper;
|
||||
import com.dkanada.gramophone.R;
|
||||
import com.dkanada.gramophone.adapter.base.AbsMultiSelectAdapter;
|
||||
import com.dkanada.gramophone.adapter.base.MediaEntryViewHolder;
|
||||
import com.dkanada.gramophone.glide.CustomGlideRequest;
|
||||
import com.dkanada.gramophone.glide.CustomPaletteTarget;
|
||||
import com.dkanada.gramophone.helper.MusicPlayerRemote;
|
||||
import com.dkanada.gramophone.helper.menu.SongMenuHelper;
|
||||
import com.dkanada.gramophone.helper.menu.SongsMenuHelper;
|
||||
import com.dkanada.gramophone.helper.sort.SortMethod;
|
||||
import com.dkanada.gramophone.interfaces.CabHolder;
|
||||
import com.dkanada.gramophone.model.Album;
|
||||
import com.dkanada.gramophone.model.Song;
|
||||
import com.dkanada.gramophone.util.MusicUtil;
|
||||
import com.dkanada.gramophone.util.NavigationUtil;
|
||||
import com.dkanada.gramophone.util.PreferenceUtil;
|
||||
import com.simplecityapps.recyclerview_fastscroll.views.FastScrollRecyclerView;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class SongAdapter extends AbsMultiSelectAdapter<SongAdapter.ViewHolder, Song> implements MaterialCab.Callback, FastScrollRecyclerView.SectionedAdapter {
|
||||
|
||||
protected final AppCompatActivity activity;
|
||||
protected List<Song> dataSet;
|
||||
|
||||
protected int itemLayoutRes;
|
||||
|
||||
protected boolean usePalette;
|
||||
protected boolean showSectionName;
|
||||
|
||||
public SongAdapter(AppCompatActivity activity, List<Song> dataSet, @LayoutRes int itemLayoutRes, boolean usePalette, @Nullable CabHolder cabHolder) {
|
||||
this(activity, dataSet, itemLayoutRes, usePalette, cabHolder, true);
|
||||
}
|
||||
|
||||
public SongAdapter(AppCompatActivity activity, List<Song> dataSet, @LayoutRes int itemLayoutRes, boolean usePalette, @Nullable CabHolder cabHolder, boolean showSectionName) {
|
||||
super(activity, cabHolder, R.menu.menu_media_selection);
|
||||
|
||||
this.activity = activity;
|
||||
this.dataSet = dataSet;
|
||||
this.itemLayoutRes = itemLayoutRes;
|
||||
this.usePalette = usePalette;
|
||||
this.showSectionName = showSectionName;
|
||||
setHasStableIds(true);
|
||||
}
|
||||
|
||||
public void swapDataSet(List<Song> dataSet) {
|
||||
this.dataSet = dataSet;
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
public void usePalette(boolean usePalette) {
|
||||
this.usePalette = usePalette;
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
public List<Song> getDataSet() {
|
||||
return dataSet;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getItemId(int position) {
|
||||
return dataSet.get(position).hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
@NonNull
|
||||
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
View view = LayoutInflater.from(activity).inflate(itemLayoutRes, parent, false);
|
||||
return createViewHolder(view);
|
||||
}
|
||||
|
||||
protected ViewHolder createViewHolder(View view) {
|
||||
return new ViewHolder(view);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull final ViewHolder holder, int position) {
|
||||
final Song song = dataSet.get(position);
|
||||
|
||||
boolean isChecked = isChecked(song);
|
||||
holder.itemView.setActivated(isChecked);
|
||||
|
||||
if (holder.getAdapterPosition() == getItemCount() - 1) {
|
||||
if (holder.shortSeparator != null) {
|
||||
holder.shortSeparator.setVisibility(View.GONE);
|
||||
}
|
||||
} else {
|
||||
if (holder.shortSeparator != null) {
|
||||
holder.shortSeparator.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
if (holder.title != null) {
|
||||
holder.title.setText(getSongTitle(song));
|
||||
}
|
||||
|
||||
if (holder.text != null) {
|
||||
holder.text.setText(getSongText(song));
|
||||
}
|
||||
|
||||
loadAlbumCover(song, holder);
|
||||
}
|
||||
|
||||
private void setColors(int color, ViewHolder holder) {
|
||||
if (holder.paletteColorContainer != null) {
|
||||
holder.paletteColorContainer.setBackgroundColor(color);
|
||||
if (holder.title != null) {
|
||||
holder.title.setTextColor(MaterialValueHelper.getPrimaryTextColor(activity, ColorUtil.isColorLight(color)));
|
||||
}
|
||||
|
||||
if (holder.text != null) {
|
||||
holder.text.setTextColor(MaterialValueHelper.getSecondaryTextColor(activity, ColorUtil.isColorLight(color)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void loadAlbumCover(Song song, final ViewHolder holder) {
|
||||
if (holder.image == null) return;
|
||||
|
||||
CustomGlideRequest.Builder
|
||||
.from(Glide.with(activity), song.primary)
|
||||
.generatePalette(activity).build()
|
||||
.into(new CustomPaletteTarget(holder.image) {
|
||||
@Override
|
||||
public void onLoadCleared(Drawable placeholder) {
|
||||
super.onLoadCleared(placeholder);
|
||||
setColors(getDefaultFooterColor(), holder);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onColorReady(int color) {
|
||||
if (usePalette) {
|
||||
setColors(color, holder);
|
||||
} else {
|
||||
setColors(getDefaultFooterColor(), holder);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected String getSongTitle(Song song) {
|
||||
return song.title;
|
||||
}
|
||||
|
||||
protected String getSongText(Song song) {
|
||||
return MusicUtil.getSongInfoString(song);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return dataSet.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Song getIdentifier(int position) {
|
||||
return dataSet.get(position);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getName(Song song) {
|
||||
return song.title;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMultipleItemAction(@NonNull MenuItem menuItem, @NonNull List<Song> selection) {
|
||||
SongsMenuHelper.handleMenuClick(activity, selection, menuItem.getItemId());
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String getSectionName(int position) {
|
||||
if (!showSectionName) {
|
||||
return "";
|
||||
}
|
||||
|
||||
@Nullable String sectionName = null;
|
||||
switch (PreferenceUtil.getInstance(activity).getSongSortMethod()) {
|
||||
case SortMethod.NAME:
|
||||
sectionName = dataSet.get(position).title;
|
||||
break;
|
||||
case SortMethod.ALBUM:
|
||||
sectionName = dataSet.get(position).albumName;
|
||||
break;
|
||||
case SortMethod.ARTIST:
|
||||
sectionName = dataSet.get(position).artistName;
|
||||
break;
|
||||
case SortMethod.YEAR:
|
||||
return MusicUtil.getYearString(dataSet.get(position).year);
|
||||
case SortMethod.RANDOM:
|
||||
return activity.getResources().getString(R.string.random);
|
||||
}
|
||||
|
||||
return MusicUtil.getSectionName(sectionName);
|
||||
}
|
||||
|
||||
public class ViewHolder extends MediaEntryViewHolder {
|
||||
protected int DEFAULT_MENU_RES = SongMenuHelper.MENU_RES;
|
||||
|
||||
public ViewHolder(@NonNull View itemView) {
|
||||
super(itemView);
|
||||
setImageTransitionName(activity.getString(R.string.transition_album_art));
|
||||
|
||||
if (menu == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
menu.setOnClickListener(new SongMenuHelper.OnClickSongMenu(activity) {
|
||||
@Override
|
||||
public Song getSong() {
|
||||
return ViewHolder.this.getSong();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMenuRes() {
|
||||
return getSongMenuRes();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onMenuItemClick(MenuItem item) {
|
||||
return onSongMenuItemClick(item) || super.onMenuItemClick(item);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected Song getSong() {
|
||||
return dataSet.get(getAdapterPosition());
|
||||
}
|
||||
|
||||
protected int getSongMenuRes() {
|
||||
return DEFAULT_MENU_RES;
|
||||
}
|
||||
|
||||
protected boolean onSongMenuItemClick(MenuItem item) {
|
||||
if (image != null && image.getVisibility() == View.VISIBLE) {
|
||||
switch (item.getItemId()) {
|
||||
case R.id.action_go_to_album:
|
||||
Pair[] albumPairs = new Pair[]{Pair.create(image, activity.getResources().getString(R.string.transition_album_art))};
|
||||
NavigationUtil.goToAlbum(activity, new Album(getSong()), albumPairs);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (isInQuickSelectMode()) {
|
||||
toggleChecked(getAdapterPosition());
|
||||
} else {
|
||||
MusicPlayerRemote.openQueue(dataSet, getAdapterPosition(), true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onLongClick(View view) {
|
||||
return toggleChecked(getAdapterPosition());
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue