convert category information to an enum

This commit is contained in:
dkanada 2021-05-28 13:36:55 +09:00
commit fbffb4ef8a
7 changed files with 73 additions and 154 deletions

View file

@ -14,20 +14,20 @@ import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.ItemTouchHelper; import androidx.recyclerview.widget.ItemTouchHelper;
import com.dkanada.gramophone.R; import com.dkanada.gramophone.R;
import com.dkanada.gramophone.model.CategoryInfo; import com.dkanada.gramophone.model.Category;
import com.dkanada.gramophone.helper.SwipeAndDragHelper; import com.dkanada.gramophone.helper.SwipeAndDragHelper;
import java.util.List; import java.util.List;
@SuppressLint("ClickableViewAccessibility") @SuppressLint("ClickableViewAccessibility")
public class CategoryAdapter extends RecyclerView.Adapter<CategoryAdapter.ViewHolder> implements SwipeAndDragHelper.ActionCompletionContract { public class CategoryAdapter extends RecyclerView.Adapter<CategoryAdapter.ViewHolder> implements SwipeAndDragHelper.ActionCompletionContract {
private List<CategoryInfo> categories; private List<Category> categories;
private ItemTouchHelper touchHelper; private ItemTouchHelper touchHelper;
public CategoryAdapter(List<CategoryInfo> categories) { public CategoryAdapter(List<Category> categories) {
this.categories = categories; this.categories = categories;
SwipeAndDragHelper swipeAndDragHelper = new SwipeAndDragHelper(this); SwipeAndDragHelper swipeAndDragHelper = new SwipeAndDragHelper(this);
touchHelper = new ItemTouchHelper(swipeAndDragHelper); this.touchHelper = new ItemTouchHelper(swipeAndDragHelper);
} }
@NonNull @NonNull
@ -40,17 +40,17 @@ public class CategoryAdapter extends RecyclerView.Adapter<CategoryAdapter.ViewHo
@Override @Override
public void onBindViewHolder(@NonNull CategoryAdapter.ViewHolder holder, int position) { public void onBindViewHolder(@NonNull CategoryAdapter.ViewHolder holder, int position) {
CategoryInfo category = categories.get(position); Category category = categories.get(position);
holder.checkBox.setChecked(category.visible); holder.checkBox.setChecked(category.select);
holder.title.setText(holder.title.getResources().getString(category.category.stringRes)); holder.title.setText(holder.title.getResources().getString(category.title));
holder.itemView.setOnClickListener(v -> { holder.itemView.setOnClickListener(v -> {
if (!(category.visible && isLastCheckedCategory(category))) { if (category.select && categories.stream().filter(c -> c.select).count() == 1) {
category.visible = !category.visible;
holder.checkBox.setChecked(category.visible);
} else {
Toast.makeText(holder.itemView.getContext(), R.string.you_have_to_select_at_least_one_category, Toast.LENGTH_SHORT).show(); Toast.makeText(holder.itemView.getContext(), R.string.you_have_to_select_at_least_one_category, Toast.LENGTH_SHORT).show();
} else {
category.select = !category.select;
holder.checkBox.setChecked(category.select);
} }
}); });
@ -68,16 +68,16 @@ public class CategoryAdapter extends RecyclerView.Adapter<CategoryAdapter.ViewHo
return categories.size(); return categories.size();
} }
public void setCategories(List<CategoryInfo> categories) { public void setCategories(List<Category> categories) {
this.categories = categories; this.categories = categories;
notifyDataSetChanged(); notifyDataSetChanged();
} }
@Override @Override
public void onViewMoved(int oldPosition, int newPosition) { public void onViewMoved(int oldPosition, int newPosition) {
CategoryInfo categoryInfo = categories.get(oldPosition); Category category = categories.get(oldPosition);
categories.remove(oldPosition); categories.remove(oldPosition);
categories.add(newPosition, categoryInfo); categories.add(newPosition, category);
notifyItemMoved(oldPosition, newPosition); notifyItemMoved(oldPosition, newPosition);
} }
@ -85,20 +85,10 @@ public class CategoryAdapter extends RecyclerView.Adapter<CategoryAdapter.ViewHo
touchHelper.attachToRecyclerView(recyclerView); touchHelper.attachToRecyclerView(recyclerView);
} }
public List<CategoryInfo> getCategories() { public List<Category> getCategories() {
return categories; return categories;
} }
private boolean isLastCheckedCategory(CategoryInfo category) {
if (category.visible) {
for (CategoryInfo c : categories) {
if (c != category && c.visible) return false;
}
}
return true;
}
public static class ViewHolder extends RecyclerView.ViewHolder { public static class ViewHolder extends RecyclerView.ViewHolder {
public CheckBox checkBox; public CheckBox checkBox;
public TextView title; public TextView title;

View file

@ -11,7 +11,7 @@ import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentPagerAdapter; import androidx.fragment.app.FragmentPagerAdapter;
import com.dkanada.gramophone.fragments.mainactivity.library.pager.FavoritesFragment; import com.dkanada.gramophone.fragments.mainactivity.library.pager.FavoritesFragment;
import com.dkanada.gramophone.model.CategoryInfo; import com.dkanada.gramophone.model.Category;
import com.dkanada.gramophone.fragments.mainactivity.library.pager.AlbumsFragment; import com.dkanada.gramophone.fragments.mainactivity.library.pager.AlbumsFragment;
import com.dkanada.gramophone.fragments.mainactivity.library.pager.ArtistsFragment; import com.dkanada.gramophone.fragments.mainactivity.library.pager.ArtistsFragment;
import com.dkanada.gramophone.fragments.mainactivity.library.pager.GenresFragment; import com.dkanada.gramophone.fragments.mainactivity.library.pager.GenresFragment;
@ -23,7 +23,7 @@ import java.lang.ref.WeakReference;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.stream.Collectors;
public class MusicLibraryPagerAdapter extends FragmentPagerAdapter { public class MusicLibraryPagerAdapter extends FragmentPagerAdapter {
@ -36,24 +36,26 @@ public class MusicLibraryPagerAdapter extends FragmentPagerAdapter {
public MusicLibraryPagerAdapter(@NonNull final Context context, final FragmentManager fragmentManager) { public MusicLibraryPagerAdapter(@NonNull final Context context, final FragmentManager fragmentManager) {
super(fragmentManager); super(fragmentManager);
mContext = context; mContext = context;
setCategoryInfos(PreferenceUtil.getInstance(context).getCategories()); setCategories(PreferenceUtil.getInstance(context).getCategories()
.stream()
.filter(category -> category.select)
.collect(Collectors.toList()));
} }
public void setCategoryInfos(@NonNull List<CategoryInfo> categoryInfos) { public void setCategories(@NonNull List<Category> categories) {
mHolderList.clear(); mHolderList.clear();
for (CategoryInfo categoryInfo : categoryInfos) { for (Category category : categories) {
if (categoryInfo.visible) { MusicFragments fragment = MusicFragments.valueOf(category.toString());
MusicFragments fragment = MusicFragments.valueOf(categoryInfo.category.toString());
Holder holder = new Holder(); Holder holder = new Holder();
holder.mClassName = fragment.getFragmentClass().getName(); holder.mClassName = fragment.getFragmentClass().getName();
holder.title = mContext.getResources() holder.title = mContext.getResources().getString(category.title).toUpperCase();
.getString(categoryInfo.category.stringRes)
.toUpperCase(Locale.getDefault());
mHolderList.add(holder); mHolderList.add(holder);
} }
}
alignCache(); alignCache();
notifyDataSetChanged(); notifyDataSetChanged();

View file

@ -12,11 +12,12 @@ import androidx.recyclerview.widget.RecyclerView;
import com.afollestad.materialdialogs.MaterialDialog; import com.afollestad.materialdialogs.MaterialDialog;
import com.dkanada.gramophone.R; import com.dkanada.gramophone.R;
import com.dkanada.gramophone.adapter.CategoryAdapter; import com.dkanada.gramophone.adapter.CategoryAdapter;
import com.dkanada.gramophone.model.CategoryInfo; import com.dkanada.gramophone.model.Category;
import com.dkanada.gramophone.util.PreferenceUtil; import com.dkanada.gramophone.util.PreferenceUtil;
import java.util.ArrayList; import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.stream.Collectors;
public class CategoryPreferenceDialog extends DialogFragment { public class CategoryPreferenceDialog extends DialogFragment {
public static final String TAG = CategoryPreferenceDialog.class.getSimpleName(); public static final String TAG = CategoryPreferenceDialog.class.getSimpleName();
@ -31,20 +32,13 @@ public class CategoryPreferenceDialog extends DialogFragment {
@Override @Override
public Dialog onCreateDialog(Bundle savedInstanceState) { public Dialog onCreateDialog(Bundle savedInstanceState) {
View view = requireActivity().getLayoutInflater().inflate(R.layout.preference_dialog_category, null); View view = requireActivity().getLayoutInflater().inflate(R.layout.preference_dialog_category, null);
List<Category> categories = PreferenceUtil.getInstance(getContext()).getCategories();
List<CategoryInfo> categories;
if (savedInstanceState != null) {
categories = savedInstanceState.getParcelableArrayList(PreferenceUtil.CATEGORIES);
} else {
categories = PreferenceUtil.getInstance(getContext()).getCategories();
}
adapter = new CategoryAdapter(categories); adapter = new CategoryAdapter(categories);
RecyclerView recyclerView = view.findViewById(R.id.recycler_view); RecyclerView recyclerView = view.findViewById(R.id.recycler_view);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity())); recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
recyclerView.setAdapter(adapter); recyclerView.setAdapter(adapter);
adapter.attachToRecyclerView(recyclerView); adapter.attachToRecyclerView(recyclerView);
return new MaterialDialog.Builder(requireActivity()) return new MaterialDialog.Builder(requireActivity())
@ -54,33 +48,16 @@ public class CategoryPreferenceDialog extends DialogFragment {
.neutralText(R.string.reset_action) .neutralText(R.string.reset_action)
.negativeText(android.R.string.cancel) .negativeText(android.R.string.cancel)
.autoDismiss(false) .autoDismiss(false)
.onNeutral((dialog, action) -> adapter.setCategories(PreferenceUtil.getInstance(getContext()).getDefaultCategories())) .onNeutral((dialog, action) -> {
adapter.setCategories(Arrays.stream(Category.values())
.peek(category -> category.select = true)
.collect(Collectors.toList()));
})
.onNegative((dialog, action) -> dismiss()) .onNegative((dialog, action) -> dismiss())
.onPositive((dialog, action) -> { .onPositive((dialog, action) -> {
updateCategories(adapter.getCategories()); PreferenceUtil.getInstance(getContext()).setCategories(adapter.getCategories());
dismiss(); dismiss();
}) })
.build(); .build();
} }
@Override
public void onSaveInstanceState(@NonNull Bundle outState) {
super.onSaveInstanceState(outState);
outState.putParcelableArrayList(PreferenceUtil.CATEGORIES, new ArrayList<>(adapter.getCategories()));
}
private void updateCategories(List<CategoryInfo> categories) {
if (getSelected(categories) == 0) return;
PreferenceUtil.getInstance(getContext()).setCategories(categories);
}
private int getSelected(List<CategoryInfo> categories) {
int selected = 0;
for (CategoryInfo category : categories) {
if (category.visible) selected++;
}
return selected;
}
} }

View file

@ -85,7 +85,7 @@ public class LibraryFragment extends AbsMainActivityFragment implements CabHolde
public void onSharedPreferenceChanged(SharedPreferences preferences, String key) { public void onSharedPreferenceChanged(SharedPreferences preferences, String key) {
if (PreferenceUtil.CATEGORIES.equals(key)) { if (PreferenceUtil.CATEGORIES.equals(key)) {
Fragment current = getCurrentFragment(); Fragment current = getCurrentFragment();
pagerAdapter.setCategoryInfos(PreferenceUtil.getInstance(getActivity()).getCategories()); pagerAdapter.setCategories(PreferenceUtil.getInstance(getActivity()).getCategories());
binding.pager.setOffscreenPageLimit(pagerAdapter.getCount() - 1); binding.pager.setOffscreenPageLimit(pagerAdapter.getCount() - 1);
int position = pagerAdapter.getItemPosition(current); int position = pagerAdapter.getItemPosition(current);
if (position < 0) position = 0; if (position < 0) position = 0;

View file

@ -0,0 +1,23 @@
package com.dkanada.gramophone.model;
import androidx.annotation.StringRes;
import com.dkanada.gramophone.R;
public enum Category {
SONGS(R.string.songs),
ALBUMS(R.string.albums),
ARTISTS(R.string.artists),
GENRES(R.string.genres),
PLAYLISTS(R.string.playlists),
FAVORITES(R.string.favorites);
@StringRes
public final int title;
public boolean select;
Category(int title) {
this.title = title;
}
}

View file

@ -1,59 +0,0 @@
package com.dkanada.gramophone.model;
import android.os.Parcel;
import android.os.Parcelable;
import androidx.annotation.StringRes;
import com.dkanada.gramophone.R;
public class CategoryInfo implements Parcelable {
public Category category;
public boolean visible;
public CategoryInfo(Category category, boolean visible) {
this.category = category;
this.visible = visible;
}
private CategoryInfo(Parcel source) {
category = (Category) source.readSerializable();
visible = source.readInt() == 1;
}
@Override
public int describeContents() {
return 0;
}
public void writeToParcel(Parcel dest, int flags) {
dest.writeSerializable(category);
dest.writeInt(visible ? 1 : 0);
}
public static final Parcelable.Creator<CategoryInfo> CREATOR = new Parcelable.Creator<CategoryInfo>() {
public CategoryInfo createFromParcel(Parcel source) {
return new CategoryInfo(source);
}
public CategoryInfo[] newArray(int size) {
return new CategoryInfo[size];
}
};
public enum Category {
SONGS(R.string.songs),
ALBUMS(R.string.albums),
ARTISTS(R.string.artists),
GENRES(R.string.genres),
PLAYLISTS(R.string.playlists),
FAVORITES(R.string.favorites);
@StringRes
public final int stringRes;
Category(int stringRes) {
this.stringRes = stringRes;
}
}
}

View file

@ -12,13 +12,12 @@ import com.dkanada.gramophone.model.Theme;
import com.dkanada.gramophone.R; import com.dkanada.gramophone.R;
import com.dkanada.gramophone.model.SortMethod; import com.dkanada.gramophone.model.SortMethod;
import com.dkanada.gramophone.model.SortOrder; import com.dkanada.gramophone.model.SortOrder;
import com.dkanada.gramophone.model.CategoryInfo; import com.dkanada.gramophone.model.Category;
import com.dkanada.gramophone.model.Codec; import com.dkanada.gramophone.model.Codec;
import com.dkanada.gramophone.interfaces.base.PreferenceMigration; import com.dkanada.gramophone.interfaces.base.PreferenceMigration;
import com.dkanada.gramophone.fragments.player.NowPlayingScreen; import com.dkanada.gramophone.fragments.player.NowPlayingScreen;
import java.lang.reflect.Type; import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
@ -95,8 +94,8 @@ public final class PreferenceUtil {
@Override @Override
public void migrate(SharedPreferences preferences) { public void migrate(SharedPreferences preferences) {
String theme = preferences.getString(GENERAL_THEME, "DARK"); String theme = preferences.getString(GENERAL_THEME, "DARK");
String imageSize = preferences.getString(IMAGE_CACHE_SIZE, "400"); String imageSize = preferences.getString(IMAGE_CACHE_SIZE, "400000000");
String mediaSize = preferences.getString(MEDIA_CACHE_SIZE, "400"); String mediaSize = preferences.getString(MEDIA_CACHE_SIZE, "400000000");
preferences.edit().putString(GENERAL_THEME, Theme.valueOf(theme.toUpperCase()).toString()).commit(); preferences.edit().putString(GENERAL_THEME, Theme.valueOf(theme.toUpperCase()).toString()).commit();
preferences.edit().putString(IMAGE_CACHE_SIZE, imageSize.substring(0, imageSize.length() - 6)).commit(); preferences.edit().putString(IMAGE_CACHE_SIZE, imageSize.substring(0, imageSize.length() - 6)).commit();
@ -404,35 +403,22 @@ public final class PreferenceUtil {
return Long.parseLong(mPreferences.getString(MEDIA_CACHE_SIZE, "400")) * 100000; return Long.parseLong(mPreferences.getString(MEDIA_CACHE_SIZE, "400")) * 100000;
} }
public List<CategoryInfo> getCategories() { public List<Category> getCategories() {
String data = mPreferences.getString(CATEGORIES, null); String data = mPreferences.getString(CATEGORIES, null);
if (data != null) { if (data != null) {
return new Gson().fromJson(data, new TypeToken<List<CategoryInfo>>(){}.getType()); return new Gson().fromJson(data, new TypeToken<List<Category>>(){}.getType());
} }
return getDefaultCategories(); return Arrays.stream(Category.values()).peek(category -> category.select = true).collect(Collectors.toList());
} }
public void setCategories(List<CategoryInfo> categories) { public void setCategories(List<Category> categories) {
Gson gson = new Gson(); Gson gson = new Gson();
Type type = new TypeToken<List<CategoryInfo>>(){}.getType(); Type type = new TypeToken<List<Category>>(){}.getType();
mPreferences.edit().putString(CATEGORIES, gson.toJson(categories, type)).apply(); mPreferences.edit().putString(CATEGORIES, gson.toJson(categories, type)).apply();
} }
public List<CategoryInfo> getDefaultCategories() {
List<CategoryInfo> defaultCategories = new ArrayList<>(5);
defaultCategories.add(new CategoryInfo(CategoryInfo.Category.SONGS, true));
defaultCategories.add(new CategoryInfo(CategoryInfo.Category.ALBUMS, true));
defaultCategories.add(new CategoryInfo(CategoryInfo.Category.ARTISTS, true));
defaultCategories.add(new CategoryInfo(CategoryInfo.Category.GENRES, true));
defaultCategories.add(new CategoryInfo(CategoryInfo.Category.PLAYLISTS, true));
defaultCategories.add(new CategoryInfo(CategoryInfo.Category.FAVORITES, true));
return defaultCategories;
}
public List<Codec> getDirectPlayCodecs() { public List<Codec> getDirectPlayCodecs() {
Set<String> defaultValues = Arrays.stream(Codec.values()).map(Enum::toString).collect(Collectors.toSet()); Set<String> defaultValues = Arrays.stream(Codec.values()).map(Enum::toString).collect(Collectors.toSet());
Set<String> values = mPreferences.getStringSet(DIRECT_PLAY_CODECS, defaultValues); Set<String> values = mPreferences.getStringSet(DIRECT_PLAY_CODECS, defaultValues);