This commit is contained in:
Muntashir Al-Islam 2020-08-02 14:14:02 +06:00
commit 283280529b
140 changed files with 2267 additions and 931 deletions

View file

@ -20,10 +20,10 @@ import io.github.muntashirakon.music.dialogs.CreatePlaylistDialog.Companion.crea
import io.github.muntashirakon.music.fragments.LibraryViewModel
import io.github.muntashirakon.music.fragments.albums.AlbumsFragment
import io.github.muntashirakon.music.fragments.artists.ArtistsFragment
import io.github.muntashirakon.music.fragments.base.AbsLibraryPagerRecyclerViewCustomGridSizeFragment
import io.github.muntashirakon.music.fragments.base.AbsRecyclerViewCustomGridSizeFragment
import io.github.muntashirakon.music.fragments.folder.FoldersFragment
import io.github.muntashirakon.music.fragments.genres.GenresFragment
import io.github.muntashirakon.music.fragments.home.BannerHomeFragment
import io.github.muntashirakon.music.fragments.mainactivity.FoldersFragment
import io.github.muntashirakon.music.fragments.playlists.PlaylistsFragment
import io.github.muntashirakon.music.fragments.queue.PlayingQueueFragment
import io.github.muntashirakon.music.fragments.songs.SongsFragment
@ -60,7 +60,7 @@ class MainActivity : AbsSlidingMusicPanelActivity(),
const val EXPAND_PANEL = "expand_panel"
}
val libraryViewModel: LibraryViewModel by inject()
private val libraryViewModel: LibraryViewModel by inject()
private var cab: MaterialCab? = null
private val intentFilter = IntentFilter(Intent.ACTION_SCREEN_OFF)
private lateinit var currentFragment: MainActivityFragmentCallbacks
@ -157,7 +157,7 @@ class MainActivity : AbsSlidingMusicPanelActivity(),
.setShowAsActionFlags(MenuItem.SHOW_AS_ACTION_IF_ROOM)
}
val fragment: Fragment? = getCurrentFragment()
if (fragment != null && fragment is AbsLibraryPagerRecyclerViewCustomGridSizeFragment<*, *>) {
if (fragment != null && fragment is AbsRecyclerViewCustomGridSizeFragment<*, *>) {
val gridSizeItem: MenuItem = menu.findItem(R.id.action_grid_size)
if (RetroUtil.isLandscape()) {
gridSizeItem.setTitle(R.string.action_grid_size_land)
@ -187,7 +187,7 @@ class MainActivity : AbsSlidingMusicPanelActivity(),
override fun onOptionsItemSelected(item: MenuItem): Boolean {
val fragment = getCurrentFragment()
if (fragment is AbsLibraryPagerRecyclerViewCustomGridSizeFragment<*, *>) {
if (fragment is AbsRecyclerViewCustomGridSizeFragment<*, *>) {
if (handleGridSizeMenuItem(fragment, item)) {
return true
}
@ -221,7 +221,7 @@ class MainActivity : AbsSlidingMusicPanelActivity(),
}
private fun handleSortOrderMenuItem(
fragment: AbsLibraryPagerRecyclerViewCustomGridSizeFragment<*, *>,
fragment: AbsRecyclerViewCustomGridSizeFragment<*, *>,
item: MenuItem
): Boolean {
var sortOrder: String? = null
@ -265,7 +265,7 @@ class MainActivity : AbsSlidingMusicPanelActivity(),
}
private fun handleLayoutResType(
fragment: AbsLibraryPagerRecyclerViewCustomGridSizeFragment<*, *>,
fragment: AbsRecyclerViewCustomGridSizeFragment<*, *>,
item: MenuItem
): Boolean {
var layoutRes = -1
@ -286,7 +286,7 @@ class MainActivity : AbsSlidingMusicPanelActivity(),
}
private fun handleGridSizeMenuItem(
fragment: AbsLibraryPagerRecyclerViewCustomGridSizeFragment<*, *>,
fragment: AbsRecyclerViewCustomGridSizeFragment<*, *>,
item: MenuItem
): Boolean {
var gridSize = 0
@ -309,7 +309,7 @@ class MainActivity : AbsSlidingMusicPanelActivity(),
}
private fun setUpGridSizeMenu(
fragment: AbsLibraryPagerRecyclerViewCustomGridSizeFragment<*, *>,
fragment: AbsRecyclerViewCustomGridSizeFragment<*, *>,
gridSizeMenu: SubMenu
) {
when (fragment.getGridSize()) {
@ -344,7 +344,7 @@ class MainActivity : AbsSlidingMusicPanelActivity(),
}
private fun setupLayoutMenu(
fragment: AbsLibraryPagerRecyclerViewCustomGridSizeFragment<*, *>,
fragment: AbsRecyclerViewCustomGridSizeFragment<*, *>,
subMenu: SubMenu
) {
when (fragment.itemLayoutRes()) {
@ -366,7 +366,7 @@ class MainActivity : AbsSlidingMusicPanelActivity(),
}
private fun setUpSortOrderMenu(
fragment: AbsLibraryPagerRecyclerViewCustomGridSizeFragment<*, *>,
fragment: AbsRecyclerViewCustomGridSizeFragment<*, *>,
sortOrderMenu: SubMenu
) {
val currentSortOrder = fragment.getSortOrder()
@ -532,8 +532,13 @@ class MainActivity : AbsSlidingMusicPanelActivity(),
fragment: Fragment,
tag: String
) {
supportFragmentManager.commit {
setCustomAnimations(
R.anim.retro_fragment_open_enter,
R.anim.retro_fragment_open_exit,
R.anim.retro_fragment_fade_enter,
R.anim.retro_fragment_fade_exit
)
replace(R.id.fragment_container, fragment, tag)
}
currentFragment = fragment as MainActivityFragmentCallbacks

View file

@ -4,19 +4,23 @@ import android.os.Bundle
import android.view.MenuItem
import androidx.annotation.StringRes
import androidx.fragment.app.Fragment
import androidx.navigation.NavController
import androidx.navigation.fragment.NavHostFragment
import androidx.navigation.ui.AppBarConfiguration
import code.name.monkey.appthemehelper.ThemeStore
import code.name.monkey.appthemehelper.util.VersionUtils
import io.github.muntashirakon.music.R
import io.github.muntashirakon.music.activities.base.AbsBaseActivity
import io.github.muntashirakon.music.appshortcuts.DynamicShortcutManager
import io.github.muntashirakon.music.extensions.applyToolbar
import io.github.muntashirakon.music.fragments.settings.MainSettingsFragment
import com.afollestad.materialdialogs.color.ColorChooserDialog
import kotlinx.android.synthetic.main.activity_settings.*
class SettingsActivity : AbsBaseActivity(), ColorChooserDialog.ColorCallback {
private val fragmentManager = supportFragmentManager
private lateinit var appBarConfiguration: AppBarConfiguration
private lateinit var navController: NavController
override fun onCreate(savedInstanceState: Bundle?) {
setDrawUnderStatusBar()
@ -26,16 +30,25 @@ class SettingsActivity : AbsBaseActivity(), ColorChooserDialog.ColorCallback {
setNavigationbarColorAuto()
setLightNavigationBar(true)
setupToolbar()
if (savedInstanceState == null) {
fragmentManager.beginTransaction().replace(R.id.contentFrame, MainSettingsFragment())
.commit()
}
}
private fun setupToolbar() {
setTitle(R.string.action_settings)
applyToolbar(toolbar)
val navHostFragment =
supportFragmentManager.findFragmentById(R.id.contentFrame) as NavHostFragment
val navController: NavController = navHostFragment.navController
navController.addOnDestinationChangedListener { _, _, _ ->
toolbar.title = navController.currentDestination?.label
}
//It removes the back button
//appBarConfiguration = AppBarConfiguration(navController.graph)
//setupActionBarWithNavController(navController, appBarConfiguration)
}
override fun onSupportNavigateUp(): Boolean {
return navController.navigateUp() || super.onSupportNavigateUp()
}
fun setupFragment(fragment: Fragment, @StringRes titleName: Int) {

View file

@ -8,7 +8,6 @@ import android.view.Menu
import android.view.MenuItem
import android.view.SubMenu
import android.view.View
import android.widget.ImageView
import androidx.core.app.ActivityCompat
import androidx.recyclerview.widget.DefaultItemAnimator
import androidx.recyclerview.widget.GridLayoutManager
@ -25,7 +24,6 @@ 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.extraNotNull
import io.github.muntashirakon.music.extensions.ripAlpha
import io.github.muntashirakon.music.extensions.show
import io.github.muntashirakon.music.extensions.surfaceColor
import io.github.muntashirakon.music.glide.AlbumGlideRequest
@ -43,7 +41,7 @@ import com.afollestad.materialcab.MaterialCab
import com.bumptech.glide.Glide
import kotlinx.android.synthetic.main.activity_album.*
import kotlinx.android.synthetic.main.activity_album_content.*
import org.koin.android.viewmodel.ext.android.viewModel
import org.koin.androidx.viewmodel.ext.android.viewModel
import org.koin.core.parameter.parametersOf
import java.util.*
import android.util.Pair as UtilPair
@ -68,12 +66,11 @@ class AlbumDetailsActivity : AbsSlidingMusicPanelActivity(), CabHolder {
return cab as MaterialCab
}
private val detailsViewModel: AlbumDetailsViewModel by viewModel {
private val detailsViewModel by viewModel<AlbumDetailsViewModel> {
parametersOf(extraNotNull<Int>(EXTRA_ALBUM_ID).value)
}
private lateinit var simpleSongAdapter: SimpleSongAdapter
private lateinit var album: Album
private lateinit var artistImage: ImageView
private var cab: MaterialCab? = null
private val savedSortOrder: String
get() = PreferenceUtil.albumDetailSongSortOrder
@ -101,24 +98,25 @@ class AlbumDetailsActivity : AbsSlidingMusicPanelActivity(), CabHolder {
setBottomBarVisibility(View.GONE)
window.sharedElementsUseOverlay = true
windowEnterTransition()
toolbar.setBackgroundColor(surfaceColor())
addMusicServiceEventListener(detailsViewModel)
ActivityCompat.postponeEnterTransition(this)
//val viewModelFactory = AlbumDetailsViewModelFactory(application, albumId)
//viewModel = ViewModelProvider(this, viewModelFactory).get(AlbumDetailsViewModel::class.java)
detailsViewModel.getAlbum().observe(this, androidx.lifecycle.Observer {
ActivityCompat.startPostponedEnterTransition(this@AlbumDetailsActivity)
album(it)
showAlbum(it)
})
detailsViewModel.getArtist().observe(this, androidx.lifecycle.Observer {
loadArtistImage(it)
})
detailsViewModel.getMoreAlbums().observe(this, androidx.lifecycle.Observer {
moreAlbums(it)
})
detailsViewModel.getAlbumInfo().observe(this, androidx.lifecycle.Observer {
aboutAlbum(it)
})
setupRecyclerView()
artistImage = findViewById(R.id.artistImage)
artistImage.setOnClickListener {
val artistPairs = ActivityOptions.makeSceneTransitionAnimation(
this,
@ -155,12 +153,7 @@ class AlbumDetailsActivity : AbsSlidingMusicPanelActivity(), CabHolder {
}
}
fun complete() {
ActivityCompat.startPostponedEnterTransition(this)
}
fun album(album: Album) {
complete()
private fun showAlbum(album: Album) {
if (album.songs!!.isEmpty()) {
finish()
return
@ -196,7 +189,7 @@ class AlbumDetailsActivity : AbsSlidingMusicPanelActivity(), CabHolder {
detailsViewModel.loadAlbumInfo(album)
}
fun moreAlbums(albums: List<Album>) {
private fun moreAlbums(albums: List<Album>) {
moreTitle.show()
moreRecyclerView.show()
moreTitle.text = String.format(getString(R.string.label_more_from), album.artistName)
@ -211,7 +204,7 @@ class AlbumDetailsActivity : AbsSlidingMusicPanelActivity(), CabHolder {
moreRecyclerView.adapter = albumAdapter
}
fun aboutAlbum(lastFmAlbum: LastFmAlbum) {
private fun aboutAlbum(lastFmAlbum: LastFmAlbum) {
if (lastFmAlbum.album != null) {
if (lastFmAlbum.album.wiki != null) {
aboutAlbumText.show()
@ -232,7 +225,7 @@ class AlbumDetailsActivity : AbsSlidingMusicPanelActivity(), CabHolder {
}
}
fun loadArtistImage(artist: Artist) {
private fun loadArtistImage(artist: Artist) {
ArtistGlideRequest.Builder.from(Glide.with(this), artist)
.generatePalette(this)
.build()
@ -260,15 +253,17 @@ class AlbumDetailsActivity : AbsSlidingMusicPanelActivity(), CabHolder {
}
private fun setColors(color: MediaNotificationProcessor) {
val buttonColor = if (PreferenceUtil.isAdaptiveColor)
color.backgroundColor.ripAlpha()
else
ATHUtil.resolveColor(this, R.attr.colorSurface)
MaterialUtil.tintColor(
button = shuffleAction,
textColor = color.primaryTextColor,
backgroundColor = color.backgroundColor
)
MaterialUtil.tintColor(
button = playAction,
textColor = color.primaryTextColor,
backgroundColor = color.backgroundColor
)
MaterialUtil.setTint(button = shuffleAction, color = buttonColor)
MaterialUtil.setTint(button = playAction, color = buttonColor)
toolbar.setBackgroundColor(surfaceColor())
setSupportActionBar(toolbar)
supportActionBar?.title = null
}

View file

@ -0,0 +1,250 @@
package code.name.monkey.retromusic.activities.albums
import android.app.ActivityOptions
import android.os.Bundle
import android.transition.TransitionInflater
import android.util.Pair
import android.view.MenuItem
import android.view.View
import androidx.appcompat.app.AppCompatActivity
import androidx.navigation.fragment.findNavController
import androidx.recyclerview.widget.DefaultItemAnimator
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager
import code.name.monkey.appthemehelper.util.MaterialUtil
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.adapter.album.HorizontalAlbumAdapter
import code.name.monkey.retromusic.adapter.song.SimpleSongAdapter
import code.name.monkey.retromusic.extensions.extraNotNull
import code.name.monkey.retromusic.extensions.show
import code.name.monkey.retromusic.fragments.base.AbsMusicServiceFragment
import code.name.monkey.retromusic.glide.AlbumGlideRequest
import code.name.monkey.retromusic.glide.ArtistGlideRequest
import code.name.monkey.retromusic.glide.RetroMusicColoredTarget
import code.name.monkey.retromusic.helper.MusicPlayerRemote
import code.name.monkey.retromusic.model.Album
import code.name.monkey.retromusic.model.Artist
import code.name.monkey.retromusic.network.model.LastFmAlbum
import code.name.monkey.retromusic.util.MusicUtil
import code.name.monkey.retromusic.util.NavigationUtil
import code.name.monkey.retromusic.util.PreferenceUtil
import code.name.monkey.retromusic.util.RetroUtil
import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
import com.bumptech.glide.Glide
import kotlinx.android.synthetic.main.activity_album.*
import kotlinx.android.synthetic.main.activity_album_content.*
import org.koin.androidx.viewmodel.ext.android.viewModel
import org.koin.core.parameter.parametersOf
import java.util.*
class AlbumDetailsFragment : AbsMusicServiceFragment(R.layout.fragment_album_details) {
private lateinit var simpleSongAdapter: SimpleSongAdapter
private lateinit var album: Album
private val savedSortOrder: String
get() = PreferenceUtil.albumDetailSongSortOrder
private val detailsViewModel by viewModel<AlbumDetailsViewModel> {
parametersOf(extraNotNull<Int>(AlbumDetailsActivity.EXTRA_ALBUM_ID).value)
}
private fun setSharedElementTransitionOnEnter() {
sharedElementEnterTransition = TransitionInflater.from(context)
.inflateTransition(R.transition.change_bounds)
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
setSharedElementTransitionOnEnter()
postponeEnterTransition()
playerActivity?.addMusicServiceEventListener(detailsViewModel)
detailsViewModel.getAlbum().observe(viewLifecycleOwner, androidx.lifecycle.Observer {
startPostponedEnterTransition()
showAlbum(it)
})
detailsViewModel.getArtist().observe(viewLifecycleOwner, androidx.lifecycle.Observer {
loadArtistImage(it)
})
detailsViewModel.getMoreAlbums().observe(viewLifecycleOwner, androidx.lifecycle.Observer {
moreAlbums(it)
})
detailsViewModel.getAlbumInfo().observe(viewLifecycleOwner, androidx.lifecycle.Observer {
aboutAlbum(it)
})
setupRecyclerView()
artistImage.setOnClickListener {
val artistPairs = ActivityOptions.makeSceneTransitionAnimation(
requireActivity(),
Pair.create(
artistImage,
getString(R.string.transition_artist_image)
)
)
NavigationUtil.goToArtistOptions(requireActivity(), album.artistId, artistPairs)
}
playAction.setOnClickListener { MusicPlayerRemote.openQueue(album.songs!!, 0, true) }
shuffleAction.setOnClickListener {
MusicPlayerRemote.openAndShuffleQueue(
album.songs!!,
true
)
}
aboutAlbumText.setOnClickListener {
if (aboutAlbumText.maxLines == 4) {
aboutAlbumText.maxLines = Integer.MAX_VALUE
} else {
aboutAlbumText.maxLines = 4
}
}
image.apply {
transitionName = getString(R.string.transition_album_art)
}
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val activity = activity as AppCompatActivity
activity.supportActionBar?.setDisplayHomeAsUpEnabled(true)
}
override fun onDestroy() {
super.onDestroy()
playerActivity?.removeMusicServiceEventListener(detailsViewModel)
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
android.R.id.home -> findNavController().navigateUp()
}
return super.onOptionsItemSelected(item)
}
private fun setupRecyclerView() {
simpleSongAdapter = SimpleSongAdapter(
requireActivity() as AppCompatActivity,
ArrayList(),
R.layout.item_song,
null
)
recyclerView.apply {
layoutManager = LinearLayoutManager(requireContext())
itemAnimator = DefaultItemAnimator()
isNestedScrollingEnabled = false
adapter = simpleSongAdapter
}
}
private fun showAlbum(album: Album) {
if (album.songs!!.isEmpty()) {
return
}
this.album = album
albumTitle.text = album.title
val songText =
resources.getQuantityString(
R.plurals.albumSongs,
album.songCount,
album.songCount
)
songTitle.text = songText
if (MusicUtil.getYearString(album.year) == "-") {
albumText.text = String.format(
"%s • %s",
album.artistName,
MusicUtil.getReadableDurationString(MusicUtil.getTotalDuration(album.songs))
)
} else {
albumText.text = String.format(
"%s • %s • %s",
album.artistName,
MusicUtil.getYearString(album.year),
MusicUtil.getReadableDurationString(MusicUtil.getTotalDuration(album.songs))
)
}
loadAlbumCover()
simpleSongAdapter.swapDataSet(album.songs)
detailsViewModel.loadArtist(album.artistId)
detailsViewModel.loadAlbumInfo(album)
}
private fun moreAlbums(albums: List<Album>) {
moreTitle.show()
moreRecyclerView.show()
moreTitle.text = String.format(getString(R.string.label_more_from), album.artistName)
val albumAdapter =
HorizontalAlbumAdapter(requireActivity() as AppCompatActivity, albums, null)
moreRecyclerView.layoutManager = GridLayoutManager(
requireContext(),
1,
GridLayoutManager.HORIZONTAL,
false
)
moreRecyclerView.adapter = albumAdapter
}
private fun aboutAlbum(lastFmAlbum: LastFmAlbum) {
if (lastFmAlbum.album != null) {
if (lastFmAlbum.album.wiki != null) {
aboutAlbumText.show()
aboutAlbumTitle.show()
aboutAlbumTitle.text =
String.format(getString(R.string.about_album_label), lastFmAlbum.album.name)
aboutAlbumText.text = lastFmAlbum.album.wiki.content
}
if (lastFmAlbum.album.listeners.isNotEmpty()) {
listeners.show()
listenersLabel.show()
scrobbles.show()
scrobblesLabel.show()
listeners.text = RetroUtil.formatValue(lastFmAlbum.album.listeners.toFloat())
scrobbles.text = RetroUtil.formatValue(lastFmAlbum.album.playcount.toFloat())
}
}
}
private fun loadArtistImage(artist: Artist) {
ArtistGlideRequest.Builder.from(Glide.with(requireContext()), artist)
.generatePalette(requireContext())
.build()
.dontAnimate()
.dontTransform()
.into(object : RetroMusicColoredTarget(artistImage) {
override fun onColorReady(colors: MediaNotificationProcessor) {
}
})
}
private fun loadAlbumCover() {
AlbumGlideRequest.Builder.from(Glide.with(requireContext()), album.safeGetFirstSong())
.checkIgnoreMediaStore(requireContext())
.ignoreMediaStore(PreferenceUtil.isIgnoreMediaStoreArtwork)
.generatePalette(requireContext())
.build()
.dontAnimate()
.dontTransform()
.into(object : RetroMusicColoredTarget(image) {
override fun onColorReady(colors: MediaNotificationProcessor) {
setColors(colors)
}
})
}
private fun setColors(color: MediaNotificationProcessor) {
MaterialUtil.tintColor(
button = shuffleAction,
textColor = color.primaryTextColor,
backgroundColor = color.backgroundColor
)
MaterialUtil.tintColor(
button = playAction,
textColor = color.primaryTextColor,
backgroundColor = color.backgroundColor
)
}
}

View file

@ -7,8 +7,8 @@ import androidx.lifecycle.viewModelScope
import io.github.muntashirakon.music.interfaces.MusicServiceEventListener
import io.github.muntashirakon.music.model.Album
import io.github.muntashirakon.music.model.Artist
import io.github.muntashirakon.music.providers.RepositoryImpl
import io.github.muntashirakon.music.network.model.LastFmAlbum
import io.github.muntashirakon.music.providers.RepositoryImpl
import kotlinx.coroutines.Deferred
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
@ -23,10 +23,12 @@ class AlbumDetailsViewModel(
private val _album = MutableLiveData<Album>()
private val _artist = MutableLiveData<Artist>()
private val _lastFmAlbum = MutableLiveData<LastFmAlbum>()
private val _moreAlbums = MutableLiveData<List<Album>>()
fun getAlbum(): LiveData<Album> = _album
fun getArtist(): LiveData<Artist> = _artist
fun getAlbumInfo(): LiveData<LastFmAlbum> = _lastFmAlbum
fun getMoreAlbums(): LiveData<List<Album>> = _moreAlbums
init {
loadAlbumDetails()
@ -49,6 +51,10 @@ class AlbumDetailsViewModel(
fun loadArtist(artistId: Int) = viewModelScope.launch(Dispatchers.IO) {
val artist = repository.artistById(artistId)
_artist.postValue(artist)
artist.albums?.filter { item -> item.id != albumId }?.let { albums ->
if (albums.isNotEmpty()) _moreAlbums.postValue(albums)
}
}
private val loadAlbumAsync: Deferred<Album?>

View file

@ -22,7 +22,6 @@ 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.extraNotNull
import io.github.muntashirakon.music.extensions.ripAlpha
import io.github.muntashirakon.music.extensions.show
import io.github.muntashirakon.music.extensions.surfaceColor
import io.github.muntashirakon.music.glide.ArtistGlideRequest
@ -31,13 +30,16 @@ import io.github.muntashirakon.music.helper.MusicPlayerRemote
import io.github.muntashirakon.music.interfaces.CabHolder
import io.github.muntashirakon.music.model.Artist
import io.github.muntashirakon.music.network.model.LastFmArtist
import io.github.muntashirakon.music.util.*
import io.github.muntashirakon.music.util.CustomArtistImageUtil
import io.github.muntashirakon.music.util.MusicUtil
import io.github.muntashirakon.music.util.RetroColorUtil
import io.github.muntashirakon.music.util.RetroUtil
import io.github.muntashirakon.music.util.color.MediaNotificationProcessor
import com.afollestad.materialcab.MaterialCab
import com.bumptech.glide.Glide
import kotlinx.android.synthetic.main.activity_artist_content.*
import kotlinx.android.synthetic.main.activity_artist_details.*
import org.koin.android.viewmodel.ext.android.viewModel
import org.koin.androidx.viewmodel.ext.android.viewModel
import org.koin.core.parameter.parametersOf
import java.util.*
import kotlin.collections.ArrayList
@ -95,8 +97,11 @@ class ArtistDetailActivity : AbsSlidingMusicPanelActivity(), CabHolder {
setBottomBarVisibility(View.GONE)
window.sharedElementsUseOverlay = true
windowEnterTransition()
ActivityCompat.postponeEnterTransition(this)
toolbar.setBackgroundColor(surfaceColor())
addMusicServiceEventListener(detailsViewModel)
ActivityCompat.postponeEnterTransition(this)
detailsViewModel.getArtist().observe(this, androidx.lifecycle.Observer {
ActivityCompat.startPostponedEnterTransition(this@ArtistDetailActivity)
artist(it)
@ -150,18 +155,12 @@ class ArtistDetailActivity : AbsSlidingMusicPanelActivity(), CabHolder {
}
}
fun complete() {
ActivityCompat.startPostponedEnterTransition(this)
}
fun artist(artist: Artist) {
complete()
if (artist.songCount <= 0) {
if (artist.songs.isEmpty()) {
finish()
}
this.artist = artist
loadArtistImage()
loadArtistImage(artist)
if (RetroUtil.isAllowedToDownloadMetadata(this)) {
loadBiography(artist.name)
}
@ -186,7 +185,7 @@ class ArtistDetailActivity : AbsSlidingMusicPanelActivity(), CabHolder {
songTitle.text = songText
albumTitle.text = albumText
songAdapter.swapDataSet(artist.songs)
albumAdapter.swapDataSet(artist.albums!!)
artist.albums?.let { albumAdapter.swapDataSet(it) }
}
private fun loadBiography(
@ -198,7 +197,7 @@ class ArtistDetailActivity : AbsSlidingMusicPanelActivity(), CabHolder {
detailsViewModel.loadBiography(name, lang, null)
}
fun artistInfo(lastFmArtist: LastFmArtist?) {
private fun artistInfo(lastFmArtist: LastFmArtist?) {
if (lastFmArtist != null && lastFmArtist.artist != null) {
val bioContent = lastFmArtist.artist.bio.content
if (bioContent != null && bioContent.trim { it <= ' ' }.isNotEmpty()) {
@ -211,7 +210,6 @@ class ArtistDetailActivity : AbsSlidingMusicPanelActivity(), CabHolder {
listenersLabel.show()
scrobbles.show()
scrobblesLabel.show()
listeners.text =
RetroUtil.formatValue(lastFmArtist.artist.stats.listeners.toFloat())
scrobbles.text =
@ -228,8 +226,9 @@ class ArtistDetailActivity : AbsSlidingMusicPanelActivity(), CabHolder {
private var lang: String? = null
private fun loadArtistImage() {
ArtistGlideRequest.Builder.from(Glide.with(this), artist).generatePalette(this).build()
private fun loadArtistImage(artist: Artist) {
ArtistGlideRequest.Builder.from(Glide.with(this), artist)
.generatePalette(this).build()
.dontAnimate().into(object : RetroMusicColoredTarget(image) {
override fun onColorReady(colors: MediaNotificationProcessor) {
setColors(colors)
@ -238,16 +237,16 @@ class ArtistDetailActivity : AbsSlidingMusicPanelActivity(), CabHolder {
}
private fun setColors(color: MediaNotificationProcessor) {
val buttonColor = if (PreferenceUtil.isAdaptiveColor)
color.backgroundColor.ripAlpha()
else
ATHUtil.resolveColor(this, R.attr.colorSurface)
MaterialUtil.setTint(button = shuffleAction, color = buttonColor)
MaterialUtil.setTint(button = playAction, color = buttonColor)
toolbar.setBackgroundColor(surfaceColor())
MaterialUtil.tintColor(
button = shuffleAction,
textColor = color.primaryTextColor,
backgroundColor = color.backgroundColor
)
MaterialUtil.tintColor(
button = playAction,
textColor = color.primaryTextColor,
backgroundColor = color.backgroundColor
)
setSupportActionBar(toolbar)
supportActionBar?.title = null
}

View file

@ -1,6 +1,5 @@
package io.github.muntashirakon.music.activities.base
import android.animation.ValueAnimator
import android.graphics.Color
import android.os.Bundle
import android.view.View
@ -8,61 +7,41 @@ import android.view.ViewGroup
import android.view.ViewTreeObserver
import android.widget.FrameLayout
import androidx.annotation.LayoutRes
import androidx.fragment.app.Fragment
import androidx.lifecycle.Observer
import code.name.monkey.appthemehelper.util.ATHUtil
import code.name.monkey.appthemehelper.util.ColorUtil
import io.github.muntashirakon.music.R
import io.github.muntashirakon.music.RetroBottomSheetBehavior
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.MiniPlayerFragment
import io.github.muntashirakon.music.fragments.NowPlayingScreen
import io.github.muntashirakon.music.fragments.NowPlayingScreen.*
import io.github.muntashirakon.music.fragments.base.AbsPlayerFragment
import io.github.muntashirakon.music.fragments.player.adaptive.AdaptiveFragment
import io.github.muntashirakon.music.fragments.player.blur.BlurPlayerFragment
import io.github.muntashirakon.music.fragments.player.card.CardFragment
import io.github.muntashirakon.music.fragments.player.cardblur.CardBlurFragment
import io.github.muntashirakon.music.fragments.player.circle.CirclePlayerFragment
import io.github.muntashirakon.music.fragments.player.classic.ClassicPlayerFragment
import io.github.muntashirakon.music.fragments.player.color.ColorFragment
import io.github.muntashirakon.music.fragments.player.fit.FitFragment
import io.github.muntashirakon.music.fragments.player.flat.FlatPlayerFragment
import io.github.muntashirakon.music.fragments.player.full.FullPlayerFragment
import io.github.muntashirakon.music.fragments.player.gradient.GradientPlayerFragment
import io.github.muntashirakon.music.fragments.player.material.MaterialFragment
import io.github.muntashirakon.music.fragments.player.normal.PlayerFragment
import io.github.muntashirakon.music.fragments.player.peak.PeakPlayerFragment
import io.github.muntashirakon.music.fragments.player.plain.PlainPlayerFragment
import io.github.muntashirakon.music.fragments.player.simple.SimplePlayerFragment
import io.github.muntashirakon.music.fragments.player.tiny.TinyPlayerFragment
import io.github.muntashirakon.music.helper.MusicPlayerRemote
import io.github.muntashirakon.music.model.CategoryInfo
import io.github.muntashirakon.music.util.DensityUtil
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.shape.MaterialShapeDrawable
import com.google.android.material.shape.ShapeAppearanceModel
import kotlinx.android.synthetic.main.sliding_music_panel_layout.*
import org.koin.androidx.viewmodel.ext.android.viewModel
abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity(),
AbsPlayerFragment.Callbacks {
abstract class AbsSlidingMusicPanelActivity() : AbsMusicServiceActivity() {
companion object {
val TAG: String = AbsSlidingMusicPanelActivity::class.java.simpleName
}
private val libraryViewModel by viewModel<LibraryViewModel>()
private lateinit var behavior: RetroBottomSheetBehavior<FrameLayout>
private var miniPlayerFragment: MiniPlayerFragment? = null
private var playerFragment: AbsPlayerFragment? = null
private var cps: NowPlayingScreen? = null
private var navigationBarColor: Int = 0
private var taskColor: Int = 0
private var lightStatusBar: Boolean = false
private var lightNavigationBar: Boolean = false
private var navigationBarColorAnimator: ValueAnimator? = null
private var paletteColor: Int = Color.WHITE
protected abstract fun createContentView(): View
private lateinit var shapeDrawable: MaterialShapeDrawable
private val panelState: Int
get() = behavior.state
@ -72,7 +51,6 @@ abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity(),
setMiniPlayerAlphaProgress(slideOffset)
dimBackground.show()
dimBackground.alpha = slideOffset
shapeDrawable.interpolation = 1 - slideOffset
}
override fun onStateChanged(bottomSheet: View, newState: Int) {
@ -91,35 +69,29 @@ abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity(),
}
}
fun getBottomSheetBehavior() = behavior
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(createContentView())
chooseFragmentForTheme()
setupSlidingUpPanel()
addMusicServiceEventListener(libraryViewModel)
behavior = BottomSheetBehavior.from(slidingPanel) as RetroBottomSheetBehavior
setupBottomSheet()
val themeColor = ATHUtil.resolveColor(this, android.R.attr.windowBackground, Color.GRAY)
dimBackground.setBackgroundColor(ColorUtil.withAlpha(themeColor, 0.5f))
shapeDrawable = MaterialShapeDrawable(
ShapeAppearanceModel.builder(
this,
R.style.ClassicThemeOverLay,
0
).build()
)
slidingPanel.background = shapeDrawable
libraryViewModel.paletteColorLiveData.observe(this, Observer {
this.paletteColor = it
onPaletteColorChanged()
})
}
override fun onResume() {
super.onResume()
if (cps != PreferenceUtil.nowPlayingScreen) {
postRecreate()
}
fun getBottomSheetBehavior() = behavior
private fun setupBottomSheet() {
behavior = BottomSheetBehavior.from(slidingPanel) as RetroBottomSheetBehavior
behavior.addBottomSheetCallback(bottomSheetCallbackList)
if (behavior.state == BottomSheetBehavior.STATE_EXPANDED) {
@ -127,17 +99,23 @@ abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity(),
}
}
override fun onResume() {
super.onResume()
if (cps != PreferenceUtil.nowPlayingScreen) {
postRecreate()
}
}
override fun onDestroy() {
super.onDestroy()
behavior.removeBottomSheetCallback(bottomSheetCallbackList)
if (navigationBarColorAnimator != null) navigationBarColorAnimator?.cancel() // just in case
}
protected fun wrapSlidingMusicPanel(@LayoutRes resId: Int): View {
val slidingMusicPanelLayout =
layoutInflater.inflate(R.layout.sliding_music_panel_layout, null)
val contentContainer =
slidingMusicPanelLayout.findViewById<ViewGroup>(R.id.mainContentFrame)
val contentContainer: ViewGroup =
slidingMusicPanelLayout.findViewById(R.id.mainContentFrame)
layoutInflater.inflate(resId, contentContainer)
return slidingMusicPanelLayout
}
@ -159,7 +137,7 @@ abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity(),
miniPlayerFragment?.view?.visibility = if (alpha == 0f) View.GONE else View.VISIBLE
bottomNavigationView.translationY = progress * 500
//bottomNavigationView.alpha = alpha
bottomNavigationView.alpha = alpha
}
open fun onPanelCollapsed() {
@ -168,20 +146,9 @@ abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity(),
super.setTaskDescriptionColor(taskColor)
super.setNavigationbarColor(navigationBarColor)
super.setLightNavigationBar(lightNavigationBar)
playerFragment?.setMenuVisibility(false)
playerFragment?.userVisibleHint = false
playerFragment?.onHide()
}
open fun onPanelExpanded() {
val playerFragmentColor = playerFragment!!.paletteColor
super.setTaskDescriptionColor(playerFragmentColor)
playerFragment?.setMenuVisibility(true)
playerFragment?.userVisibleHint = true
playerFragment?.onShow()
onPaletteColorChanged()
}
@ -190,15 +157,12 @@ abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity(),
ViewTreeObserver.OnGlobalLayoutListener {
override fun onGlobalLayout() {
slidingPanel.viewTreeObserver.removeOnGlobalLayoutListener(this)
if (cps != Peak) {
val params = slidingPanel.layoutParams as ViewGroup.LayoutParams
params.height = ViewGroup.LayoutParams.MATCH_PARENT
slidingPanel.layoutParams = params
}
when (panelState) {
BottomSheetBehavior.STATE_EXPANDED -> onPanelExpanded()
BottomSheetBehavior.STATE_COLLAPSED -> onPanelCollapsed()
else -> playerFragment!!.onHide()
else -> {
//playerFragment!!.onHide()
}
}
}
})
@ -240,33 +204,6 @@ abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity(),
private fun chooseFragmentForTheme() {
cps = PreferenceUtil.nowPlayingScreen
val fragment: Fragment = when (cps) {
Blur -> BlurPlayerFragment()
Adaptive -> AdaptiveFragment()
Normal -> PlayerFragment()
Card -> CardFragment()
BlurCard -> CardBlurFragment()
Fit -> FitFragment()
Flat -> FlatPlayerFragment()
Full -> FullPlayerFragment()
Plain -> PlainPlayerFragment()
Simple -> SimplePlayerFragment()
Material -> MaterialFragment()
Color -> ColorFragment()
Tiny -> TinyPlayerFragment()
Peak -> PeakPlayerFragment()
Circle -> CirclePlayerFragment()
Classic -> ClassicPlayerFragment()
Gradient -> GradientPlayerFragment()
else -> PlayerFragment()
} // must implement AbsPlayerFragment
supportFragmentManager.beginTransaction()
.replace(R.id.playerFragmentContainer, fragment)
.commit()
supportFragmentManager.executePendingTransactions()
playerFragment =
supportFragmentManager.findFragmentById(R.id.playerFragmentContainer) as AbsPlayerFragment
miniPlayerFragment =
supportFragmentManager.findFragmentById(R.id.miniPlayerFragment) as MiniPlayerFragment
miniPlayerFragment?.view?.setOnClickListener { expandPanel() }
@ -295,7 +232,7 @@ abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity(),
}
open fun handleBackPress(): Boolean {
if (behavior.peekHeight != 0 && playerFragment!!.onBackPressed()) return true
if (panelState == BottomSheetBehavior.STATE_EXPANDED) {
collapsePanel()
return true
@ -303,13 +240,10 @@ abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity(),
return false
}
override fun onPaletteColorChanged() {
private fun onPaletteColorChanged() {
if (panelState == BottomSheetBehavior.STATE_EXPANDED) {
val paletteColor = playerFragment!!.paletteColor
super.setTaskDescriptionColor(paletteColor)
val isColorLight = ColorUtil.isColorLight(paletteColor)
if (PreferenceUtil.isAdaptiveColor && (cps == Normal || cps == Flat)) {
super.setLightNavigationBar(true)
super.setLightStatusbar(isColorLight)
@ -360,7 +294,6 @@ abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity(),
override fun setNavigationbarColor(color: Int) {
navigationBarColor = color
if (panelState == BottomSheetBehavior.STATE_COLLAPSED) {
if (navigationBarColorAnimator != null) navigationBarColorAnimator!!.cancel()
super.setNavigationbarColor(color)
}
}

View file

@ -21,7 +21,7 @@ import io.github.muntashirakon.music.util.DensityUtil
import io.github.muntashirakon.music.util.RetroColorUtil
import com.afollestad.materialcab.MaterialCab
import kotlinx.android.synthetic.main.activity_playlist_detail.*
import org.koin.android.viewmodel.ext.android.viewModel
import org.koin.androidx.viewmodel.ext.android.viewModel
import org.koin.core.parameter.parametersOf
import java.util.*

View file

@ -29,7 +29,7 @@ import com.h6ah4i.android.widget.advrecyclerview.animator.RefactoredDefaultItemA
import com.h6ah4i.android.widget.advrecyclerview.draggable.RecyclerViewDragDropManager
import com.h6ah4i.android.widget.advrecyclerview.utils.WrapperAdapterUtils
import kotlinx.android.synthetic.main.activity_playlist_detail.*
import org.koin.android.viewmodel.ext.android.viewModel
import org.koin.androidx.viewmodel.ext.android.viewModel
import org.koin.core.parameter.parametersOf