Conflicts:
	app/build.gradle
	app/src/main/java/io/github/muntashirakon/music/activities/MainActivity.kt
	app/src/main/java/io/github/muntashirakon/music/activities/base/AbsSlidingMusicPanelActivity.kt
	app/src/main/java/io/github/muntashirakon/music/adapter/album/AlbumAdapter.kt
	app/src/main/java/io/github/muntashirakon/music/adapter/base/MediaEntryViewHolder.java
	app/src/main/java/io/github/muntashirakon/music/adapter/song/ShuffleButtonSongAdapter.kt
	app/src/main/java/io/github/muntashirakon/music/fragments/CoroutineViewModel.kt
	app/src/main/java/io/github/muntashirakon/music/fragments/DetailListFragment.kt
	app/src/main/java/io/github/muntashirakon/music/fragments/albums/AlbumDetailsFragment.kt
	app/src/main/java/io/github/muntashirakon/music/fragments/albums/AlbumsFragment.kt
	app/src/main/java/io/github/muntashirakon/music/fragments/artists/ArtistDetailsFragment.kt
	app/src/main/java/io/github/muntashirakon/music/fragments/genres/GenreDetailsFragment.kt
	app/src/main/java/io/github/muntashirakon/music/fragments/genres/GenresFragment.kt
	app/src/main/java/io/github/muntashirakon/music/fragments/player/full/FullPlaybackControlsFragment.kt
	app/src/main/java/io/github/muntashirakon/music/fragments/playlists/PlaylistDetailsFragment.kt
	app/src/main/java/io/github/muntashirakon/music/fragments/playlists/PlaylistsFragment.kt
	app/src/main/java/io/github/muntashirakon/music/fragments/search/SearchFragment.kt
	app/src/main/java/io/github/muntashirakon/music/fragments/songs/SongsFragment.kt
	app/src/main/res/layout/item_grid_circle.xml
	app/src/main/res/layout/item_list_quick_actions.xml
	appthemehelper/build.gradle
This commit is contained in:
Muntashir Al-Islam 2021-01-04 16:51:16 +06:00
commit 86f2f788e9
58 changed files with 1156 additions and 496 deletions

View file

@ -50,6 +50,7 @@ import io.github.muntashirakon.music.TOGGLE_SEPARATE_LINE
import io.github.muntashirakon.music.TOGGLE_VOLUME
import io.github.muntashirakon.music.USER_NAME
import io.github.muntashirakon.music.activities.base.AbsSlidingMusicPanelActivity
import io.github.muntashirakon.music.extensions.extra
import io.github.muntashirakon.music.extensions.findNavController
import io.github.muntashirakon.music.helper.MusicPlayerRemote
import io.github.muntashirakon.music.helper.SearchQueryHelper.getSongs
@ -57,6 +58,7 @@ import io.github.muntashirakon.music.model.CategoryInfo
import io.github.muntashirakon.music.model.Song
import io.github.muntashirakon.music.repository.PlaylistSongsLoader
import io.github.muntashirakon.music.service.MusicService
import io.github.muntashirakon.music.util.AppRater
import io.github.muntashirakon.music.util.PreferenceUtil
import kotlinx.coroutines.Dispatchers.IO
import kotlinx.coroutines.launch
@ -66,7 +68,6 @@ class MainActivity : AbsSlidingMusicPanelActivity(), OnSharedPreferenceChangeLis
companion object {
const val TAG = "MainActivity"
const val EXPAND_PANEL = "expand_panel"
const val APP_UPDATE_REQUEST_CODE = 9002
}
override fun createContentView(): View {
@ -83,17 +84,10 @@ class MainActivity : AbsSlidingMusicPanelActivity(), OnSharedPreferenceChangeLis
hideStatusBar()
updateTabs()
// NavigationUI.setupWithNavController(getBottomNavigationView(), findNavController(R.id.fragment_container))
setupNavigationController()
if (!hasPermissions()) {
findNavController(R.id.fragment_container).navigate(R.id.permissionFragment)
}
showPromotionalDialog()
}
private fun showPromotionalDialog() {
}
private fun setupNavigationController() {
@ -115,27 +109,27 @@ class MainActivity : AbsSlidingMusicPanelActivity(), OnSharedPreferenceChangeLis
override fun onResume() {
super.onResume()
PreferenceUtil.registerOnSharedPreferenceChangedListener(this)
if (intent.hasExtra(EXPAND_PANEL) &&
intent.getBooleanExtra(EXPAND_PANEL, false) &&
PreferenceUtil.isExpandPanel
) {
val expand = extra<Boolean>(EXPAND_PANEL).value ?: false
if (expand && PreferenceUtil.isExpandPanel) {
expandPanel()
intent.removeExtra(EXPAND_PANEL)
}
}
override fun onDestroy() {
super.onDestroy()
PreferenceUtil.unregisterOnSharedPreferenceChangedListener(this)
}
override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, key: String?) {
if (key == GENERAL_THEME || key == BLACK_THEME || key == ADAPTIVE_COLOR_APP || key == USER_NAME || key == TOGGLE_FULL_SCREEN || key == TOGGLE_VOLUME || key == ROUND_CORNERS || key == CAROUSEL_EFFECT || key == NOW_PLAYING_SCREEN_ID || key == TOGGLE_GENRE || key == BANNER_IMAGE_PATH || key == PROFILE_IMAGE_PATH || key == CIRCULAR_ALBUM_ART || key == KEEP_SCREEN_ON || key == TOGGLE_SEPARATE_LINE || key == TOGGLE_HOME_BANNER || key == TOGGLE_ADD_CONTROLS || key == ALBUM_COVER_STYLE || key == HOME_ARTIST_GRID_STYLE || key == ALBUM_COVER_TRANSFORM || key == DESATURATED_COLOR || key == EXTRA_SONG_INFO || key == TAB_TEXT_MODE || key == LANGUAGE_NAME || key == LIBRARY_CATEGORIES
) {
if (key == GENERAL_THEME || key == BLACK_THEME || key == ADAPTIVE_COLOR_APP || key == USER_NAME || key == TOGGLE_FULL_SCREEN || key == TOGGLE_VOLUME || key == ROUND_CORNERS || key == CAROUSEL_EFFECT || key == NOW_PLAYING_SCREEN_ID || key == TOGGLE_GENRE || key == BANNER_IMAGE_PATH || key == PROFILE_IMAGE_PATH || key == CIRCULAR_ALBUM_ART || key == KEEP_SCREEN_ON || key == TOGGLE_SEPARATE_LINE || key == TOGGLE_HOME_BANNER || key == TOGGLE_ADD_CONTROLS || key == ALBUM_COVER_STYLE || key == HOME_ARTIST_GRID_STYLE || key == ALBUM_COVER_TRANSFORM || key == DESATURATED_COLOR || key == EXTRA_SONG_INFO || key == TAB_TEXT_MODE || key == LANGUAGE_NAME || key == LIBRARY_CATEGORIES) {
postRecreate()
}
}
override fun onServiceConnected() {
super.onServiceConnected()
if (intent == null) {
return
}
intent ?: return
handlePlaybackIntent(intent)
}

View file

@ -56,7 +56,6 @@ import io.github.muntashirakon.music.helper.MusicPlayerRemote
import io.github.muntashirakon.music.model.CategoryInfo
import io.github.muntashirakon.music.util.PreferenceUtil
import io.github.muntashirakon.music.views.BottomNavigationBarTinted
import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.google.android.material.bottomsheet.BottomSheetBehavior.*
import kotlinx.android.synthetic.main.sliding_music_panel_layout.*
import org.koin.androidx.viewmodel.ext.android.viewModel
@ -97,6 +96,7 @@ abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity() {
onPanelCollapsed()
dimBackground.hide()
}
else -> {
println("Do something")
}
@ -114,11 +114,11 @@ abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity() {
setupBottomSheet()
updateColor()
val themeColor = ATHUtil.resolveColor(this, android.R.attr.windowBackground, Color.GRAY)
val themeColor = resolveColor(android.R.attr.windowBackground, Color.GRAY)
dimBackground.setBackgroundColor(ColorUtil.withAlpha(themeColor, 0.5f))
dimBackground.setOnClickListener {
println("dimBackground")
collapsePanel()
}
}
@ -132,7 +132,7 @@ abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity() {
if (nowPlayingScreen != PreferenceUtil.nowPlayingScreen) {
postRecreate()
}
if (bottomSheetBehavior.state == BottomSheetBehavior.STATE_EXPANDED) {
if (bottomSheetBehavior.state == STATE_EXPANDED) {
setMiniPlayerAlphaProgress(1f)
}
}
@ -154,6 +154,7 @@ abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity() {
fun collapsePanel() {
bottomSheetBehavior.state = STATE_COLLAPSED
setMiniPlayerAlphaProgress(0f)
}
fun expandPanel() {
@ -324,14 +325,14 @@ abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity() {
})
}
fun setBottomBarVisibility(visible: Int) {
bottomNavigationView.visibility = visible
fun setBottomBarVisibility(visible: Boolean) {
bottomNavigationView.isVisible = visible
hideBottomBar(MusicPlayerRemote.playingQueue.isEmpty())
}
private fun hideBottomBar(hide: Boolean) {
val heightOfBar = dip(R.dimen.mini_player_height)
val heightOfBarWithTabs = dip(R.dimen.mini_player_height_expanded)
val heightOfBarWithTabs = heightOfBar * 2
val isVisible = bottomNavigationView.isVisible
if (hide) {
bottomSheetBehavior.isHideable = true
@ -345,10 +346,10 @@ abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity() {
ViewCompat.setElevation(slidingPanel, 10f)
ViewCompat.setElevation(bottomNavigationView, 10f)
if (isVisible) {
bottomSheetBehavior.peekHeight = heightOfBarWithTabs
bottomNavigationView.translateYAnimate(0f)
println("List")
bottomSheetBehavior.peekHeight = heightOfBarWithTabs - 22
} else {
bottomNavigationView.translateYAnimate(150f)
println("Details")
bottomSheetBehavior.peekHeight = heightOfBar
}
}

View file

@ -98,7 +98,8 @@ public class WriteTagsAsyncTask extends DialogAsyncTask<LoadingInfo, Integer, Li
Context context = getContext();
if (context != null) {
if (wroteArtwork) {
MusicUtil.INSTANCE.insertAlbumArt(context, info.getArtworkInfo().getAlbumId(), albumArtFile.getPath());
MusicUtil.INSTANCE.
insertAlbumArt(context, info.getArtworkInfo().getAlbumId(), albumArtFile.getPath());
} else if (deletedArtwork) {
MusicUtil.INSTANCE.deleteAlbumArt(context, info.getArtworkInfo().getAlbumId());
}

View file

@ -239,15 +239,17 @@ class HomeAdapter(
val clickableArea: ViewGroup = itemView.findViewById(R.id.clickable_area)
}
fun artistsAdapter(artists: List<Artist>) =
private fun artistsAdapter(artists: List<Artist>) =
ArtistAdapter(activity, artists, PreferenceUtil.homeArtistGridStyle, null, this)
fun albumAdapter(albums: List<Album>) =
private fun albumAdapter(albums: List<Album>) =
AlbumAdapter(activity, albums, PreferenceUtil.homeAlbumGridStyle, null, this)
fun gridLayoutManager() = GridLayoutManager(activity, 1, GridLayoutManager.HORIZONTAL, false)
private fun gridLayoutManager() =
GridLayoutManager(activity, 1, GridLayoutManager.HORIZONTAL, false)
fun linearLayoutManager() = LinearLayoutManager(activity, LinearLayoutManager.HORIZONTAL, false)
private fun linearLayoutManager() =
LinearLayoutManager(activity, LinearLayoutManager.HORIZONTAL, false)
override fun onArtist(artistId: Long, view: View) {
activity.findNavController(R.id.fragment_container).navigate(

View file

@ -42,10 +42,10 @@ class SongFileAdapter(
private val activity: AppCompatActivity,
private var dataSet: List<File>,
private val itemLayoutRes: Int,
private val ICallbacks: ICallbacks?,
ICabHolder: ICabHolder?
private val iCallbacks: ICallbacks?,
iCabHolder: ICabHolder?
) : AbsMultiSelectAdapter<SongFileAdapter.ViewHolder, File>(
activity, ICabHolder, R.menu.menu_media_selection
activity, iCabHolder, R.menu.menu_media_selection
), PopupTextProvider {
init {
@ -135,8 +135,8 @@ class SongFileAdapter(
}
override fun onMultipleItemAction(menuItem: MenuItem, selection: List<File>) {
if (ICallbacks == null) return
ICallbacks.onMultipleItemAction(menuItem, selection as ArrayList<File>)
if (iCallbacks == null) return
iCallbacks.onMultipleItemAction(menuItem, selection as ArrayList<File>)
}
override fun getPopupText(position: Int): String {
@ -150,11 +150,11 @@ class SongFileAdapter(
inner class ViewHolder(itemView: View) : MediaEntryViewHolder(itemView) {
init {
if (menu != null && ICallbacks != null) {
if (menu != null && iCallbacks != null) {
menu?.setOnClickListener { v ->
val position = layoutPosition
if (isPositionInRange(position)) {
ICallbacks.onFileMenuClicked(dataSet[position], v)
iCallbacks.onFileMenuClicked(dataSet[position], v)
}
}
}
@ -169,7 +169,7 @@ class SongFileAdapter(
if (isInQuickSelectMode) {
toggleChecked(position)
} else {
ICallbacks?.onFileSelected(dataSet[position])
iCallbacks?.onFileSelected(dataSet[position])
}
}
}

View file

@ -15,20 +15,17 @@
package io.github.muntashirakon.music.adapter.album
import android.content.res.ColorStateList
import android.content.res.Resources
import android.view.LayoutInflater
import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
import androidx.core.view.ViewCompat
import androidx.fragment.app.FragmentActivity
import com.bumptech.glide.Glide
import io.github.muntashirakon.music.R
import io.github.muntashirakon.music.adapter.base.AbsMultiSelectAdapter
import io.github.muntashirakon.music.adapter.base.MediaEntryViewHolder
import io.github.muntashirakon.music.glide.AlbumGlideRequest
import io.github.muntashirakon.music.glide.RetroMusicColoredTarget
import io.github.muntashirakon.music.helper.MusicPlayerRemote
import io.github.muntashirakon.music.helper.SortOrder
import io.github.muntashirakon.music.helper.menu.SongsMenuHelper
import io.github.muntashirakon.music.interfaces.IAlbumClickListener
@ -38,17 +35,18 @@ import io.github.muntashirakon.music.model.Song
import io.github.muntashirakon.music.util.MusicUtil
import io.github.muntashirakon.music.util.PreferenceUtil
import io.github.muntashirakon.music.util.color.MediaNotificationProcessor
import com.bumptech.glide.Glide
import me.zhanghai.android.fastscroll.PopupTextProvider
open class AlbumAdapter(
protected val activity: FragmentActivity,
val activity: FragmentActivity,
var dataSet: List<Album>,
protected var itemLayoutRes: Int,
ICabHolder: ICabHolder?,
private val albumClickListener: IAlbumClickListener?
var itemLayoutRes: Int,
iCabHolder: ICabHolder?,
val listener: IAlbumClickListener?
) : AbsMultiSelectAdapter<AlbumAdapter.ViewHolder, Album>(
activity,
ICabHolder,
iCabHolder,
R.menu.menu_media_selection
), PopupTextProvider {
@ -62,12 +60,7 @@ open class AlbumAdapter(
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view =
try {
LayoutInflater.from(activity).inflate(itemLayoutRes, parent, false)
} catch (e: Resources.NotFoundException) {
LayoutInflater.from(activity).inflate(R.layout.item_grid, parent, false)
}
val view = LayoutInflater.from(activity).inflate(itemLayoutRes, parent, false)
return createViewHolder(view, viewType)
}
@ -99,7 +92,7 @@ open class AlbumAdapter(
holder.paletteColorContainer?.setBackgroundColor(color.backgroundColor)
}
holder.mask?.backgroundTintList = ColorStateList.valueOf(color.primaryTextColor)
}
holder.imageContainerCard?.setCardBackgroundColor(color.backgroundColor) }
protected open fun loadAlbumCover(album: Album, holder: ViewHolder) {
if (holder.image == null) {
@ -177,8 +170,11 @@ open class AlbumAdapter(
if (isInQuickSelectMode) {
toggleChecked(layoutPosition)
} else {
ViewCompat.setTransitionName(itemView, "album")
albumClickListener?.onAlbumClick(dataSet[layoutPosition].id, itemView)
image?.let {
ViewCompat.setTransitionName(it, "album")
listener?.onAlbumClick(dataSet[layoutPosition].id, it)
}
}
}

View file

@ -85,7 +85,7 @@ class ArtistAdapter(
loadArtistImage(artist, holder)
}
fun setColors(processor: MediaNotificationProcessor, holder: ViewHolder) {
private fun setColors(processor: MediaNotificationProcessor, holder: ViewHolder) {
holder.mask?.backgroundTintList = ColorStateList.valueOf(processor.primaryTextColor)
if (holder.paletteColorContainer != null) {
holder.paletteColorContainer?.setBackgroundColor(processor.backgroundColor)
@ -155,8 +155,8 @@ class ArtistAdapter(
toggleChecked(layoutPosition)
} else {
image?.let {
ViewCompat.setTransitionName(itemView, "album")
IArtistClickListener.onArtist(dataSet[layoutPosition].id, itemView)
ViewCompat.setTransitionName(it, "artist")
IArtistClickListener.onArtist(dataSet[layoutPosition].id, it)
}
}
}

View file

@ -16,103 +16,122 @@ package io.github.muntashirakon.music.adapter.base;
import android.graphics.Color;
import android.view.View;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.AppCompatImageView;
import androidx.recyclerview.widget.RecyclerView;
import io.github.muntashirakon.music.R;
import com.google.android.material.card.MaterialCardView;
import com.h6ah4i.android.widget.advrecyclerview.utils.AbstractDraggableSwipeableItemViewHolder;
public class MediaEntryViewHolder extends AbstractDraggableSwipeableItemViewHolder
implements View.OnLongClickListener, View.OnClickListener {
implements View.OnLongClickListener, View.OnClickListener {
@Nullable public View dragView;
@Nullable
public View dragView;
@Nullable public View dummyContainer;
@Nullable
public View dummyContainer;
@Nullable public ImageView image;
@Nullable
public ImageView image;
@Nullable public ImageView artistImage;
@Nullable
public ImageView artistImage;
@Nullable public ImageView playerImage;
@Nullable
public ImageView playerImage;
@Nullable public MaterialCardView imageContainerCard;
@Nullable
public MaterialCardView imageContainerCard;
@Nullable public TextView imageText;
@Nullable
public TextView imageText;
@Nullable public MaterialCardView imageTextContainer;
@Nullable
public MaterialCardView imageTextContainer;
@Nullable public View mask;
@Nullable
public View mask;
@Nullable public AppCompatImageView menu;
@Nullable
public AppCompatImageView menu;
@Nullable public View paletteColorContainer;
@Nullable
public View paletteColorContainer;
@Nullable public RecyclerView recyclerView;
@Nullable
public RecyclerView recyclerView;
@Nullable public TextView text;
@Nullable
public TextView text;
@Nullable public TextView text2;
@Nullable
public TextView text2;
@Nullable public TextView time;
@Nullable
public TextView time;
@Nullable public TextView title;
@Nullable
public TextView title;
public MediaEntryViewHolder(@NonNull View itemView) {
super(itemView);
title = itemView.findViewById(R.id.title);
text = itemView.findViewById(R.id.text);
text2 = itemView.findViewById(R.id.text2);
public MediaEntryViewHolder(@NonNull View itemView) {
super(itemView);
title = itemView.findViewById(R.id.title);
text = itemView.findViewById(R.id.text);
text2 = itemView.findViewById(R.id.text2);
image = itemView.findViewById(R.id.image);
artistImage = itemView.findViewById(R.id.artistImage);
playerImage = itemView.findViewById(R.id.player_image);
time = itemView.findViewById(R.id.time);
image = itemView.findViewById(R.id.image);
artistImage = itemView.findViewById(R.id.artistImage);
playerImage = itemView.findViewById(R.id.player_image);
time = itemView.findViewById(R.id.time);
imageText = itemView.findViewById(R.id.imageText);
imageTextContainer = itemView.findViewById(R.id.imageTextContainer);
imageContainerCard = itemView.findViewById(R.id.imageContainerCard);
imageText = itemView.findViewById(R.id.imageText);
imageTextContainer = itemView.findViewById(R.id.imageTextContainer);
imageContainerCard = itemView.findViewById(R.id.imageContainerCard);
menu = itemView.findViewById(R.id.menu);
dragView = itemView.findViewById(R.id.drag_view);
paletteColorContainer = itemView.findViewById(R.id.paletteColorContainer);
recyclerView = itemView.findViewById(R.id.recycler_view);
mask = itemView.findViewById(R.id.mask);
dummyContainer = itemView.findViewById(R.id.dummy_view);
menu = itemView.findViewById(R.id.menu);
dragView = itemView.findViewById(R.id.drag_view);
paletteColorContainer = itemView.findViewById(R.id.paletteColorContainer);
recyclerView = itemView.findViewById(R.id.recycler_view);
mask = itemView.findViewById(R.id.mask);
dummyContainer = itemView.findViewById(R.id.dummy_view);
if (imageContainerCard != null) {
imageContainerCard.setCardBackgroundColor(Color.TRANSPARENT);
if (imageContainerCard != null) {
imageContainerCard.setCardBackgroundColor(Color.TRANSPARENT);
}
itemView.setOnClickListener(this);
itemView.setOnLongClickListener(this);
}
itemView.setOnClickListener(this);
itemView.setOnLongClickListener(this);
}
@Nullable
@Override
public View getSwipeableContainerView() {
return null;
}
@Nullable
@Override
public View getSwipeableContainerView() {
return null;
}
@Override
public void onClick(View v) {}
@Override
public void onClick(View v) {
}
@Override
public boolean onLongClick(View v) {
return false;
}
@Override
public boolean onLongClick(View v) {
return false;
}
public void setImageTransitionName(@NonNull String transitionName) {
itemView.setTransitionName(transitionName);
public void setImageTransitionName(@NonNull String transitionName) {
itemView.setTransitionName(transitionName);
/* if (imageContainerCard != null) {
imageContainerCard.setTransitionName(transitionName);
}
if (image != null) {
image.setTransitionName(transitionName);
}*/
}
}
}

View file

@ -25,13 +25,13 @@ import io.github.muntashirakon.music.dialogs.RemoveSongFromPlaylistDialog
import io.github.muntashirakon.music.interfaces.ICabHolder
import io.github.muntashirakon.music.model.Song
open class PlaylistSongAdapter(
class PlaylistSongAdapter(
private val playlist: PlaylistEntity,
activity: FragmentActivity,
dataSet: MutableList<Song>,
itemLayoutRes: Int,
ICabHolder: ICabHolder?
) : SongAdapter(activity, dataSet, itemLayoutRes, ICabHolder) {
iCabHolder: ICabHolder?
) : SongAdapter(activity, dataSet, itemLayoutRes, iCabHolder) {
init {
this.setMultiSelectMenuRes(R.menu.menu_cannot_delete_single_songs_playlist_songs_selection)

View file

@ -15,15 +15,18 @@
package io.github.muntashirakon.music.adapter.song
import android.view.View
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.FragmentActivity
import code.name.monkey.appthemehelper.ThemeStore
import io.github.muntashirakon.music.R
import io.github.muntashirakon.music.extensions.applyColor
import io.github.muntashirakon.music.extensions.applyOutlineColor
import io.github.muntashirakon.music.helper.MusicPlayerRemote
import io.github.muntashirakon.music.interfaces.ICabHolder
import io.github.muntashirakon.music.model.Song
import com.google.android.material.button.MaterialButton
class ShuffleButtonSongAdapter(
activity: AppCompatActivity,
activity: FragmentActivity,
dataSet: MutableList<Song>,
itemLayoutRes: Int,
ICabHolder: ICabHolder?
@ -35,16 +38,19 @@ class ShuffleButtonSongAdapter(
override fun onBindViewHolder(holder: SongAdapter.ViewHolder, position: Int) {
if (holder.itemViewType == OFFSET_ITEM) {
val color = ThemeStore.accentColor(activity)
val viewHolder = holder as ViewHolder
viewHolder.playAction?.let {
it.setOnClickListener {
MusicPlayerRemote.openQueue(dataSet, 0, true)
}
it.applyOutlineColor(color)
}
viewHolder.shuffleAction?.let {
it.setOnClickListener {
MusicPlayerRemote.openAndShuffleQueue(dataSet, true)
}
it.applyColor(color)
}
} else {
super.onBindViewHolder(holder, position - 1)

View file

@ -19,7 +19,7 @@ import androidx.room.RoomDatabase
@Database(
entities = [PlaylistEntity::class, SongEntity::class, HistoryEntity::class, PlayCountEntity::class, BlackListStoreEntity::class, LyricsEntity::class],
version = 22,
version = 23,
exportSchema = false
)
abstract class RetroDatabase : RoomDatabase() {

View file

@ -16,6 +16,7 @@ package io.github.muntashirakon.music.dialogs
import android.app.Dialog
import android.os.Bundle
import androidx.core.os.bundleOf
import androidx.core.text.HtmlCompat
import androidx.fragment.app.DialogFragment
import io.github.muntashirakon.music.EXTRA_SONG
@ -40,11 +41,11 @@ class DeleteSongsDialog : DialogFragment() {
}
fun create(songs: List<Song>): DeleteSongsDialog {
val dialog = DeleteSongsDialog()
val args = Bundle()
args.putParcelableArrayList(EXTRA_SONG, ArrayList(songs))
dialog.arguments = args
return dialog
return DeleteSongsDialog().apply {
arguments = bundleOf(
EXTRA_SONG to ArrayList(songs)
)
}
}
}

View file

@ -164,7 +164,6 @@ class SleepTimerDialog : DialogFragment() {
) {
override fun onTick(millisUntilFinished: Long) {
println("onTick: $millisUntilFinished")
seekBar.progress = millisUntilFinished.toInt()
}

View file

@ -23,6 +23,7 @@ import android.util.Log
import android.view.LayoutInflater
import android.widget.TextView
import androidx.annotation.NonNull
import androidx.core.os.bundleOf
import androidx.core.text.HtmlCompat
import androidx.fragment.app.DialogFragment
import io.github.muntashirakon.music.EXTRA_SONG
@ -155,11 +156,11 @@ class SongDetailDialog : DialogFragment() {
val TAG: String = SongDetailDialog::class.java.simpleName
fun create(song: Song): SongDetailDialog {
val dialog = SongDetailDialog()
val args = Bundle()
args.putParcelable(EXTRA_SONG, song)
dialog.arguments = args
return dialog
return SongDetailDialog().apply {
arguments = bundleOf(
EXTRA_SONG to song
)
}
}
private fun makeTextWithTitle(context: Context, titleResId: Int, text: String?): Spanned {

View file

@ -17,6 +17,7 @@ package io.github.muntashirakon.music.dialogs
import android.app.Dialog
import android.content.Intent
import android.os.Bundle
import androidx.core.os.bundleOf
import androidx.fragment.app.DialogFragment
import io.github.muntashirakon.music.EXTRA_SONG
import io.github.muntashirakon.music.R
@ -93,11 +94,11 @@ class SongShareDialog : DialogFragment() {
companion object {
fun create(song: Song): SongShareDialog {
val dialog = SongShareDialog()
val args = Bundle()
args.putParcelable(EXTRA_SONG, song)
dialog.arguments = args
return dialog
return SongShareDialog().apply {
arguments = bundleOf(
EXTRA_SONG to song
)
}
}
}
}

View file

@ -38,7 +38,7 @@ import code.name.monkey.appthemehelper.util.MaterialValueHelper
import com.google.android.material.button.MaterialButton
import com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
import com.google.android.material.floatingactionbutton.FloatingActionButton
import com.google.android.material.progressindicator.ProgressIndicator
import com.google.android.material.progressindicator.CircularProgressIndicator
import com.google.android.material.textfield.TextInputEditText
import com.google.android.material.textfield.TextInputLayout
import io.github.muntashirakon.music.App
@ -95,13 +95,7 @@ fun SeekBar.addAccentColor() {
thumbTintList = colorState
}
fun Button.accentTextColor() {
setTextColor(ThemeStore.accentColor(App.getContext()))
}
fun MaterialButton.accentTextColor() {
setTextColor(ThemeStore.accentColor(App.getContext()))
}
fun Button.accentTextColor() = setTextColor(ThemeStore.accentColor(App.getContext()))
fun MaterialButton.accentBackgroundColor() {
backgroundTintList = ColorStateList.valueOf(ThemeStore.accentColor(App.getContext()))
@ -154,9 +148,7 @@ fun MaterialButton.applyColor(color: Int) {
iconTint = textColorColorStateList
}
fun MaterialButton.accentColor(){
this.applyColor(ThemeStore.accentColor(context))
}
fun MaterialButton.accentColor() = applyColor(ThemeStore.accentColor(context))
fun MaterialButton.applyOutlineColor(color: Int) {
val textColorColorStateList = ColorStateList.valueOf(color)
@ -172,23 +164,18 @@ fun TextInputLayout.accentColor() {
isHintAnimationEnabled = true
}
fun ProgressIndicator.accentColor() {
val accentColor = ThemeStore.accentColor(context)
indicatorColors = intArrayOf(accentColor)
trackColor = ColorUtil.withAlpha(accentColor, 0.2f)
}
fun ProgressIndicator.applyColor(color: Int) {
indicatorColors = intArrayOf(color)
fun CircularProgressIndicator.accentColor() {
val color = ThemeStore.accentColor(context)
setIndicatorColor(color)
trackColor = ColorUtil.withAlpha(color, 0.2f)
}
fun TextInputEditText.accentColor() {
fun CircularProgressIndicator.applyColor(color: Int) {
setIndicatorColor(color)
trackColor = ColorUtil.withAlpha(color, 0.2f)
}
fun AppCompatImageView.accentColor(): Int {
return ThemeStore.accentColor(context)
}
fun AppCompatImageView.accentColor(): Int = ThemeStore.accentColor(context)
@CheckResult
fun Drawable.tint(@ColorInt color: Int): Drawable {
@ -198,9 +185,8 @@ fun Drawable.tint(@ColorInt color: Int): Drawable {
}
@CheckResult
fun Drawable.tint(context: Context, @ColorRes color: Int): Drawable {
return tint(context.getColorCompat(color))
}
fun Drawable.tint(context: Context, @ColorRes color: Int): Drawable =
tint(context.getColorCompat(color))
@ColorInt
fun Context.getColorCompat(@ColorRes colorRes: Int): Int {

View file

@ -48,15 +48,4 @@ fun Drawable.getBitmapDrawable(): Bitmap {
val canvas = Canvas(bmp)
draw(canvas)
return bmp
}
fun getAdaptiveIconDrawable(context: Context): Drawable {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
AdaptiveIconDrawable(
ContextCompat.getDrawable(context, R.drawable.ic_launcher_background),
ContextCompat.getDrawable(context, R.drawable.ic_launcher_background)
)
} else {
ContextCompat.getDrawable(context, R.drawable.color_circle_gradient)!!
}
}
}

View file

@ -27,6 +27,8 @@ import androidx.core.animation.doOnStart
import code.name.monkey.appthemehelper.ThemeStore
import code.name.monkey.appthemehelper.util.TintHelper
import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.google.android.material.imageview.ShapeableImageView
import com.google.android.material.shape.ShapeAppearanceModel
@Suppress("UNCHECKED_CAST")
fun <T : View> ViewGroup.inflate(@LayoutRes layout: Int): T {
@ -112,4 +114,11 @@ fun View.focusAndShowKeyboard() {
}
})
}
}
}
fun ShapeableImageView.setCircleShape(boolean: Boolean) {
addOnLayoutChangeListener { _, _, _, _, _, _, _, _, _ ->
val radius = width / 2f
shapeAppearanceModel = ShapeAppearanceModel().withCornerSize(radius)
}
}

View file

@ -1,37 +0,0 @@
/*
* Copyright (c) 2020 Hemanth Savarla.
*
* 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 io.github.muntashirakon.music.fragments
import androidx.lifecycle.ViewModel
import kotlin.coroutines.CoroutineContext
import kotlinx.coroutines.*
open class CoroutineViewModel(
private val mainDispatcher: CoroutineDispatcher
) : ViewModel() {
private val job = Job()
protected val scope = CoroutineScope(job + mainDispatcher)
protected fun launch(
context: CoroutineContext = mainDispatcher,
start: CoroutineStart = CoroutineStart.DEFAULT,
block: suspend CoroutineScope.() -> Unit
) = scope.launch(context, start, block)
override fun onCleared() {
super.onCleared()
job.cancel()
}
}

View file

@ -26,15 +26,16 @@ import androidx.recyclerview.widget.RecyclerView.AdapterDataObserver
import io.github.muntashirakon.music.*
import io.github.muntashirakon.music.adapter.album.AlbumAdapter
import io.github.muntashirakon.music.adapter.artist.ArtistAdapter
import io.github.muntashirakon.music.adapter.song.ShuffleButtonSongAdapter
import io.github.muntashirakon.music.adapter.song.SongAdapter
import io.github.muntashirakon.music.db.toSong
import io.github.muntashirakon.music.extensions.dipToPix
import io.github.muntashirakon.music.extensions.hide
import io.github.muntashirakon.music.fragments.base.AbsMainActivityFragment
import io.github.muntashirakon.music.interfaces.IAlbumClickListener
import io.github.muntashirakon.music.interfaces.IArtistClickListener
import io.github.muntashirakon.music.model.Album
import io.github.muntashirakon.music.model.Artist
import io.github.muntashirakon.music.state.NowPlayingPanelState
import io.github.muntashirakon.music.util.RetroUtil
import kotlinx.android.synthetic.main.fragment_playlist_detail.*
@ -44,22 +45,14 @@ class DetailListFragment : AbsMainActivityFragment(R.layout.fragment_playlist_de
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
mainActivity.setBottomBarVisibility(View.GONE)
mainActivity.setBottomBarVisibility(false)
mainActivity.setSupportActionBar(toolbar)
progressIndicator.hide()
when (args.type) {
TOP_ARTISTS -> {
loadArtists(R.string.top_artists, TOP_ARTISTS)
}
RECENT_ARTISTS -> {
loadArtists(R.string.recent_artists, RECENT_ARTISTS)
}
TOP_ALBUMS -> {
loadAlbums(R.string.top_albums, TOP_ALBUMS)
}
RECENT_ALBUMS -> {
loadAlbums(R.string.recent_albums, RECENT_ALBUMS)
}
TOP_ARTISTS -> loadArtists(R.string.top_artists, TOP_ARTISTS)
RECENT_ARTISTS -> loadArtists(R.string.recent_artists, RECENT_ARTISTS)
TOP_ALBUMS -> loadAlbums(R.string.top_albums, TOP_ALBUMS)
RECENT_ALBUMS -> loadAlbums(R.string.recent_albums, RECENT_ALBUMS)
FAVOURITES -> loadFavorite()
HISTORY_PLAYLIST -> loadHistory()
LAST_ADDED_PLAYLIST -> lastAddedSongs()
@ -77,7 +70,7 @@ class DetailListFragment : AbsMainActivityFragment(R.layout.fragment_playlist_de
private fun lastAddedSongs() {
toolbar.setTitle(R.string.last_added)
val songAdapter = SongAdapter(
val songAdapter = ShuffleButtonSongAdapter(
requireActivity(),
mutableListOf(),
R.layout.item_list, null
@ -93,7 +86,7 @@ class DetailListFragment : AbsMainActivityFragment(R.layout.fragment_playlist_de
private fun topPlayed() {
toolbar.setTitle(R.string.my_top_tracks)
val songAdapter = SongAdapter(
val songAdapter = ShuffleButtonSongAdapter(
requireActivity(),
mutableListOf(),
R.layout.item_list, null
@ -110,7 +103,7 @@ class DetailListFragment : AbsMainActivityFragment(R.layout.fragment_playlist_de
private fun loadHistory() {
toolbar.setTitle(R.string.history)
val songAdapter = SongAdapter(
val songAdapter = ShuffleButtonSongAdapter(
requireActivity(),
mutableListOf(),
R.layout.item_list, null

View file

@ -122,10 +122,6 @@ class VolumeFragment : Fragment(), SeekBar.OnSeekBarChangeListener, OnAudioVolum
volumeSeekBar.applyColor(color)
}
fun removeThumb() {
volumeSeekBar.thumb = null
}
private fun setPauseWhenZeroVolume(pauseWhenZeroVolume: Boolean) {
if (PreferenceUtil.isPauseOnZeroVolume)
if (MusicPlayerRemote.isPlaying && pauseWhenZeroVolume)

View file

@ -16,6 +16,7 @@ package io.github.muntashirakon.music.fragments.albums
import android.app.ActivityOptions
import android.content.Intent
import android.graphics.Color
import android.os.Bundle
import android.view.*
import androidx.appcompat.app.AppCompatActivity
@ -31,7 +32,6 @@ import androidx.recyclerview.widget.DefaultItemAnimator
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager
import code.name.monkey.appthemehelper.common.ATHToolbarActivity.getToolbarBackgroundColor
import code.name.monkey.appthemehelper.util.ATHUtil
import code.name.monkey.appthemehelper.util.ToolbarContentTintHelper
import io.github.muntashirakon.music.EXTRA_ALBUM_ID
import io.github.muntashirakon.music.EXTRA_ARTIST_ID
@ -42,17 +42,17 @@ import io.github.muntashirakon.music.adapter.album.HorizontalAlbumAdapter
import io.github.muntashirakon.music.adapter.song.SimpleSongAdapter
import io.github.muntashirakon.music.dialogs.AddToPlaylistDialog
import io.github.muntashirakon.music.dialogs.DeleteSongsDialog
import io.github.muntashirakon.music.extensions.applyColor
import io.github.muntashirakon.music.extensions.applyOutlineColor
import io.github.muntashirakon.music.extensions.findActivityNavController
import io.github.muntashirakon.music.extensions.show
import io.github.muntashirakon.music.extensions.*
import io.github.muntashirakon.music.fragments.base.AbsMainActivityFragment
import io.github.muntashirakon.music.glide.AlbumGlideRequest
import io.github.muntashirakon.music.glide.ArtistGlideRequest
import io.github.muntashirakon.music.glide.RetroMusicColoredTarget
import io.github.muntashirakon.music.glide.SingleColorTarget
import io.github.muntashirakon.music.helper.MusicPlayerRemote
import io.github.muntashirakon.music.helper.SortOrder
import io.github.muntashirakon.music.helper.SortOrder.AlbumSongSortOrder.Companion.SONG_A_Z
import io.github.muntashirakon.music.helper.SortOrder.AlbumSongSortOrder.Companion.SONG_DURATION
import io.github.muntashirakon.music.helper.SortOrder.AlbumSongSortOrder.Companion.SONG_TRACK_LIST
import io.github.muntashirakon.music.helper.SortOrder.AlbumSongSortOrder.Companion.SONG_Z_A
import io.github.muntashirakon.music.interfaces.IAlbumClickListener
import io.github.muntashirakon.music.model.Album
import io.github.muntashirakon.music.model.Artist
@ -64,7 +64,9 @@ import io.github.muntashirakon.music.util.PreferenceUtil
import io.github.muntashirakon.music.util.RetroUtil
import io.github.muntashirakon.music.util.color.MediaNotificationProcessor
import com.bumptech.glide.Glide
import com.google.android.material.transition.MaterialArcMotion
import com.google.android.material.transition.MaterialContainerTransform
import com.google.android.material.transition.MaterialElevationScale
import kotlinx.android.synthetic.main.fragment_album_content.*
import kotlinx.android.synthetic.main.fragment_album_details.*
import kotlinx.coroutines.Dispatchers
@ -89,25 +91,26 @@ class AlbumDetailsFragment : AbsMainActivityFragment(R.layout.fragment_album_det
private val savedSortOrder: String
get() = PreferenceUtil.albumDetailSongSortOrder
private fun setUpTransitions() {
val transform = MaterialContainerTransform()
transform.setAllContainerColors(ATHUtil.resolveColor(requireContext(), R.attr.colorSurface))
sharedElementEnterTransition = transform
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setUpTransitions()
sharedElementEnterTransition = MaterialContainerTransform().apply {
drawingViewId = R.id.fragment_container
duration = 300L
scrimColor = Color.TRANSPARENT
setAllContainerColors(requireContext().resolveColor(R.attr.colorSurface))
setPathMotion(MaterialArcMotion())
}
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
setHasOptionsMenu(true)
mainActivity.setBottomBarVisibility(View.GONE)
mainActivity.setBottomBarVisibility(false)
mainActivity.addMusicServiceEventListener(detailsViewModel)
mainActivity.setSupportActionBar(toolbar)
toolbar.title = " "
ViewCompat.setTransitionName(container, "album")
ViewCompat.setTransitionName(albumCoverContainer, "album")
postponeEnterTransition()
detailsViewModel.getAlbum().observe(viewLifecycleOwner, Observer {
startPostponedEnterTransition()
@ -117,6 +120,12 @@ class AlbumDetailsFragment : AbsMainActivityFragment(R.layout.fragment_album_det
setupRecyclerView()
artistImage.setOnClickListener { artistView ->
ViewCompat.setTransitionName(artistView, "artist")
exitTransition = MaterialElevationScale(false).apply {
duration = 300L
}
reenterTransition = MaterialElevationScale(true).apply {
duration = 300L
}
findActivityNavController(R.id.fragment_container)
.navigate(
R.id.artistDetailsFragment,
@ -125,8 +134,9 @@ class AlbumDetailsFragment : AbsMainActivityFragment(R.layout.fragment_album_det
FragmentNavigatorExtras(artistView to "artist")
)
}
playAction.setOnClickListener { MusicPlayerRemote.openQueue(album.songs, 0, true) }
playAction.setOnClickListener {
MusicPlayerRemote.openQueue(album.songs, 0, true)
}
shuffleAction.setOnClickListener {
MusicPlayerRemote.openAndShuffleQueue(
album.songs,
@ -141,9 +151,6 @@ class AlbumDetailsFragment : AbsMainActivityFragment(R.layout.fragment_album_det
aboutAlbumText.maxLines = 4
}
}
image.apply {
transitionName = getString(R.string.transition_album_art)
}
}
override fun onDestroy() {
@ -255,7 +262,7 @@ class AlbumDetailsFragment : AbsMainActivityFragment(R.layout.fragment_album_det
}
private fun loadArtistImage(artist: Artist) {
detailsViewModel.getMoreAlbums(artist).observe(viewLifecycleOwner, Observer {
detailsViewModel.getMoreAlbums(artist).observe(viewLifecycleOwner, {
moreAlbums(it)
})
ArtistGlideRequest.Builder.from(Glide.with(requireContext()), artist)
@ -288,6 +295,12 @@ class AlbumDetailsFragment : AbsMainActivityFragment(R.layout.fragment_album_det
}
override fun onAlbumClick(albumId: Long, view: View) {
exitTransition = MaterialElevationScale(false).apply {
duration = 300L
}
reenterTransition = MaterialElevationScale(false).apply {
duration = 300L
}
findNavController().navigate(
R.id.albumDetailsFragment,
bundleOf(EXTRA_ALBUM_ID to albumId),
@ -356,13 +369,10 @@ class AlbumDetailsFragment : AbsMainActivityFragment(R.layout.fragment_album_det
)
return true
}
/*Sort*/
R.id.action_sort_order_title -> sortOrder = SortOrder.AlbumSongSortOrder.SONG_A_Z
R.id.action_sort_order_title_desc -> sortOrder = SortOrder.AlbumSongSortOrder.SONG_Z_A
R.id.action_sort_order_track_list -> sortOrder =
SortOrder.AlbumSongSortOrder.SONG_TRACK_LIST
R.id.action_sort_order_artist_song_duration ->
sortOrder = SortOrder.AlbumSongSortOrder.SONG_DURATION
R.id.action_sort_order_title -> sortOrder = SONG_A_Z
R.id.action_sort_order_title_desc -> sortOrder = SONG_Z_A
R.id.action_sort_order_track_list -> sortOrder = SONG_TRACK_LIST
R.id.action_sort_order_artist_song_duration -> sortOrder = SONG_DURATION
}
if (sortOrder != null) {
item.isChecked = true
@ -373,36 +383,34 @@ class AlbumDetailsFragment : AbsMainActivityFragment(R.layout.fragment_album_det
private fun setUpSortOrderMenu(sortOrder: SubMenu) {
when (savedSortOrder) {
SortOrder.AlbumSongSortOrder.SONG_A_Z -> sortOrder.findItem(R.id.action_sort_order_title)
.isChecked = true
SortOrder.AlbumSongSortOrder.SONG_Z_A -> sortOrder.findItem(R.id.action_sort_order_title_desc)
.isChecked = true
SortOrder.AlbumSongSortOrder.SONG_TRACK_LIST -> sortOrder.findItem(R.id.action_sort_order_track_list)
.isChecked = true
SortOrder.AlbumSongSortOrder.SONG_DURATION -> sortOrder.findItem(R.id.action_sort_order_artist_song_duration)
.isChecked = true
SONG_A_Z -> sortOrder.findItem(R.id.action_sort_order_title).isChecked = true
SONG_Z_A -> sortOrder.findItem(R.id.action_sort_order_title_desc).isChecked = true
SONG_TRACK_LIST ->
sortOrder.findItem(R.id.action_sort_order_track_list).isChecked = true
SONG_DURATION ->
sortOrder.findItem(R.id.action_sort_order_artist_song_duration).isChecked = true
}
}
private fun setSaveSortOrder(sortOrder: String) {
PreferenceUtil.albumDetailSongSortOrder = sortOrder
val songs = when (sortOrder) {
SortOrder.AlbumSongSortOrder.SONG_TRACK_LIST -> album.songs.sortedWith { o1, o2 ->
SONG_TRACK_LIST -> album.songs.sortedWith { o1, o2 ->
o1.trackNumber.compareTo(
o2.trackNumber
)
}
SortOrder.AlbumSongSortOrder.SONG_A_Z -> album.songs.sortedWith { o1, o2 ->
SONG_A_Z -> album.songs.sortedWith { o1, o2 ->
o1.title.compareTo(
o2.title
)
}
SortOrder.AlbumSongSortOrder.SONG_Z_A -> album.songs.sortedWith { o1, o2 ->
SONG_Z_A -> album.songs.sortedWith { o1, o2 ->
o2.title.compareTo(
o1.title
)
}
SortOrder.AlbumSongSortOrder.SONG_DURATION -> album.songs.sortedWith { o1, o2 ->
SONG_DURATION -> album.songs.sortedWith { o1, o2 ->
o1.duration.compareTo(
o2.duration
)

View file

@ -17,7 +17,6 @@ package io.github.muntashirakon.music.fragments.albums
import android.os.Bundle
import android.view.*
import androidx.core.os.bundleOf
import androidx.lifecycle.Observer
import androidx.navigation.fragment.FragmentNavigatorExtras
import androidx.navigation.fragment.findNavController
import androidx.recyclerview.widget.GridLayoutManager
@ -27,7 +26,6 @@ import io.github.muntashirakon.music.adapter.album.AlbumAdapter
import io.github.muntashirakon.music.extensions.surfaceColor
import io.github.muntashirakon.music.fragments.ReloadType
import io.github.muntashirakon.music.fragments.base.AbsRecyclerViewCustomGridSizeFragment
import io.github.muntashirakon.music.helper.SortOrder
import io.github.muntashirakon.music.helper.SortOrder.AlbumSortOrder
import io.github.muntashirakon.music.interfaces.IAlbumClickListener
import io.github.muntashirakon.music.interfaces.ICabHolder
@ -35,13 +33,14 @@ import io.github.muntashirakon.music.util.PreferenceUtil
import io.github.muntashirakon.music.util.RetroColorUtil
import io.github.muntashirakon.music.util.RetroUtil
import com.afollestad.materialcab.MaterialCab
import com.google.android.material.transition.MaterialElevationScale
class AlbumsFragment : AbsRecyclerViewCustomGridSizeFragment<AlbumAdapter, GridLayoutManager>(),
IAlbumClickListener, ICabHolder {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
libraryViewModel.getAlbums().observe(viewLifecycleOwner, Observer {
libraryViewModel.getAlbums().observe(viewLifecycleOwner, {
if (it.isNotEmpty())
adapter?.swapDataSet(it)
else
@ -115,6 +114,12 @@ class AlbumsFragment : AbsRecyclerViewCustomGridSizeFragment<AlbumAdapter, GridL
}
override fun onAlbumClick(albumId: Long, view: View) {
exitTransition = MaterialElevationScale(false).apply {
duration = 300L
}
reenterTransition = MaterialElevationScale(true).apply {
duration = 300L
}
findNavController().navigate(
R.id.albumDetailsFragment,
bundleOf(EXTRA_ALBUM_ID to albumId),
@ -148,28 +153,28 @@ class AlbumsFragment : AbsRecyclerViewCustomGridSizeFragment<AlbumAdapter, GridL
0,
R.string.sort_order_a_z
).isChecked =
currentSortOrder.equals(SortOrder.AlbumSortOrder.ALBUM_A_Z)
currentSortOrder.equals(AlbumSortOrder.ALBUM_A_Z)
sortOrderMenu.add(
0,
R.id.action_album_sort_order_desc,
1,
R.string.sort_order_z_a
).isChecked =
currentSortOrder.equals(SortOrder.AlbumSortOrder.ALBUM_Z_A)
currentSortOrder.equals(AlbumSortOrder.ALBUM_Z_A)
sortOrderMenu.add(
0,
R.id.action_album_sort_order_artist,
2,
R.string.sort_order_artist
).isChecked =
currentSortOrder.equals(SortOrder.AlbumSortOrder.ALBUM_ARTIST)
currentSortOrder.equals(AlbumSortOrder.ALBUM_ARTIST)
sortOrderMenu.add(
0,
R.id.action_album_sort_order_year,
3,
R.string.sort_order_year
).isChecked =
currentSortOrder.equals(SortOrder.AlbumSortOrder.ALBUM_YEAR)
currentSortOrder.equals(AlbumSortOrder.ALBUM_YEAR)
sortOrderMenu.setGroupCheckable(0, true, true)
}
@ -300,16 +305,6 @@ class AlbumsFragment : AbsRecyclerViewCustomGridSizeFragment<AlbumAdapter, GridL
private var cab: MaterialCab? = null
fun handleBackPress(): Boolean {
cab?.let {
if (it.isActive) {
it.finish()
return true
}
}
return false
}
override fun openCab(menuRes: Int, callback: MaterialCab.Callback): MaterialCab {
cab?.let {
println("Cab")

View file

@ -16,6 +16,7 @@ package io.github.muntashirakon.music.fragments.artists
import android.app.Activity
import android.content.Intent
import android.graphics.Color
import android.os.Bundle
import android.text.Spanned
import android.view.Menu
@ -39,10 +40,7 @@ import io.github.muntashirakon.music.R
import io.github.muntashirakon.music.adapter.album.HorizontalAlbumAdapter
import io.github.muntashirakon.music.adapter.song.SimpleSongAdapter
import io.github.muntashirakon.music.dialogs.AddToPlaylistDialog
import io.github.muntashirakon.music.extensions.applyColor
import io.github.muntashirakon.music.extensions.applyOutlineColor
import io.github.muntashirakon.music.extensions.show
import io.github.muntashirakon.music.extensions.showToast
import io.github.muntashirakon.music.extensions.*
import io.github.muntashirakon.music.fragments.base.AbsMainActivityFragment
import io.github.muntashirakon.music.glide.ArtistGlideRequest
import io.github.muntashirakon.music.glide.SingleColorTarget
@ -57,6 +55,7 @@ import io.github.muntashirakon.music.util.MusicUtil
import io.github.muntashirakon.music.util.RetroUtil
import com.bumptech.glide.Glide
import com.google.android.material.transition.MaterialContainerTransform
import com.google.android.material.transition.MaterialElevationScale
import kotlinx.android.synthetic.main.fragment_artist_content.*
import kotlinx.android.synthetic.main.fragment_artist_details.*
import kotlinx.coroutines.Dispatchers
@ -81,27 +80,26 @@ class ArtistDetailsFragment : AbsMainActivityFragment(R.layout.fragment_artist_d
private var lang: String? = null
private var biography: Spanned? = null
private fun setUpTransitions() {
val transform = MaterialContainerTransform()
transform.setAllContainerColors(ATHUtil.resolveColor(requireContext(), R.attr.colorSurface))
sharedElementEnterTransition = transform
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setUpTransitions()
sharedElementEnterTransition = MaterialContainerTransform().apply {
drawingViewId = R.id.fragment_container
duration = 300L
scrimColor = Color.TRANSPARENT
setAllContainerColors(requireContext().resolveColor(R.attr.colorSurface))
}
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
setHasOptionsMenu(true)
mainActivity.setBottomBarVisibility(View.GONE)
mainActivity.setBottomBarVisibility(false)
mainActivity.addMusicServiceEventListener(detailsViewModel)
mainActivity.setSupportActionBar(toolbar)
toolbar.title = null
ViewCompat.setTransitionName(container, "artist")
ViewCompat.setTransitionName(artistCoverContainer, "artist")
postponeEnterTransition()
detailsViewModel.getArtist().observe(viewLifecycleOwner, Observer {
detailsViewModel.getArtist().observe(viewLifecycleOwner, {
startPostponedEnterTransition()
showArtist(it)
})
@ -150,14 +148,12 @@ class ArtistDetailsFragment : AbsMainActivityFragment(R.layout.fragment_artist_d
MusicUtil.getArtistInfoString(requireContext(), artist),
MusicUtil.getReadableDurationString(MusicUtil.getTotalDuration(artist.songs))
)
val songText =
resources.getQuantityString(
val songText = resources.getQuantityString(
R.plurals.albumSongs,
artist.songCount,
artist.songCount
)
val albumText =
resources.getQuantityString(
val albumText = resources.getQuantityString(
R.plurals.albums,
artist.songCount,
artist.songCount
@ -228,6 +224,12 @@ class ArtistDetailsFragment : AbsMainActivityFragment(R.layout.fragment_artist_d
}
override fun onAlbumClick(albumId: Long, view: View) {
exitTransition = MaterialElevationScale(false).apply {
duration = 300L
}
reenterTransition = MaterialElevationScale(false).apply {
duration = 300L
}
findNavController().navigate(
R.id.albumDetailsFragment,
bundleOf(EXTRA_ALBUM_ID to albumId),

View file

@ -34,6 +34,7 @@ import io.github.muntashirakon.music.util.PreferenceUtil
import io.github.muntashirakon.music.util.RetroColorUtil
import io.github.muntashirakon.music.util.RetroUtil
import com.afollestad.materialcab.MaterialCab
import com.google.android.material.transition.MaterialElevationScale
class ArtistsFragment : AbsRecyclerViewCustomGridSizeFragment<ArtistAdapter, GridLayoutManager>(),
IArtistClickListener, ICabHolder {
@ -114,6 +115,12 @@ class ArtistsFragment : AbsRecyclerViewCustomGridSizeFragment<ArtistAdapter, Gri
}
override fun onArtist(artistId: Long, view: View) {
exitTransition = MaterialElevationScale(true).apply {
duration = 300L
}
reenterTransition = MaterialElevationScale(false).apply {
duration = 300L
}
findNavController().navigate(
R.id.artistDetailsFragment,
bundleOf(EXTRA_ARTIST_ID to artistId),
@ -160,13 +167,13 @@ class ArtistsFragment : AbsRecyclerViewCustomGridSizeFragment<ArtistAdapter, Gri
when (itemLayoutRes()) {
R.layout.item_card -> subMenu.findItem(R.id.action_layout_card).isChecked = true
R.layout.item_grid -> subMenu.findItem(R.id.action_layout_normal).isChecked = true
R.layout.item_card_color ->
subMenu.findItem(R.id.action_layout_colored_card).isChecked = true
R.layout.item_grid_circle ->
subMenu.findItem(R.id.action_layout_circular).isChecked = true
R.layout.item_card_color -> subMenu.findItem(R.id.action_layout_colored_card).isChecked =
true
R.layout.item_grid_circle -> subMenu.findItem(R.id.action_layout_circular).isChecked =
true
R.layout.image -> subMenu.findItem(R.id.action_layout_image).isChecked = true
R.layout.item_image_gradient ->
subMenu.findItem(R.id.action_layout_gradient_image).isChecked = true
R.layout.item_image_gradient -> subMenu.findItem(R.id.action_layout_gradient_image).isChecked =
true
}
}
@ -275,21 +282,11 @@ class ArtistsFragment : AbsRecyclerViewCustomGridSizeFragment<ArtistAdapter, Gri
}
return false
}
private var cab: MaterialCab? = null
fun handleBackPress(): Boolean {
cab?.let {
if (it.isActive) {
it.finish()
return true
}
}
return false
}
private var cab: MaterialCab? = null
override fun openCab(menuRes: Int, callback: MaterialCab.Callback): MaterialCab {
cab?.let {
println("Cab")
if (it.isActive) {
it.finish()
}

View file

@ -22,6 +22,7 @@ import android.view.View
import androidx.annotation.NonNull
import androidx.annotation.StringRes
import androidx.core.text.HtmlCompat
import androidx.core.view.doOnPreDraw
import androidx.core.view.updatePadding
import androidx.navigation.fragment.findNavController
import androidx.recyclerview.widget.RecyclerView
@ -53,7 +54,11 @@ abstract class AbsRecyclerViewFragment<A : RecyclerView.Adapter<*>, LM : Recycle
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
mainActivity.setBottomBarVisibility(View.VISIBLE)
postponeEnterTransition()
view.doOnPreDraw { startPostponedEnterTransition() }
mainActivity.setBottomBarVisibility(true)
mainActivity.setSupportActionBar(toolbar)
mainActivity.supportActionBar?.title = null
initLayoutManager()
@ -78,7 +83,6 @@ abstract class AbsRecyclerViewFragment<A : RecyclerView.Adapter<*>, LM : Recycle
layoutManager = this@AbsRecyclerViewFragment.layoutManager
adapter = this@AbsRecyclerViewFragment.adapter
val fastScroller = create(this)
}
checkForPadding()
}

View file

@ -166,7 +166,7 @@ public class FoldersFragment extends AbsMainActivityFragment
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
getMainActivity().addMusicServiceEventListener(getLibraryViewModel());
getMainActivity().setBottomBarVisibility(View.VISIBLE);
getMainActivity().setBottomBarVisibility(true);
getMainActivity().setSupportActionBar(toolbar);
getMainActivity().getSupportActionBar().setTitle(null);
setStatusBarColorAuto(view);

View file

@ -14,6 +14,7 @@
*/
package io.github.muntashirakon.music.fragments.genres
import android.graphics.Color
import android.os.Bundle
import android.view.Menu
import android.view.MenuInflater
@ -24,14 +25,15 @@ import androidx.navigation.fragment.navArgs
import androidx.recyclerview.widget.DefaultItemAnimator
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import code.name.monkey.appthemehelper.util.ATHUtil
import io.github.muntashirakon.music.R
import io.github.muntashirakon.music.adapter.song.SongAdapter
import io.github.muntashirakon.music.extensions.dipToPix
import io.github.muntashirakon.music.extensions.resolveColor
import io.github.muntashirakon.music.fragments.base.AbsMainActivityFragment
import io.github.muntashirakon.music.helper.menu.GenreMenuHelper
import io.github.muntashirakon.music.model.Genre
import io.github.muntashirakon.music.model.Song
import com.google.android.material.transition.MaterialArcMotion
import com.google.android.material.transition.MaterialContainerTransform
import kotlinx.android.synthetic.main.fragment_playlist_detail.*
import org.koin.androidx.viewmodel.ext.android.viewModel
@ -45,21 +47,22 @@ class GenreDetailsFragment : AbsMainActivityFragment(R.layout.fragment_playlist_
}
private lateinit var genre: Genre
private lateinit var songAdapter: SongAdapter
private fun setUpTransitions() {
val transform = MaterialContainerTransform()
transform.setAllContainerColors(ATHUtil.resolveColor(requireContext(), R.attr.colorSurface))
sharedElementEnterTransition = transform
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setUpTransitions()
sharedElementEnterTransition = MaterialContainerTransform().apply {
drawingViewId = R.id.fragment_container
duration = 300L
scrimColor = Color.TRANSPARENT
setAllContainerColors(requireContext().resolveColor(R.attr.colorSurface))
setPathMotion(MaterialArcMotion())
}
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
setHasOptionsMenu(true)
mainActivity.setBottomBarVisibility(View.GONE)
mainActivity.setBottomBarVisibility(false)
mainActivity.addMusicServiceEventListener(detailsViewModel)
mainActivity.setSupportActionBar(toolbar)
ViewCompat.setTransitionName(container, "genre")

View file

@ -27,6 +27,7 @@ import io.github.muntashirakon.music.adapter.GenreAdapter
import io.github.muntashirakon.music.fragments.base.AbsRecyclerViewFragment
import io.github.muntashirakon.music.interfaces.IGenreClickListener
import io.github.muntashirakon.music.model.Genre
import com.google.android.material.transition.MaterialElevationScale
class GenresFragment : AbsRecyclerViewFragment<GenreAdapter, LinearLayoutManager>(),
IGenreClickListener {
@ -63,6 +64,12 @@ class GenresFragment : AbsRecyclerViewFragment<GenreAdapter, LinearLayoutManager
}
override fun onClickGenre(genre: Genre, view: View) {
exitTransition = MaterialElevationScale(false).apply {
duration = 300L
}
reenterTransition = MaterialElevationScale(true).apply {
duration = 300L
}
findNavController().navigate(
R.id.genreDetailsFragment,
bundleOf(EXTRA_GENRE to genre),

View file

@ -48,7 +48,7 @@ class HomeFragment :
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
mainActivity.setBottomBarVisibility(View.VISIBLE)
mainActivity.setBottomBarVisibility(true)
mainActivity.setSupportActionBar(toolbar)
mainActivity.supportActionBar?.title = null
setStatusBarColorAuto(view)

View file

@ -41,7 +41,7 @@ class LibraryFragment : AbsMainActivityFragment(R.layout.fragment_library) {
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
setHasOptionsMenu(true)
mainActivity.setBottomBarVisibility(View.VISIBLE)
mainActivity.setBottomBarVisibility(true)
mainActivity.setSupportActionBar(toolbar)
mainActivity.supportActionBar?.title = null
toolbar.setNavigationOnClickListener {

View file

@ -16,9 +16,11 @@ package io.github.muntashirakon.music.fragments.player.full
import android.animation.ObjectAnimator
import android.annotation.SuppressLint
import android.content.Intent
import android.content.res.ColorStateList
import android.graphics.Color
import android.graphics.PorterDuff
import android.graphics.drawable.Drawable
import android.os.AsyncTask
import android.os.Bundle
import android.view.MenuItem
@ -27,12 +29,18 @@ import android.view.animation.DecelerateInterpolator
import android.view.animation.LinearInterpolator
import android.widget.PopupMenu
import android.widget.SeekBar
import androidx.lifecycle.lifecycleScope
import code.name.monkey.appthemehelper.util.ColorUtil
import code.name.monkey.appthemehelper.util.TintHelper
import io.github.muntashirakon.music.R
import io.github.muntashirakon.music.db.PlaylistEntity
import io.github.muntashirakon.music.db.SongEntity
import io.github.muntashirakon.music.db.toSongEntity
import io.github.muntashirakon.music.extensions.applyColor
import io.github.muntashirakon.music.extensions.hide
import io.github.muntashirakon.music.extensions.show
import io.github.muntashirakon.music.fragments.LibraryViewModel
import io.github.muntashirakon.music.fragments.ReloadType
import io.github.muntashirakon.music.fragments.base.AbsPlayerControlsFragment
import io.github.muntashirakon.music.helper.MusicPlayerRemote
import io.github.muntashirakon.music.helper.MusicProgressViewUpdateHelper
@ -42,8 +50,13 @@ import io.github.muntashirakon.music.model.Song
import io.github.muntashirakon.music.service.MusicService
import io.github.muntashirakon.music.util.MusicUtil
import io.github.muntashirakon.music.util.PreferenceUtil
import io.github.muntashirakon.music.util.RetroUtil
import io.github.muntashirakon.music.util.color.MediaNotificationProcessor
import kotlinx.android.synthetic.main.fragment_full_player_controls.*
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import org.koin.androidx.viewmodel.ext.android.sharedViewModel
/**
* Created by hemanths on 20/09/17.
@ -56,6 +69,7 @@ class FullPlaybackControlsFragment :
private var lastPlaybackControlsColor: Int = 0
private var lastDisabledPlaybackControlsColor: Int = 0
private lateinit var progressViewUpdateHelper: MusicProgressViewUpdateHelper
private val libraryViewModel: LibraryViewModel by sharedViewModel()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@ -158,7 +172,6 @@ class FullPlaybackControlsFragment :
}
private fun setUpPlayPauseFab() {
playPauseButton.setOnClickListener(PlayPauseButtonOnClickHandler())
playPauseButton.post {
if (playPauseButton != null) {
@ -283,44 +296,41 @@ class FullPlaybackControlsFragment :
}
}
private fun toggleFavorite(song: Song) {
MusicUtil.toggleFavorite(requireContext(), song)
if (song.id == MusicPlayerRemote.currentSong.id) {
updateIsFavorite()
}
}
private var updateIsFavoriteTask: AsyncTask<*, *, *>? = null
@SuppressLint("StaticFieldLeak")
fun updateIsFavorite() {
if (updateIsFavoriteTask != null) {
updateIsFavoriteTask?.cancel(false)
}
updateIsFavoriteTask = object : AsyncTask<Song, Void, Boolean>() {
override fun doInBackground(vararg params: Song): Boolean? {
val activity = activity
return if (activity != null) {
MusicUtil.isFavorite(requireActivity(), params[0])
} else {
cancel(false)
null
}
}
override fun onPostExecute(isFavorite: Boolean?) {
val activity = activity
if (activity != null) {
val res = if (isFavorite!!)
R.drawable.ic_favorite
else
R.drawable.ic_favorite_border
val drawable = TintHelper.createTintedDrawable(activity, res, Color.WHITE)
lifecycleScope.launch(Dispatchers.IO) {
val playlist: PlaylistEntity? = libraryViewModel.favoritePlaylist()
if (playlist != null) {
val song: SongEntity =
MusicPlayerRemote.currentSong.toSongEntity(playlist.playListId)
val isFavorite: Boolean = libraryViewModel.isFavoriteSong(song).isNotEmpty()
withContext(Dispatchers.Main) {
val icon =
if (isFavorite) R.drawable.ic_favorite else R.drawable.ic_favorite_border
val drawable = TintHelper.createTintedDrawable(activity, icon, Color.WHITE)
songFavourite?.setImageDrawable(drawable)
}
}
}.execute(MusicPlayerRemote.currentSong)
}
}
private fun toggleFavorite(song: Song) {
if (song.id == MusicPlayerRemote.currentSong.id) {
updateIsFavorite()
}
lifecycleScope.launch(Dispatchers.IO) {
val playlist: PlaylistEntity? = libraryViewModel.favoritePlaylist()
if (playlist != null) {
val songEntity = song.toSongEntity(playlist.playListId)
val isFavorite = libraryViewModel.isFavoriteSong(songEntity).isNotEmpty()
if (isFavorite) {
libraryViewModel.removeSongFromPlaylist(songEntity)
} else {
libraryViewModel.insertSongs(listOf(song.toSongEntity(playlist.playListId)))
}
}
libraryViewModel.forceReload(ReloadType.Playlists)
requireContext().sendBroadcast(Intent(MusicService.FAVORITE_STATE_CHANGED))
}
}
fun onFavoriteToggled() {

View file

@ -1,5 +1,6 @@
package io.github.muntashirakon.music.fragments.playlists
import android.graphics.Color
import android.os.Bundle
import android.view.Menu
import android.view.MenuInflater
@ -12,14 +13,15 @@ import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import code.name.monkey.appthemehelper.util.ATHUtil
import io.github.muntashirakon.music.R
import io.github.muntashirakon.music.adapter.song.PlaylistSongAdapter
import io.github.muntashirakon.music.adapter.song.ShuffleButtonSongAdapter
import io.github.muntashirakon.music.db.PlaylistWithSongs
import io.github.muntashirakon.music.db.toSongs
import io.github.muntashirakon.music.extensions.dipToPix
import io.github.muntashirakon.music.extensions.resolveColor
import io.github.muntashirakon.music.fragments.base.AbsMainActivityFragment
import io.github.muntashirakon.music.helper.menu.PlaylistMenuHelper
import io.github.muntashirakon.music.model.Song
import io.github.muntashirakon.music.state.NowPlayingPanelState
import com.google.android.material.transition.MaterialArcMotion
import com.google.android.material.transition.MaterialContainerTransform
import kotlinx.android.synthetic.main.fragment_playlist_detail.*
import org.koin.androidx.viewmodel.ext.android.viewModel
@ -32,23 +34,23 @@ class PlaylistDetailsFragment : AbsMainActivityFragment(R.layout.fragment_playli
}
private lateinit var playlist: PlaylistWithSongs
private lateinit var playlistSongAdapter: PlaylistSongAdapter
private fun setUpTransitions() {
val transform = MaterialContainerTransform()
transform.setAllContainerColors(ATHUtil.resolveColor(requireContext(), R.attr.colorSurface))
sharedElementEnterTransition = transform
}
private lateinit var playlistSongAdapter: ShuffleButtonSongAdapter
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setUpTransitions()
sharedElementEnterTransition = MaterialContainerTransform().apply {
drawingViewId = R.id.fragment_container
duration = 300L
scrimColor = Color.TRANSPARENT
setAllContainerColors(requireContext().resolveColor(R.attr.colorSurface))
setPathMotion(MaterialArcMotion())
}
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
setHasOptionsMenu(true)
mainActivity.setBottomBarVisibility(View.GONE)
mainActivity.setBottomBarVisibility(false)
mainActivity.addMusicServiceEventListener(viewModel)
mainActivity.setSupportActionBar(toolbar)
ViewCompat.setTransitionName(container, "playlist")
@ -61,8 +63,7 @@ class PlaylistDetailsFragment : AbsMainActivityFragment(R.layout.fragment_playli
}
private fun setUpRecyclerView() {
playlistSongAdapter = PlaylistSongAdapter(
playlist.playlistEntity,
playlistSongAdapter = ShuffleButtonSongAdapter(
requireActivity(),
ArrayList(),
R.layout.item_list,

View file

@ -35,6 +35,7 @@ import io.github.muntashirakon.music.fragments.base.AbsRecyclerViewCustomGridSiz
import io.github.muntashirakon.music.helper.SortOrder.PlaylistSortOrder
import io.github.muntashirakon.music.interfaces.IPlaylistClickListener
import io.github.muntashirakon.music.util.PreferenceUtil
import com.google.android.material.transition.MaterialElevationScale
import kotlinx.android.synthetic.main.fragment_library.*
class PlaylistsFragment :
@ -183,6 +184,12 @@ class PlaylistsFragment :
}
override fun onPlaylistClick(playlistWithSongs: PlaylistWithSongs, view: View) {
exitTransition = MaterialElevationScale(false).apply {
duration = 300L
}
reenterTransition = MaterialElevationScale(true).apply {
duration = 300L
}
findNavController().navigate(
R.id.playlistDetailsFragment,
bundleOf(EXTRA_PLAYLIST to playlistWithSongs),

View file

@ -15,12 +15,15 @@
package io.github.muntashirakon.music.fragments.search
import android.content.ActivityNotFoundException
import android.content.Context
import android.content.Intent
import android.graphics.Color
import android.os.Bundle
import android.speech.RecognizerIntent
import android.text.Editable
import android.text.TextWatcher
import android.view.View
import android.view.inputmethod.InputMethodManager
import androidx.core.view.isGone
import androidx.core.view.isVisible
import androidx.recyclerview.widget.LinearLayoutManager
@ -28,12 +31,11 @@ import androidx.recyclerview.widget.RecyclerView
import androidx.transition.TransitionManager
import io.github.muntashirakon.music.R
import io.github.muntashirakon.music.adapter.SearchAdapter
import io.github.muntashirakon.music.extensions.accentColor
import io.github.muntashirakon.music.extensions.dipToPix
import io.github.muntashirakon.music.extensions.focusAndShowKeyboard
import io.github.muntashirakon.music.extensions.showToast
import io.github.muntashirakon.music.extensions.*
import io.github.muntashirakon.music.fragments.base.AbsMainActivityFragment
import com.google.android.material.textfield.TextInputEditText
import com.google.android.material.transition.MaterialArcMotion
import com.google.android.material.transition.MaterialContainerTransform
import kotlinx.android.synthetic.main.fragment_search.*
import java.util.*
import kotlin.collections.ArrayList
@ -47,18 +49,30 @@ class SearchFragment : AbsMainActivityFragment(R.layout.fragment_search), TextWa
private lateinit var searchAdapter: SearchAdapter
private var query: String? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
sharedElementEnterTransition = MaterialContainerTransform().apply {
drawingViewId = R.id.fragment_container
duration = 300L
scrimColor = Color.TRANSPARENT
setAllContainerColors(requireContext().resolveColor(R.attr.colorSurface))
setPathMotion(MaterialArcMotion())
}
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
mainActivity.setBottomBarVisibility(View.GONE)
mainActivity.setBottomBarVisibility(false)
mainActivity.setSupportActionBar(toolbar)
libraryViewModel.clearSearchResult()
setupRecyclerView()
voiceSearch.setOnClickListener { startMicSearch() }
clearText.setOnClickListener { searchView.clearText() }
searchView.apply {
addTextChangedListener(this@SearchFragment)
focusAndShowKeyboard()
}
voiceSearch.setOnClickListener { startMicSearch() }
clearText.setOnClickListener { searchView.clearText() }
keyboardPopup.apply {
accentColor()
setOnClickListener {
@ -143,6 +157,19 @@ class SearchFragment : AbsMainActivityFragment(R.layout.fragment_search), TextWa
showToast(getString(R.string.speech_not_supported))
}
}
override fun onDestroyView() {
hideKeyboard(view)
super.onDestroyView()
}
private fun hideKeyboard(view: View?) {
if (view != null) {
val imm: InputMethodManager =
requireContext().getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
imm.hideSoftInputFromWindow(view.windowToken, 0)
}
}
}
fun TextInputEditText.clearText() {

View file

@ -20,6 +20,7 @@ import androidx.annotation.LayoutRes
import androidx.lifecycle.Observer
import androidx.recyclerview.widget.GridLayoutManager
import io.github.muntashirakon.music.R
import io.github.muntashirakon.music.adapter.song.ShuffleButtonSongAdapter
import io.github.muntashirakon.music.adapter.song.SongAdapter
import io.github.muntashirakon.music.extensions.surfaceColor
import io.github.muntashirakon.music.fragments.ReloadType
@ -35,7 +36,7 @@ class SongsFragment : AbsRecyclerViewCustomGridSizeFragment<SongAdapter, GridLay
ICabHolder {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
libraryViewModel.getSongs().observe(viewLifecycleOwner, Observer {
libraryViewModel.getSongs().observe(viewLifecycleOwner, {
if (it.isNotEmpty())
adapter?.swapDataSet(it)
else
@ -52,7 +53,7 @@ class SongsFragment : AbsRecyclerViewCustomGridSizeFragment<SongAdapter, GridLay
override fun createAdapter(): SongAdapter {
val dataSet = if (adapter == null) mutableListOf() else adapter!!.dataSet
return SongAdapter(
return ShuffleButtonSongAdapter(
requireActivity(),
dataSet,
itemLayoutRes(),
@ -198,8 +199,7 @@ class SongsFragment : AbsRecyclerViewCustomGridSizeFragment<SongAdapter, GridLay
gridSizeMenu: SubMenu
) {
when (getGridSize()) {
1 -> gridSizeMenu.findItem(R.id.action_grid_size_1).isChecked =
true
1 -> gridSizeMenu.findItem(R.id.action_grid_size_1).isChecked = true
2 -> gridSizeMenu.findItem(R.id.action_grid_size_2).isChecked = true
3 -> gridSizeMenu.findItem(R.id.action_grid_size_3).isChecked = true
4 -> gridSizeMenu.findItem(R.id.action_grid_size_4).isChecked = true

View file

@ -71,7 +71,7 @@ class LibraryPreferenceDialog : DialogFragment() {
categoryAdapter.categoryInfos = PreferenceUtil.defaultCategories
}
.setNegativeButton(android.R.string.cancel, null)
.setPositiveButton(android.R.string.ok) { _, _ -> updateCategories(categoryAdapter.categoryInfos) }
.setPositiveButton( R.string.done) { _, _ -> updateCategories(categoryAdapter.categoryInfos) }
.setView(view)
.create()
.colorButtons()

View file

@ -100,7 +100,6 @@ class RealRoomRepository(
playlistDao.insertSongsToPlaylist(songs)
}
override fun getSongs(playListId: Long): LiveData<List<SongEntity>> =
playlistDao.songsFromPlaylist(playListId)
@ -160,10 +159,9 @@ class RealRoomRepository(
)
override suspend fun favoritePlaylistSongs(favorite: String): List<SongEntity> =
if (playlistDao.isPlaylistExists(favorite).isNotEmpty())
playlistDao.favoritesSongs(
playlistDao.isPlaylistExists(favorite).first().playListId
) else emptyList()
if (playlistDao.isPlaylistExists(favorite).isNotEmpty()) playlistDao.favoritesSongs(
playlistDao.isPlaylistExists(favorite).first().playListId
) else emptyList()
override suspend fun insertSongInPlayCount(playCountEntity: PlayCountEntity) =
playCountDao.insertSongInPlayCount(playCountEntity)
@ -192,10 +190,8 @@ class RealRoomRepository(
override suspend fun blackListPaths(): List<BlackListStoreEntity> =
blackListStoreDao.blackListPaths()
override suspend fun deleteSongs(songs: List<Song>) {
songs.forEach {
playCountDao.deleteSong(it.id)
}
override suspend fun deleteSongs(songs: List<Song>) = songs.forEach {
playCountDao.deleteSong(it.id)
}
override suspend fun deleteBlacklistPath(blackListStoreEntity: BlackListStoreEntity) =

View file

@ -94,7 +94,7 @@ object MusicUtil : KoinComponent {
fun deleteAlbumArt(context: Context, albumId: Long) {
val contentResolver = context.contentResolver
val localUri = Uri.parse("content://media/external/audio/albumart")
contentResolver.delete(ContentUris.withAppendedId(localUri, albumId.toLong()), null, null)
contentResolver.delete(ContentUris.withAppendedId(localUri, albumId), null, null)
contentResolver.notifyChange(localUri, null)
}
@ -165,7 +165,7 @@ object MusicUtil : KoinComponent {
try {
val newLyrics =
FileUtil.read(f)
if (newLyrics != null && !newLyrics.trim { it <= ' ' }.isEmpty()) {
if (newLyrics != null && newLyrics.trim { it <= ' ' }.isNotEmpty()) {
if (AbsSynchronizedLyrics.isSynchronized(newLyrics)) {
return newLyrics
}
@ -283,9 +283,8 @@ object MusicUtil : KoinComponent {
path: String?
) {
val contentResolver = context.contentResolver
val artworkUri =
Uri.parse("content://media/external/audio/albumart")
contentResolver.delete(ContentUris.withAppendedId(artworkUri, albumId.toLong()), null, null)
val artworkUri = Uri.parse("content://media/external/audio/albumart")
contentResolver.delete(ContentUris.withAppendedId(artworkUri, albumId), null, null)
val values = ContentValues()
values.put("album_id", albumId)
values.put("_data", path)
@ -444,9 +443,7 @@ object MusicUtil : KoinComponent {
}
fun deleteTracks(context: Context, songs: List<Song>) {
val projection = arrayOf(
BaseColumns._ID, MediaStore.MediaColumns.DATA
)
val projection = arrayOf(BaseColumns._ID, MediaStore.MediaColumns.DATA)
val selection = StringBuilder()
selection.append(BaseColumns._ID + " IN (")
for (i in songs.indices) {

View file

@ -27,7 +27,7 @@ import androidx.core.view.ViewCompat
import code.name.monkey.appthemehelper.util.ATHUtil
import code.name.monkey.appthemehelper.util.ColorUtil
import code.name.monkey.appthemehelper.util.MaterialValueHelper
import com.google.android.material.progressindicator.ProgressIndicator
import com.google.android.material.progressindicator.CircularProgressIndicator
object ViewUtil {
@ -77,9 +77,9 @@ object ViewUtil {
)
}
fun setProgressDrawable(progressIndicator: ProgressIndicator, newColor: Int) {
progressIndicator.indicatorColors = intArrayOf(newColor)
progressIndicator.trackColor = ColorUtil.withAlpha(newColor, 0.2f)
fun setProgressDrawable(indicator: CircularProgressIndicator, newColor: Int) {
indicator.setIndicatorColor(newColor)
indicator.trackColor = ColorUtil.withAlpha(newColor, 0.2f)
}
fun hitTest(v: View, x: Int, y: Int): Boolean {

View file

@ -31,9 +31,12 @@ class RetroShapeableImageView @JvmOverloads constructor(
init {
val typedArray =
context.obtainStyledAttributes(attrs, R.styleable.RetroShapeableImageView, defStyle, -1)
val cornerSize =
typedArray.getDimension(R.styleable.RetroShapeableImageView_retroCornerSize, 0f)
updateCornerSize(cornerSize)
val cornerSize = typedArray.getDimension(R.styleable.RetroShapeableImageView_retroCornerSize, 0f)
val circleShape = typedArray.getBoolean(R.styleable.RetroShapeableImageView_circleShape, false)
addOnLayoutChangeListener { _, _, _, _, _, _, _, _, _ ->
val radius = width / 2f
shapeAppearanceModel = ShapeAppearanceModel().withCornerSize(radius)
}
typedArray.recycle()
}