implemented dynamic tabs

This commit is contained in:
h4h13 2019-07-22 20:56:37 +05:30
parent 0c23f313b6
commit 67ea2a40a9
39 changed files with 871 additions and 162 deletions

View file

@ -175,7 +175,7 @@ class ArtistDetailActivity : AbsSlidingMusicPanelActivity(), ArtistDetailContrac
super.onActivityResult(requestCode, resultCode, data)
when (requestCode) {
REQUEST_CODE_SELECT_IMAGE -> if (resultCode == Activity.RESULT_OK) {
CustomArtistImageUtil.getInstance(this).setCustomArtistImage(artist!!, data!!.data!!)
data?.data?.let { CustomArtistImageUtil.getInstance(this).setCustomArtistImage(artist, it) }
}
else -> if (resultCode == Activity.RESULT_OK) {
reload()

View file

@ -24,7 +24,6 @@ import code.name.monkey.retromusic.loaders.AlbumLoader
import code.name.monkey.retromusic.loaders.ArtistLoader
import code.name.monkey.retromusic.loaders.PlaylistSongsLoader
import code.name.monkey.retromusic.service.MusicService
import code.name.monkey.retromusic.util.NavigationUtil
import code.name.monkey.retromusic.util.PreferenceUtil
import io.reactivex.disposables.CompositeDisposable
import java.util.*
@ -62,12 +61,17 @@ class MainActivity : AbsSlidingMusicPanelActivity(), SharedPreferences.OnSharedP
setDrawUnderStatusBar()
super.onCreate(savedInstanceState)
getBottomNavigationView().selectedItemId = PreferenceUtil.getInstance().lastPage
getBottomNavigationView().setOnNavigationItemSelectedListener {
PreferenceUtil.getInstance().lastPage = it.itemId
selectedFragment(it.itemId)
true
}
if (savedInstanceState == null) {
selectedFragment(PreferenceUtil.getInstance().lastPage)
} else {
@ -254,8 +258,10 @@ class MainActivity : AbsSlidingMusicPanelActivity(), SharedPreferences.OnSharedP
key == PreferenceUtil.ALBUM_COVER_STYLE ||
key == PreferenceUtil.HOME_ARTIST_GRID_STYLE ||
key == PreferenceUtil.ALBUM_COVER_TRANSFORM ||
key == PreferenceUtil.TAB_TEXT_MODE)
key == PreferenceUtil.TAB_TEXT_MODE ||
key == PreferenceUtil.LIBRARY_CATEGORIES)
postRecreate()
}
private fun showPromotionalOffer() {
@ -277,6 +283,7 @@ class MainActivity : AbsSlidingMusicPanelActivity(), SharedPreferences.OnSharedP
R.id.action_album,
R.id.action_artist,
R.id.action_playlist,
R.id.action_genre,
R.id.action_song -> setCurrentFragment(LibraryFragment.newInstance(itemId), false)
R.id.action_home -> setCurrentFragment(BannerHomeFragment.newInstance(), false)
R.id.action_folder -> setCurrentFragment(FoldersFragment.newInstance(this), false)
@ -296,8 +303,6 @@ class MainActivity : AbsSlidingMusicPanelActivity(), SharedPreferences.OnSharedP
companion object {
const val APP_INTRO_REQUEST = 2323
const val LIBRARY = 1
const val FOLDERS = 3
const val HOME = 0
private const val TAG = "MainActivity"
private const val APP_USER_INFO_REQUEST = 9003

View file

@ -61,6 +61,8 @@ abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity(), Sliding
chooseFragmentForTheme()
setupSlidingUpPanel()
updateTabs()
}
override fun onResume() {
@ -307,4 +309,16 @@ abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity(), Sliding
}
}
fun updateTabs() {
bottomNavigationView.menu.clear()
val currentTabs = PreferenceUtil.getInstance().libraryCategoryInfos
for (tab in currentTabs) {
if (tab.visible) {
val menu = tab.category;
bottomNavigationView.menu.add(0, menu.id, 0, menu.stringRes)
.setIcon(menu.icon)
}
}
}
}

View file

@ -0,0 +1,127 @@
/*
* Copyright (c) 2019 Hemanth Savarala.
*
* Licensed under the GNU General Public License v3
*
* This is free software: you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by
* the Free Software Foundation either version 3 of the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*/
package code.name.monkey.retromusic.adapter;
import android.annotation.SuppressLint;
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 androidx.annotation.NonNull;
import androidx.recyclerview.widget.ItemTouchHelper;
import androidx.recyclerview.widget.RecyclerView;
import java.util.List;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.model.CategoryInfo;
import code.name.monkey.retromusic.util.SwipeAndDragHelper;
public class CategoryInfoAdapter extends RecyclerView.Adapter<CategoryInfoAdapter.ViewHolder> implements SwipeAndDragHelper.ActionCompletionContract {
private List<CategoryInfo> categoryInfos;
private ItemTouchHelper touchHelper;
public CategoryInfoAdapter(@NonNull 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();
}
@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);
}
@NonNull
public List<CategoryInfo> getCategoryInfos() {
return categoryInfos;
}
public void setCategoryInfos(@NonNull List<CategoryInfo> categoryInfos) {
this.categoryInfos = categoryInfos;
notifyDataSetChanged();
}
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 {
CheckBox checkBox;
TextView title;
View dragView;
ViewHolder(View view) {
super(view);
checkBox = view.findViewById(R.id.checkbox);
title = view.findViewById(R.id.title);
dragView = view.findViewById(R.id.drag_view);
}
}
}

View file

@ -4,14 +4,12 @@ import android.app.Activity
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import java.util.ArrayList
import java.util.Locale
import androidx.recyclerview.widget.RecyclerView
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.model.Genre
import code.name.monkey.retromusic.adapter.base.MediaEntryViewHolder
import code.name.monkey.retromusic.model.Genre
import code.name.monkey.retromusic.util.NavigationUtil
import java.util.*
/**
* @author Hemanth S (h4h13).
@ -40,10 +38,6 @@ class GenreAdapter(private val mActivity: Activity, dataSet: ArrayList<Genre>, p
else
mActivity.getString(R.string.song))
}
if (holder.separator != null) {
holder.separator!!.visibility = View.GONE
}
}
override fun getItemCount(): Int {
@ -56,14 +50,6 @@ class GenreAdapter(private val mActivity: Activity, dataSet: ArrayList<Genre>, p
}
inner class ViewHolder(itemView: View) : MediaEntryViewHolder(itemView) {
init {
if (menu != null) {
menu!!.visibility = View.GONE
}
assert(imageContainer != null)
imageContainer!!.visibility = View.GONE
}
override fun onClick(v: View?) {
super.onClick(v)
val genre = dataSet[adapterPosition]

View file

@ -32,7 +32,6 @@ class HomeAdapter(private val activity: AppCompatActivity, private var homes: Li
val layout = LayoutInflater.from(activity).inflate(R.layout.section_recycler_view, parent, false)
return when (viewType) {
RECENT_ARTISTS, TOP_ARTISTS -> ArtistViewHolder(layout)
GENRES -> GenreViewHolder(layout)
PLAYLISTS -> PlaylistViewHolder(layout)
else -> {
AlbumViewHolder(LayoutInflater.from(activity).inflate(R.layout.metal_section_recycler_view, parent, false))
@ -52,10 +51,6 @@ class HomeAdapter(private val activity: AppCompatActivity, private var homes: Li
val viewHolder = holder as ArtistViewHolder
viewHolder.bindView(home)
}
GENRES -> {
val viewHolder = holder as GenreViewHolder
viewHolder.bindView(home)
}
PLAYLISTS -> {
val viewHolder = holder as PlaylistViewHolder
viewHolder.bindView(home)
@ -108,20 +103,6 @@ class HomeAdapter(private val activity: AppCompatActivity, private var homes: Li
chip.setChipIconResource(home.icon)
}
}
private inner class GenreViewHolder(view: View) : AbsHomeViewItem(view) {
fun bindView(home: Home) {
recyclerView.apply {
val genreAdapter = GenreAdapter(activity, home.arrayList as ArrayList<Genre>, R.layout.item_list)
layoutManager = LinearLayoutManager(context)
adapter = genreAdapter
}
chip.text = activity.getString(home.title)
chip.setChipIconResource(home.icon)
}
}
private inner class PlaylistViewHolder(view: View) : AbsHomeViewItem(view) {
fun bindView(home: Home) {
val songs = PlaylistSongsLoader.getPlaylistSongList(activity, home.arrayList[0] as Playlist).blockingFirst()

View file

@ -3,11 +3,11 @@ package code.name.monkey.retromusic.fragments.mainactivity
import android.os.Bundle
import androidx.recyclerview.widget.GridLayoutManager
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.adapter.album.AlbumAdapter
import code.name.monkey.retromusic.fragments.base.AbsLibraryPagerRecyclerViewCustomGridSizeFragment
import code.name.monkey.retromusic.model.Album
import code.name.monkey.retromusic.mvp.contract.AlbumContract
import code.name.monkey.retromusic.mvp.presenter.AlbumPresenter
import code.name.monkey.retromusic.adapter.album.AlbumAdapter
import code.name.monkey.retromusic.fragments.base.AbsLibraryPagerRecyclerViewCustomGridSizeFragment
import code.name.monkey.retromusic.util.PreferenceUtil
open class AlbumsFragment : AbsLibraryPagerRecyclerViewCustomGridSizeFragment<AlbumAdapter, GridLayoutManager>(), AlbumContract.AlbumView {
@ -95,23 +95,9 @@ open class AlbumsFragment : AbsLibraryPagerRecyclerViewCustomGridSizeFragment<Al
presenter = AlbumPresenter(this)
}
override fun setMenuVisibility(menuVisible: Boolean) {
super.setMenuVisibility(menuVisible)
if (menuVisible) {
libraryFragment.setTitle(
if (PreferenceUtil.getInstance().tabTitles())
R.string.library
else
R.string.albums)
}
}
override fun onResume() {
super.onResume()
libraryFragment.setTitle(
if (PreferenceUtil.getInstance().tabTitles()) R.string.library else R.string.albums)
if (adapter!!.dataSet.isEmpty()) {
presenter.subscribe()
}

View file

@ -3,11 +3,11 @@ package code.name.monkey.retromusic.fragments.mainactivity
import android.os.Bundle
import androidx.recyclerview.widget.GridLayoutManager
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.adapter.artist.ArtistAdapter
import code.name.monkey.retromusic.fragments.base.AbsLibraryPagerRecyclerViewCustomGridSizeFragment
import code.name.monkey.retromusic.model.Artist
import code.name.monkey.retromusic.mvp.contract.ArtistContract
import code.name.monkey.retromusic.mvp.presenter.ArtistPresenter
import code.name.monkey.retromusic.adapter.artist.ArtistAdapter
import code.name.monkey.retromusic.fragments.base.AbsLibraryPagerRecyclerViewCustomGridSizeFragment
import code.name.monkey.retromusic.util.PreferenceUtil
import java.util.*
@ -86,22 +86,8 @@ class ArtistsFragment : AbsLibraryPagerRecyclerViewCustomGridSizeFragment<Artist
presenter.loadArtists()
}
override fun setMenuVisibility(menuVisible: Boolean) {
super.setMenuVisibility(menuVisible)
if (menuVisible) {
libraryFragment.setTitle(
if (PreferenceUtil.getInstance().tabTitles())
R.string.library
else
R.string.artists)
}
}
override fun onResume() {
super.onResume()
libraryFragment.setTitle(
if (PreferenceUtil.getInstance().tabTitles()) R.string.library else R.string.artists)
if (adapter!!.dataSet.isEmpty()) {
presenter.subscribe()
}

View file

@ -0,0 +1,86 @@
/*
* Copyright (c) 2019 Hemanth Savarala.
*
* Licensed under the GNU General Public License v3
*
* This is free software: you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by
* the Free Software Foundation either version 3 of the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*/
package code.name.monkey.retromusic.fragments.mainactivity
import android.os.Bundle
import androidx.recyclerview.widget.LinearLayoutManager
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.adapter.GenreAdapter
import code.name.monkey.retromusic.fragments.base.AbsLibraryPagerRecyclerViewFragment
import code.name.monkey.retromusic.model.Genre
import code.name.monkey.retromusic.mvp.contract.GenreContract
import code.name.monkey.retromusic.mvp.presenter.GenrePresenter
class GenresFragment : AbsLibraryPagerRecyclerViewFragment<GenreAdapter, LinearLayoutManager>(), GenreContract.GenreView {
override fun loading() {
}
override fun showData(list: ArrayList<Genre>) {
adapter?.swapDataSet(list)
}
override fun showEmptyView() {
}
override fun completed() {
}
override fun createLayoutManager(): LinearLayoutManager {
return LinearLayoutManager(activity)
}
override fun createAdapter(): GenreAdapter {
val dataSet = if (adapter == null) ArrayList() else adapter!!.dataSet
return GenreAdapter(libraryFragment.mainActivity, dataSet, R.layout.item_list_no_image)
}
override val emptyMessage: Int
get() = R.string.no_genres
private lateinit var presenter: GenrePresenter
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
presenter = GenrePresenter(this)
}
override fun onResume() {
super.onResume()
if (adapter!!.dataSet.isEmpty()) {
presenter.subscribe()
}
}
override fun onDestroy() {
presenter.unsubscribe()
super.onDestroy()
}
override fun onMediaStoreChanged() {
presenter.loadGenre()
}
companion object {
fun newInstance(): GenresFragment {
return GenresFragment()
}
}
}

View file

@ -1,7 +1,6 @@
package code.name.monkey.retromusic.fragments.mainactivity;
import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.Menu;
@ -26,10 +25,11 @@ import com.google.android.material.card.MaterialCardView;
import org.jetbrains.annotations.NotNull;
import java.util.Objects;
import code.name.monkey.appthemehelper.ThemeStore;
import code.name.monkey.appthemehelper.common.ATHToolbarActivity;
import code.name.monkey.appthemehelper.util.ATHUtil;
import code.name.monkey.appthemehelper.util.ColorUtil;
import code.name.monkey.appthemehelper.util.TintHelper;
import code.name.monkey.appthemehelper.util.ToolbarContentTintHelper;
import code.name.monkey.retromusic.R;
@ -137,6 +137,9 @@ public class LibraryFragment extends AbsMainActivityFragment implements CabHolde
case R.id.action_playlist:
selectedFragment(PlaylistsFragment.Companion.newInstance());
break;
case R.id.action_genre:
selectedFragment(GenresFragment.Companion.newInstance());
break;
}
}
@ -144,13 +147,13 @@ public class LibraryFragment extends AbsMainActivityFragment implements CabHolde
private void setupToolbar() {
int primaryColor = ThemeStore.Companion.primaryColor(getContext());
TintHelper.setTintAuto(contentContainer, primaryColor, true);
appBarLayout.setBackgroundColor(primaryColor);
toolbar.setBackgroundColor(RetroColorUtil.toolbarColor(getMainActivity()));
toolbar.setNavigationIcon(R.drawable.ic_menu_white_24dp);
toolbar.setOnClickListener(v -> {
Pair<View, String> pair = new Pair<>(toolbarContainer, getString(R.string.transition_toolbar));
NavigationUtil.goToSearch(getMainActivity(), pair);
});
appBarLayout.setBackgroundColor(primaryColor);
appBarLayout.addOnOffsetChangedListener((appBarLayout, verticalOffset) ->
getMainActivity().setLightStatusbar(!ATHUtil.INSTANCE.isWindowBackgroundDark(getContext())));
getMainActivity().setSupportActionBar(toolbar);
@ -187,12 +190,12 @@ public class LibraryFragment extends AbsMainActivityFragment implements CabHolde
if (cab != null && cab.isActive()) {
cab.finish();
}
//noinspection ConstantConditions
cab = new MaterialCab(getMainActivity(), R.id.cab_stub)
.setMenu(menuRes)
.setCloseDrawableRes(R.drawable.ic_close_white_24dp)
.setBackgroundColor(
RetroColorUtil.shiftBackgroundColorForLightText(ThemeStore.Companion.primaryColor(getActivity())))
RetroColorUtil.shiftBackgroundColorForLightText(ThemeStore.Companion.primaryColor(Objects.requireNonNull(getActivity()))))
.start(callback);
return cab;
}

View file

@ -5,12 +5,11 @@ import android.view.Menu
import android.view.MenuInflater
import androidx.recyclerview.widget.LinearLayoutManager
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.adapter.playlist.PlaylistAdapter
import code.name.monkey.retromusic.fragments.base.AbsLibraryPagerRecyclerViewFragment
import code.name.monkey.retromusic.model.Playlist
import code.name.monkey.retromusic.mvp.contract.PlaylistContract
import code.name.monkey.retromusic.mvp.presenter.PlaylistPresenter
import code.name.monkey.retromusic.adapter.playlist.PlaylistAdapter
import code.name.monkey.retromusic.fragments.base.AbsLibraryPagerRecyclerViewFragment
import code.name.monkey.retromusic.util.PreferenceUtil
import java.util.*
@ -36,16 +35,8 @@ class PlaylistsFragment : AbsLibraryPagerRecyclerViewFragment<PlaylistAdapter, L
R.layout.item_list, libraryFragment)
}
override fun setMenuVisibility(menuVisible: Boolean) {
super.setMenuVisibility(menuVisible)
if (menuVisible) {
libraryFragment.setTitle(if (PreferenceUtil.getInstance().tabTitles()) R.string.library else R.string.playlists)
}
}
override fun onResume() {
super.onResume()
libraryFragment.setTitle(if (PreferenceUtil.getInstance().tabTitles()) R.string.library else R.string.playlists)
if (adapter!!.dataSet.isEmpty()) {
presenter.subscribe()
}

View file

@ -2,14 +2,13 @@ package code.name.monkey.retromusic.fragments.mainactivity
import android.os.Bundle
import androidx.recyclerview.widget.GridLayoutManager
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.model.Song
import code.name.monkey.retromusic.mvp.contract.SongContract
import code.name.monkey.retromusic.mvp.presenter.SongPresenter
import code.name.monkey.retromusic.adapter.song.ShuffleButtonSongAdapter
import code.name.monkey.retromusic.adapter.song.SongAdapter
import code.name.monkey.retromusic.fragments.base.AbsLibraryPagerRecyclerViewCustomGridSizeFragment
import code.name.monkey.retromusic.model.Song
import code.name.monkey.retromusic.mvp.contract.SongContract
import code.name.monkey.retromusic.mvp.presenter.SongPresenter
import code.name.monkey.retromusic.util.PreferenceUtil
import java.util.*
@ -81,23 +80,11 @@ class SongsFragment : AbsLibraryPagerRecyclerViewCustomGridSizeFragment<SongAdap
override fun onResume() {
super.onResume()
libraryFragment.setTitle(if (PreferenceUtil.getInstance().tabTitles()) R.string.library else R.string.songs)
if (adapter!!.dataSet.isEmpty()) {
presenter.subscribe()
}
}
override fun setMenuVisibility(menuVisible: Boolean) {
super.setMenuVisibility(menuVisible)
if (menuVisible) {
libraryFragment.setTitle(
if (PreferenceUtil.getInstance().tabTitles())
R.string.library
else
R.string.songs)
}
}
override fun onDestroy() {
presenter.unsubscribe()
super.onDestroy()

View file

@ -71,8 +71,9 @@ abstract class AbsSettingsFragment : PreferenceFragmentCompat() {
var dialogFragment: DialogFragment? = null// Dialog creation could not be handled here. Try with the super method.
// The dialog was created (it was one of our custom Preferences), show the dialog for it
when (preference) {
is NowPlayingScreenPreference -> dialogFragment = NowPlayingScreenPreferenceDialog.newInstance(preference.key)
is AlbumCoverStylePreference -> dialogFragment = AlbumCoverStylePreferenceDialog.newInstance(preference.key)
is LibraryPreference -> dialogFragment = LibraryPreferenceDialog.newInstance()
is NowPlayingScreenPreference -> dialogFragment = NowPlayingScreenPreferenceDialog.newInstance( )
is AlbumCoverStylePreference -> dialogFragment = AlbumCoverStylePreferenceDialog.newInstance()
is MaterialListPreference -> {
preference.entries
dialogFragment = MaterialListPreferenceDialog.newInstance(preference)

View file

@ -0,0 +1,75 @@
/*
* Copyright (c) 2019 Hemanth Savarala.
*
* Licensed under the GNU General Public License v3
*
* This is free software: you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by
* the Free Software Foundation either version 3 of the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*/
package code.name.monkey.retromusic.model;
import android.os.Parcel;
import android.os.Parcelable;
import code.name.monkey.retromusic.R;
public class CategoryInfo implements Parcelable {
public static final Creator<CategoryInfo> CREATOR = new Creator<CategoryInfo>() {
public CategoryInfo createFromParcel(Parcel source) {
return new CategoryInfo(source);
}
public CategoryInfo[] newArray(int size) {
return new CategoryInfo[size];
}
};
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 enum Category {
HOME(R.id.action_home, R.string.home, R.drawable.toggle_home),
SONGS(R.id.action_song, R.string.songs, R.drawable.toggle_audiotrack),
ALBUMS(R.id.action_album, R.string.albums, R.drawable.toggle_album),
ARTISTS(R.id.action_artist, R.string.artists, R.drawable.toggle_artist),
PLAYLISTS(R.id.action_playlist, R.string.playlists, R.drawable.toggle_queue_music),
GENRES(R.id.action_genre, R.string.genres, R.drawable.toggle_guitar);
public final int stringRes;
public final int id;
public final int icon;
Category(int id, int stringRes, int icon) {
this.stringRes = stringRes;
this.id = id;
this.icon = icon;
}
}
}

View file

@ -42,7 +42,6 @@ class HomePresenter(private val view: HomeContract.HomeView) : Presenter(), Home
loadTopArtists()
loadATopAlbums()
loadFavorite()
if (PreferenceUtil.getInstance().isGenreShown) loadGenre()
}
override fun subscribe() {
@ -102,14 +101,4 @@ class HomePresenter(private val view: HomeContract.HomeView) : Presenter(), Home
view.showEmptyView()
})
}
private fun loadGenre() {
disposable += repository.allGenres
.subscribe({
if (it.isNotEmpty()) hashSet.add(Home(6, R.string.genres, 0, it, GENRES, R.drawable.ic_guitar_acoustic_white_24dp))
view.showData(ArrayList(hashSet))
}, {
view.showEmptyView()
})
}
}

View file

@ -33,7 +33,6 @@ import code.name.monkey.retromusic.fragments.AlbumCoverStyle
import code.name.monkey.retromusic.util.PreferenceUtil
import code.name.monkey.retromusic.util.ViewUtil
import com.afollestad.materialdialogs.MaterialDialog
import com.afollestad.materialdialogs.bottomsheets.BottomSheet
import com.afollestad.materialdialogs.customview.customView
import com.bumptech.glide.Glide
@ -131,14 +130,8 @@ class AlbumCoverStylePreferenceDialog : PreferenceDialogFragmentCompat(), ViewPa
companion object {
val TAG: String = AlbumCoverStylePreferenceDialog::class.java.simpleName
private const val EXTRA_KEY = "key"
fun newInstance(key: String): AlbumCoverStylePreferenceDialog {
val args = Bundle()
args.putString(EXTRA_KEY, key)
val fragment = AlbumCoverStylePreferenceDialog()
fragment.arguments = args
return fragment
fun newInstance(): AlbumCoverStylePreferenceDialog {
return AlbumCoverStylePreferenceDialog()
}
}
}

View file

@ -23,6 +23,7 @@ import android.util.AttributeSet
import androidx.fragment.app.DialogFragment
import androidx.preference.DialogPreference
import code.name.monkey.appthemehelper.ThemeStore
import code.name.monkey.appthemehelper.common.prefs.supportv7.ATEDialogPreference
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.dialogs.BlacklistFolderChooserDialog
import code.name.monkey.retromusic.providers.BlacklistStore
@ -32,7 +33,7 @@ import com.afollestad.materialdialogs.list.listItems
import java.io.File
import java.util.*
class BlacklistPreference : DialogPreference {
class BlacklistPreference : ATEDialogPreference {
constructor(context: Context) : super(context)
constructor(context: Context, attrs: AttributeSet) : super(context, attrs)

View file

@ -0,0 +1,117 @@
/*
* Copyright (c) 2019 Hemanth Savarala.
*
* Licensed under the GNU General Public License v3
*
* This is free software: you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by
* the Free Software Foundation either version 3 of the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*/
package code.name.monkey.retromusic.preferences
import android.app.Dialog
import android.content.Context
import android.graphics.PorterDuff
import android.os.Bundle
import android.util.AttributeSet
import android.widget.Toast
import androidx.fragment.app.DialogFragment
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import code.name.monkey.appthemehelper.ThemeStore
import code.name.monkey.appthemehelper.common.prefs.supportv7.ATEDialogPreference
import code.name.monkey.retromusic.adapter.CategoryInfoAdapter
import code.name.monkey.retromusic.model.CategoryInfo
import code.name.monkey.retromusic.util.PreferenceUtil
import com.afollestad.materialdialogs.MaterialDialog
import com.afollestad.materialdialogs.bottomsheets.BottomSheet
import com.afollestad.materialdialogs.customview.customView
import java.util.*
class LibraryPreference : ATEDialogPreference {
constructor(context: Context) : super(context) {}
constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {}
constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {}
constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int, defStyleRes: Int) : super(context, attrs, defStyleAttr, defStyleRes) {}
init {
icon?.setColorFilter(ThemeStore.textColorSecondary(context), PorterDuff.Mode.SRC_IN)
}
}
class LibraryPreferenceDialog : DialogFragment() {
lateinit var adapter: CategoryInfoAdapter
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
val view = activity!!.layoutInflater.inflate(code.name.monkey.retromusic.R.layout.preference_dialog_library_categories, null)
val categoryInfos: List<CategoryInfo>
if (savedInstanceState != null) {
categoryInfos = savedInstanceState.getParcelableArrayList(PreferenceUtil.LIBRARY_CATEGORIES)
} else {
categoryInfos = PreferenceUtil.getInstance().getLibraryCategoryInfos()
}
adapter = CategoryInfoAdapter(categoryInfos)
val recyclerView = view.findViewById<RecyclerView>(code.name.monkey.retromusic.R.id.recycler_view)
recyclerView.layoutManager = LinearLayoutManager(activity)
recyclerView.adapter = adapter
adapter.attachToRecyclerView(recyclerView)
return MaterialDialog(context!!, BottomSheet())
.title(code.name.monkey.retromusic.R.string.library_categories)
.customView(view = view)
.positiveButton(android.R.string.ok) {
updateCategories(adapter.categoryInfos)
dismiss()
}
.negativeButton(android.R.string.cancel) {
dismiss()
}
.neutralButton(code.name.monkey.retromusic.R.string.reset_action) {
adapter.categoryInfos = PreferenceUtil.getInstance().defaultLibraryCategoryInfos
}
.noAutoDismiss()
}
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
outState.putParcelableArrayList(PreferenceUtil.LIBRARY_CATEGORIES, ArrayList(adapter.categoryInfos))
}
private fun updateCategories(categories: List<CategoryInfo>) {
if (getSelected(categories) == 0) return
if (getSelected(categories) > 5) {
Toast.makeText(context, "Not more than 5 items", Toast.LENGTH_SHORT).show()
return
}
PreferenceUtil.getInstance().libraryCategoryInfos = categories
}
private fun getSelected(categories: List<CategoryInfo>): Int {
var selected = 0
for (categoryInfo in categories) {
if (categoryInfo.visible)
selected++
}
return selected
}
companion object {
fun newInstance(): LibraryPreferenceDialog {
return LibraryPreferenceDialog()
}
}
}

View file

@ -124,14 +124,10 @@ class NowPlayingScreenPreferenceDialog : PreferenceDialogFragmentCompat(), ViewP
}
companion object {
private const val EXTRA_KEY = "key"
fun newInstance(key: String): NowPlayingScreenPreferenceDialog {
val args = Bundle()
args.putString(EXTRA_KEY, key)
val fragment = NowPlayingScreenPreferenceDialog()
fragment.arguments = args
return fragment
fun newInstance(): NowPlayingScreenPreferenceDialog {
return NowPlayingScreenPreferenceDialog()
}
}
}

View file

@ -58,6 +58,7 @@ class CustomArtistImageUtil private constructor(context: Context) {
@SuppressLint("ApplySharedPref")
override fun doInBackground(vararg params: Void): Void? {
val dir = File(App.context.filesDir, FOLDER_NAME)
println(dir.absolutePath)
if (!dir.exists()) {
if (!dir.mkdirs()) { // create the folder
return null

View file

@ -27,8 +27,14 @@ import androidx.annotation.StyleRes;
import androidx.viewpager.widget.ViewPager;
import com.google.android.material.bottomnavigation.LabelVisibilityMode;
import com.google.gson.Gson;
import com.google.gson.JsonSyntaxException;
import com.google.gson.reflect.TypeToken;
import java.io.File;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import code.name.monkey.retromusic.App;
@ -38,6 +44,7 @@ import code.name.monkey.retromusic.fragments.AlbumCoverStyle;
import code.name.monkey.retromusic.fragments.NowPlayingScreen;
import code.name.monkey.retromusic.fragments.mainactivity.folders.FoldersFragment;
import code.name.monkey.retromusic.helper.SortOrder;
import code.name.monkey.retromusic.model.CategoryInfo;
import code.name.monkey.retromusic.transform.CascadingPageTransformer;
import code.name.monkey.retromusic.transform.DepthTransformation;
import code.name.monkey.retromusic.transform.HingeTransformation;
@ -47,7 +54,7 @@ import code.name.monkey.retromusic.transform.VerticalFlipTransformation;
import code.name.monkey.retromusic.transform.VerticalStackTransformer;
public final class PreferenceUtil {
public static final String LIBRARY_CATEGORIES = "library_categories";
public static final String KEEP_SCREEN_ON = "keep_screen_on";
public static final String TOGGLE_HOME_BANNER = "toggle_home_banner";
public static final String NOW_PLAYING_SCREEN_ID = "now_playing_screen_id";
@ -812,4 +819,44 @@ public final class PreferenceUtil {
public boolean isClickOrSave() {
return mPreferences.getBoolean(NOW_PLAYING_SCREEN, false);
}
@NonNull
public List<CategoryInfo> getLibraryCategoryInfos() {
String data = mPreferences.getString(LIBRARY_CATEGORIES, null);
if (data != null) {
Gson gson = new Gson();
Type collectionType = new TypeToken<List<CategoryInfo>>() {
}.getType();
try {
return gson.fromJson(data, collectionType);
} catch (JsonSyntaxException e) {
e.printStackTrace();
}
}
return getDefaultLibraryCategoryInfos();
}
public void setLibraryCategoryInfos(List<CategoryInfo> categories) {
Gson gson = new Gson();
Type collectionType = new TypeToken<List<CategoryInfo>>() {
}.getType();
final SharedPreferences.Editor editor = mPreferences.edit();
editor.putString(LIBRARY_CATEGORIES, gson.toJson(categories, collectionType));
editor.apply();
}
@NonNull
public List<CategoryInfo> getDefaultLibraryCategoryInfos() {
List<CategoryInfo> defaultCategoryInfos = new ArrayList<>(6);
defaultCategoryInfos.add(new CategoryInfo(CategoryInfo.Category.HOME, true));
defaultCategoryInfos.add(new CategoryInfo(CategoryInfo.Category.SONGS, true));
defaultCategoryInfos.add(new CategoryInfo(CategoryInfo.Category.ALBUMS, true));
defaultCategoryInfos.add(new CategoryInfo(CategoryInfo.Category.ARTISTS, true));
defaultCategoryInfos.add(new CategoryInfo(CategoryInfo.Category.PLAYLISTS, true));
defaultCategoryInfos.add(new CategoryInfo(CategoryInfo.Category.GENRES, false));
return defaultCategoryInfos;
}
}

View file

@ -195,6 +195,13 @@ public class RetroColorUtil {
return backgroundColor;
}
@ColorInt
public static int shiftBackgroundColorForDarkText(@ColorInt int backgroundColor) {
while (!ColorUtil.INSTANCE.isColorLight(backgroundColor)) {
backgroundColor = ColorUtil.INSTANCE.lightenColor(backgroundColor);
}
return backgroundColor;
}
private static class SwatchComparator implements Comparator<Palette.Swatch> {

View file

@ -0,0 +1,70 @@
/*
* Copyright (c) 2019 Hemanth Savarala.
*
* Licensed under the GNU General Public License v3
*
* This is free software: you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by
* the Free Software Foundation either version 3 of the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*/
package code.name.monkey.retromusic.util;
import android.graphics.Canvas;
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.ItemTouchHelper;
public class SwipeAndDragHelper extends ItemTouchHelper.Callback {
private ActionCompletionContract contract;
public SwipeAndDragHelper(ActionCompletionContract contract) {
this.contract = contract;
}
@Override
public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
return makeMovementFlags(dragFlags, 0);
}
@Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
contract.onViewMoved(viewHolder.getAdapterPosition(), target.getAdapterPosition());
return true;
}
@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
}
@Override
public boolean isLongPressDragEnabled() {
return false;
}
@Override
public void onChildDraw(Canvas c,
RecyclerView recyclerView,
RecyclerView.ViewHolder viewHolder,
float dX,
float dY,
int actionState,
boolean isCurrentlyActive) {
if (actionState == ItemTouchHelper.ACTION_STATE_SWIPE) {
float alpha = 1 - (Math.abs(dX) / recyclerView.getWidth());
viewHolder.itemView.setAlpha(alpha);
}
super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
}
public interface ActionCompletionContract {
void onViewMoved(int oldPosition, int newPosition);
}
}