Merge pull request #1233 from prathameshmm02/dev

Bug fixes
This commit is contained in:
Daksh P. Jain 2022-01-31 07:56:29 +05:30 committed by GitHub
commit e7ed4ed62f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
55 changed files with 243 additions and 202 deletions

View file

@ -15,7 +15,7 @@ android {
applicationId "code.name.monkey.retromusic" applicationId "code.name.monkey.retromusic"
versionCode 10564 versionCode 10564
versionName '5.7.0' versionName '5.7.1'
buildConfigField("String", "GOOGLE_PLAY_LICENSING_KEY", "\"${getProperty(getProperties('../public.properties'), 'GOOGLE_PLAY_LICENSE_KEY')}\"") buildConfigField("String", "GOOGLE_PLAY_LICENSING_KEY", "\"${getProperty(getProperties('../public.properties'), 'GOOGLE_PLAY_LICENSE_KEY')}\"")
} }

View file

@ -60,13 +60,37 @@
{style-placeholder} {style-placeholder}
</style> </style>
</head> </head>
<body> <body>
<div>
<h5>February 1, 2022</h5>
<h2>v5.7.1</h2>
<h3>What's New</h3>
<ul>
<li>Added option to disable changing song by swiping anywhere on the now playing screen</li>
</ul>
<h3>Fixed</h3>
<ul>
<li>Fixed Playlist save on A11+</li>
<li>Fixed Just Black theme</li>
<li>Fixed some UI issues</li>
</ul>
<h3>Improved</h3>
<ul>
<li>Improvements to search</li>
</ul>
</div>
<div> <div>
<h5>January 25, 2022</h5> <h5>January 25, 2022</h5>
<h2>v5.7.0</h2> <h2>v5.7.0<span class="tag"><i>Beta</i></span></h2>
<h3>What's New</h3> <h3>What's New</h3>
<ul> <ul>
<li>Added Android Auto</li> <li>Added Android Auto</li>

View file

@ -55,6 +55,7 @@ object Constants {
) )
const val NUMBER_OF_TOP_TRACKS = 99 const val NUMBER_OF_TOP_TRACKS = 99
} }
const val EXTRA_PLAYLIST_TYPE = "type" const val EXTRA_PLAYLIST_TYPE = "type"
const val EXTRA_GENRE = "extra_genre" const val EXTRA_GENRE = "extra_genre"
const val EXTRA_PLAYLIST = "extra_playlist" const val EXTRA_PLAYLIST = "extra_playlist"
@ -162,3 +163,4 @@ const val APPBAR_MODE = "appbar_mode"
const val WALLPAPER_ACCENT = "wallpaper_accent" const val WALLPAPER_ACCENT = "wallpaper_accent"
const val SCREEN_ON_LYRICS = "screen_on_lyrics" const val SCREEN_ON_LYRICS = "screen_on_lyrics"
const val CIRCLE_PLAY_BUTTON = "circle_play_button" const val CIRCLE_PLAY_BUTTON = "circle_play_button"
const val SWIPE_ANYWHERE_NOW_PLAYING = "swipe_anywhere_now_playing"

View file

@ -24,7 +24,9 @@ import code.name.monkey.appthemehelper.util.VersionUtils
import code.name.monkey.retromusic.R import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.activities.base.AbsMusicServiceActivity import code.name.monkey.retromusic.activities.base.AbsMusicServiceActivity
import code.name.monkey.retromusic.databinding.ActivityLockScreenBinding import code.name.monkey.retromusic.databinding.ActivityLockScreenBinding
import code.name.monkey.retromusic.extensions.* import code.name.monkey.retromusic.extensions.hideStatusBar
import code.name.monkey.retromusic.extensions.setTaskDescriptionColorAuto
import code.name.monkey.retromusic.extensions.whichFragment
import code.name.monkey.retromusic.fragments.player.lockscreen.LockScreenControlsFragment import code.name.monkey.retromusic.fragments.player.lockscreen.LockScreenControlsFragment
import code.name.monkey.retromusic.glide.GlideApp import code.name.monkey.retromusic.glide.GlideApp
import code.name.monkey.retromusic.glide.RetroGlideExtension import code.name.monkey.retromusic.glide.RetroGlideExtension

View file

@ -39,7 +39,6 @@ import code.name.monkey.retromusic.extensions.*
import com.anjlab.android.iab.v3.BillingProcessor import com.anjlab.android.iab.v3.BillingProcessor
import com.anjlab.android.iab.v3.PurchaseInfo import com.anjlab.android.iab.v3.PurchaseInfo
import com.anjlab.android.iab.v3.SkuDetails import com.anjlab.android.iab.v3.SkuDetails
import java.util.*
class SupportDevelopmentActivity : AbsBaseActivity(), BillingProcessor.IBillingHandler { class SupportDevelopmentActivity : AbsBaseActivity(), BillingProcessor.IBillingHandler {

View file

@ -14,7 +14,10 @@ import code.name.monkey.appthemehelper.util.ToolbarContentTintHelper
import code.name.monkey.retromusic.Constants import code.name.monkey.retromusic.Constants
import code.name.monkey.retromusic.activities.base.AbsThemeActivity import code.name.monkey.retromusic.activities.base.AbsThemeActivity
import code.name.monkey.retromusic.databinding.ActivityWhatsNewBinding import code.name.monkey.retromusic.databinding.ActivityWhatsNewBinding
import code.name.monkey.retromusic.extensions.* import code.name.monkey.retromusic.extensions.accentColor
import code.name.monkey.retromusic.extensions.drawAboveSystemBars
import code.name.monkey.retromusic.extensions.setTaskDescriptionColorAuto
import code.name.monkey.retromusic.extensions.surfaceColor
import code.name.monkey.retromusic.util.PreferenceUtil.lastVersion import code.name.monkey.retromusic.util.PreferenceUtil.lastVersion
import code.name.monkey.retromusic.util.RetroUtil import code.name.monkey.retromusic.util.RetroUtil
import java.io.BufferedReader import java.io.BufferedReader

View file

@ -11,7 +11,6 @@ import com.google.android.gms.cast.framework.CastContext
import com.google.android.gms.cast.framework.CastSession import com.google.android.gms.cast.framework.CastSession
import com.google.android.gms.common.ConnectionResult import com.google.android.gms.common.ConnectionResult
import com.google.android.gms.common.GoogleApiAvailability import com.google.android.gms.common.GoogleApiAvailability
import java.util.*
abstract class AbsCastActivity : AbsSlidingMusicPanelActivity() { abstract class AbsCastActivity : AbsSlidingMusicPanelActivity() {

View file

@ -351,10 +351,10 @@ abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity() {
} }
private fun updateColor() { private fun updateColor() {
libraryViewModel.paletteColor.observe(this, { color -> libraryViewModel.paletteColor.observe(this) { color ->
this.paletteColor = color this.paletteColor = color
onPaletteColorChanged() onPaletteColorChanged()
}) }
} }
fun setBottomNavVisibility(visible: Boolean, animate: Boolean = false, hideBottomSheet: Boolean = MusicPlayerRemote.playingQueue.isEmpty()) { fun setBottomNavVisibility(visible: Boolean, animate: Boolean = false, hideBottomSheet: Boolean = MusicPlayerRemote.playingQueue.isEmpty()) {

View file

@ -51,7 +51,9 @@ abstract class AbsThemeActivity : ATHToolbarActivity(), Runnable {
private fun updateTheme() { private fun updateTheme() {
setTheme(ThemeManager.getThemeResValue()) setTheme(ThemeManager.getThemeResValue())
if (PreferenceUtil.materialYou) {
setDefaultNightMode(ThemeManager.getNightMode()) setDefaultNightMode(ThemeManager.getNightMode())
}
if (PreferenceUtil.isCustomFont) { if (PreferenceUtil.isCustomFont) {
setTheme(R.style.FontThemeOverlay) setTheme(R.style.FontThemeOverlay)

View file

@ -41,7 +41,6 @@ import code.name.monkey.retromusic.util.MusicUtil
import code.name.monkey.retromusic.util.PreferenceUtil import code.name.monkey.retromusic.util.PreferenceUtil
import code.name.monkey.retromusic.util.color.MediaNotificationProcessor import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
import me.zhanghai.android.fastscroll.PopupTextProvider import me.zhanghai.android.fastscroll.PopupTextProvider
import java.util.*
class ArtistAdapter( class ArtistAdapter(
override val activity: FragmentActivity, override val activity: FragmentActivity,

View file

@ -16,7 +16,6 @@ import code.name.monkey.retromusic.util.RetroColorUtil
import com.afollestad.materialcab.attached.AttachedCab import com.afollestad.materialcab.attached.AttachedCab
import com.afollestad.materialcab.attached.destroy import com.afollestad.materialcab.attached.destroy
import com.afollestad.materialcab.attached.isActive import com.afollestad.materialcab.attached.isActive
import java.util.*
abstract class AbsMultiSelectAdapter<V : RecyclerView.ViewHolder?, I>( abstract class AbsMultiSelectAdapter<V : RecyclerView.ViewHolder?, I>(
open val activity: FragmentActivity, private val ICabHolder: ICabHolder?, @MenuRes menuRes: Int open val activity: FragmentActivity, private val ICabHolder: ICabHolder?, @MenuRes menuRes: Int

View file

@ -19,14 +19,13 @@ import android.view.View
import androidx.core.view.isVisible import androidx.core.view.isVisible
import androidx.fragment.app.FragmentActivity import androidx.fragment.app.FragmentActivity
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import code.name.monkey.appthemehelper.ThemeStore
import code.name.monkey.retromusic.R import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.db.PlaylistEntity import code.name.monkey.retromusic.db.PlaylistEntity
import code.name.monkey.retromusic.db.toSongEntity import code.name.monkey.retromusic.db.toSongEntity
import code.name.monkey.retromusic.db.toSongsEntity import code.name.monkey.retromusic.db.toSongsEntity
import code.name.monkey.retromusic.dialogs.RemoveSongFromPlaylistDialog import code.name.monkey.retromusic.dialogs.RemoveSongFromPlaylistDialog
import code.name.monkey.retromusic.extensions.applyColor import code.name.monkey.retromusic.extensions.accentColor
import code.name.monkey.retromusic.extensions.applyOutlineColor import code.name.monkey.retromusic.extensions.accentOutlineColor
import code.name.monkey.retromusic.fragments.LibraryViewModel import code.name.monkey.retromusic.fragments.LibraryViewModel
import code.name.monkey.retromusic.helper.MusicPlayerRemote import code.name.monkey.retromusic.helper.MusicPlayerRemote
import code.name.monkey.retromusic.interfaces.ICabHolder import code.name.monkey.retromusic.interfaces.ICabHolder
@ -48,7 +47,6 @@ class OrderablePlaylistSongAdapter(
DraggableItemAdapter<OrderablePlaylistSongAdapter.ViewHolder> { DraggableItemAdapter<OrderablePlaylistSongAdapter.ViewHolder> {
val libraryViewModel: LibraryViewModel by activity.viewModel() val libraryViewModel: LibraryViewModel by activity.viewModel()
val tempDataSet = dataSet
init { init {
this.setHasStableIds(true) this.setHasStableIds(true)
@ -63,8 +61,6 @@ class OrderablePlaylistSongAdapter(
} else { } else {
-1 -1
} }
} }
override fun createViewHolder(view: View): SongAdapter.ViewHolder { override fun createViewHolder(view: View): SongAdapter.ViewHolder {
@ -77,19 +73,18 @@ class OrderablePlaylistSongAdapter(
override fun onBindViewHolder(holder: SongAdapter.ViewHolder, position: Int) { override fun onBindViewHolder(holder: SongAdapter.ViewHolder, position: Int) {
if (holder.itemViewType == OFFSET_ITEM) { if (holder.itemViewType == OFFSET_ITEM) {
val color = ThemeStore.accentColor(activity)
val viewHolder = holder as ViewHolder val viewHolder = holder as ViewHolder
viewHolder.playAction?.let { viewHolder.playAction?.let {
it.setOnClickListener { it.setOnClickListener {
MusicPlayerRemote.openQueue(dataSet, 0, true) MusicPlayerRemote.openQueue(dataSet, 0, true)
} }
it.applyOutlineColor(color) it.accentOutlineColor()
} }
viewHolder.shuffleAction?.let { viewHolder.shuffleAction?.let {
it.setOnClickListener { it.setOnClickListener {
MusicPlayerRemote.openAndShuffleQueue(dataSet, true) MusicPlayerRemote.openAndShuffleQueue(dataSet, true)
} }
it.applyColor(color) it.accentColor()
} }
} else { } else {
super.onBindViewHolder(holder, position - 1) super.onBindViewHolder(holder, position - 1)
@ -132,18 +127,10 @@ class OrderablePlaylistSongAdapter(
init { init {
dragView?.isVisible = true dragView?.isVisible = true
} }
override fun onClick(v: View?) {
if (itemViewType == OFFSET_ITEM) {
MusicPlayerRemote.openAndShuffleQueue(dataSet, true)
return
}
super.onClick(v)
}
} }
override fun onCheckCanStartDrag(holder: ViewHolder, position: Int, x: Int, y: Int): Boolean { override fun onCheckCanStartDrag(holder: ViewHolder, position: Int, x: Int, y: Int): Boolean {
if (dataSet.size == 0 or 1) { if (dataSet.size == 0 or 1 || isInQuickSelectMode) {
return false return false
} }
val dragHandle = holder.dragView ?: return false val dragHandle = holder.dragView ?: return false
@ -161,7 +148,6 @@ class OrderablePlaylistSongAdapter(
dataSet.add(toPosition - 1, dataSet.removeAt(fromPosition - 1)) dataSet.add(toPosition - 1, dataSet.removeAt(fromPosition - 1))
} }
override fun onGetItemDraggableRange(holder: ViewHolder, position: Int): ItemDraggableRange { override fun onGetItemDraggableRange(holder: ViewHolder, position: Int): ItemDraggableRange {
return ItemDraggableRange(1, itemCount - 1) return ItemDraggableRange(1, itemCount - 1)
} }

View file

@ -20,7 +20,6 @@ import androidx.fragment.app.FragmentActivity
import code.name.monkey.retromusic.interfaces.ICabHolder import code.name.monkey.retromusic.interfaces.ICabHolder
import code.name.monkey.retromusic.model.Song import code.name.monkey.retromusic.model.Song
import code.name.monkey.retromusic.util.MusicUtil import code.name.monkey.retromusic.util.MusicUtil
import java.util.*
class SimpleSongAdapter( class SimpleSongAdapter(
context: FragmentActivity, context: FragmentActivity,

View file

@ -25,7 +25,6 @@ import code.name.monkey.retromusic.service.MusicService
import code.name.monkey.retromusic.util.MusicUtil import code.name.monkey.retromusic.util.MusicUtil
import code.name.monkey.retromusic.util.PreferenceUtil import code.name.monkey.retromusic.util.PreferenceUtil
import java.lang.ref.WeakReference import java.lang.ref.WeakReference
import java.util.*
/** /**

View file

@ -8,7 +8,6 @@ import com.google.android.gms.cast.framework.SessionProvider
import com.google.android.gms.cast.framework.media.CastMediaOptions import com.google.android.gms.cast.framework.media.CastMediaOptions
import com.google.android.gms.cast.framework.media.MediaIntentReceiver import com.google.android.gms.cast.framework.media.MediaIntentReceiver
import com.google.android.gms.cast.framework.media.NotificationOptions import com.google.android.gms.cast.framework.media.NotificationOptions
import java.util.*
class CastOptionsProvider : OptionsProvider { class CastOptionsProvider : OptionsProvider {

View file

@ -21,9 +21,10 @@ fun Fragment.createNewFile(
registerForActivityResult(ActivityResultContracts.StartActivityForResult()) registerForActivityResult(ActivityResultContracts.StartActivityForResult())
{ result: ActivityResult -> { result: ActivityResult ->
if (result.resultCode == Activity.RESULT_OK) { if (result.resultCode == Activity.RESULT_OK) {
context?.contentResolver?.openOutputStream(result.data?.data!!)?.use { os-> write(
write(os, result.data?.data) context?.contentResolver?.openOutputStream(result.data?.data!!),
} result.data?.data
)
} }
} }

View file

@ -122,9 +122,9 @@ class AboutFragment : Fragment(R.layout.fragment_about), View.OnClickListener {
itemAnimator = DefaultItemAnimator() itemAnimator = DefaultItemAnimator()
adapter = contributorAdapter adapter = contributorAdapter
} }
libraryViewModel.fetchContributors().observe(viewLifecycleOwner, { contributors -> libraryViewModel.fetchContributors().observe(viewLifecycleOwner) { contributors ->
contributorAdapter.swapData(contributors) contributorAdapter.swapData(contributors)
}) }
} }
override fun onDestroyView() { override fun onDestroyView() {

View file

@ -122,7 +122,7 @@ class AlbumDetailsFragment : AbsMainActivityFragment(R.layout.fragment_album_det
binding.toolbar.title = " " binding.toolbar.title = " "
ViewCompat.setTransitionName(binding.albumCoverContainer, arguments.extraAlbumId.toString()) ViewCompat.setTransitionName(binding.albumCoverContainer, arguments.extraAlbumId.toString())
postponeEnterTransition() postponeEnterTransition()
detailsViewModel.getAlbum().observe(viewLifecycleOwner, { detailsViewModel.getAlbum().observe(viewLifecycleOwner) {
requireView().doOnPreDraw { requireView().doOnPreDraw {
startPostponedEnterTransition() startPostponedEnterTransition()
} }
@ -133,7 +133,7 @@ class AlbumDetailsFragment : AbsMainActivityFragment(R.layout.fragment_album_det
} else { } else {
ViewCompat.setTransitionName(binding.artistImage, album.artistId.toString()) ViewCompat.setTransitionName(binding.artistImage, album.artistId.toString())
} }
}) }
setupRecyclerView() setupRecyclerView()
binding.artistImage.setOnClickListener { artistView -> binding.artistImage.setOnClickListener { artistView ->
@ -236,17 +236,17 @@ class AlbumDetailsFragment : AbsMainActivityFragment(R.layout.fragment_album_det
simpleSongAdapter.swapDataSet(album.songs) simpleSongAdapter.swapDataSet(album.songs)
if (albumArtistExists) { if (albumArtistExists) {
detailsViewModel.getAlbumArtist(album.albumArtist.toString()) detailsViewModel.getAlbumArtist(album.albumArtist.toString())
.observe(viewLifecycleOwner, { .observe(viewLifecycleOwner) {
loadArtistImage(it) loadArtistImage(it)
}) }
} else { } else {
detailsViewModel.getArtist(album.artistId).observe(viewLifecycleOwner, { detailsViewModel.getArtist(album.artistId).observe(viewLifecycleOwner) {
loadArtistImage(it) loadArtistImage(it)
}) }
} }
detailsViewModel.getAlbumInfo(album).observe(viewLifecycleOwner, { result -> detailsViewModel.getAlbumInfo(album).observe(viewLifecycleOwner) { result ->
when (result) { when (result) {
is Result.Loading -> { is Result.Loading -> {
println("Loading") println("Loading")
@ -258,7 +258,7 @@ class AlbumDetailsFragment : AbsMainActivityFragment(R.layout.fragment_album_det
aboutAlbum(result.data) aboutAlbum(result.data)
} }
} }
}) }
} }
private fun moreAlbums(albums: List<Album>) { private fun moreAlbums(albums: List<Album>) {
@ -305,9 +305,9 @@ class AlbumDetailsFragment : AbsMainActivityFragment(R.layout.fragment_album_det
} }
private fun loadArtistImage(artist: Artist) { private fun loadArtistImage(artist: Artist) {
detailsViewModel.getMoreAlbums(artist).observe(viewLifecycleOwner, { detailsViewModel.getMoreAlbums(artist).observe(viewLifecycleOwner) {
moreAlbums(it) moreAlbums(it)
}) }
GlideApp.with(requireContext()).asBitmapPalette().artistImageOptions(artist) GlideApp.with(requireContext()).asBitmapPalette().artistImageOptions(artist)
//.forceDownload(PreferenceUtil.isAllowedToDownloadMetadata()) //.forceDownload(PreferenceUtil.isAllowedToDownloadMetadata())
.load( .load(

View file

@ -48,12 +48,12 @@ class AlbumsFragment : AbsRecyclerViewCustomGridSizeFragment<AlbumAdapter, GridL
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
libraryViewModel.getAlbums().observe(viewLifecycleOwner, { libraryViewModel.getAlbums().observe(viewLifecycleOwner) {
if (it.isNotEmpty()) if (it.isNotEmpty())
adapter?.swapDataSet(it) adapter?.swapDataSet(it)
else else
adapter?.swapDataSet(listOf()) adapter?.swapDataSet(listOf())
}) }
requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner) { requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner) {
if (!handleBackPress()) { if (!handleBackPress()) {
remove() remove()

View file

@ -92,12 +92,12 @@ abstract class AbsArtistDetailsFragment : AbsMainActivityFragment(R.layout.fragm
(artistId ?: artistName).toString() (artistId ?: artistName).toString()
) )
postponeEnterTransition() postponeEnterTransition()
detailsViewModel.getArtist().observe(viewLifecycleOwner, { detailsViewModel.getArtist().observe(viewLifecycleOwner) {
requireView().doOnPreDraw { requireView().doOnPreDraw {
startPostponedEnterTransition() startPostponedEnterTransition()
} }
showArtist(it) showArtist(it)
}) }
setupRecyclerView() setupRecyclerView()
binding.fragmentArtistContent.playAction.apply { binding.fragmentArtistContent.playAction.apply {
@ -180,13 +180,13 @@ abstract class AbsArtistDetailsFragment : AbsMainActivityFragment(R.layout.fragm
biography = null biography = null
this.lang = lang this.lang = lang
detailsViewModel.getArtistInfo(name, lang, null) detailsViewModel.getArtistInfo(name, lang, null)
.observe(viewLifecycleOwner, { result -> .observe(viewLifecycleOwner) { result ->
when (result) { when (result) {
is Result.Loading -> println("Loading") is Result.Loading -> println("Loading")
is Result.Error -> println("Error") is Result.Error -> println("Error")
is Result.Success -> artistInfo(result.data) is Result.Success -> artistInfo(result.data)
} }
}) }
} }
private fun artistInfo(lastFmArtist: LastFmArtist?) { private fun artistInfo(lastFmArtist: LastFmArtist?) {

View file

@ -49,12 +49,12 @@ class ArtistsFragment : AbsRecyclerViewCustomGridSizeFragment<ArtistAdapter, Gri
IArtistClickListener, IAlbumArtistClickListener, ICabHolder { IArtistClickListener, IAlbumArtistClickListener, ICabHolder {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
libraryViewModel.getArtists().observe(viewLifecycleOwner, { libraryViewModel.getArtists().observe(viewLifecycleOwner) {
if (it.isNotEmpty()) if (it.isNotEmpty())
adapter?.swapDataSet(it) adapter?.swapDataSet(it)
else else
adapter?.swapDataSet(listOf()) adapter?.swapDataSet(listOf())
}) }
requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner) { requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner) {
if (!handleBackPress()) { if (!handleBackPress()) {
remove() remove()

View file

@ -41,7 +41,7 @@ class BackupFragment : Fragment(R.layout.fragment_backup), BackupAdapter.BackupC
_binding = FragmentBackupBinding.bind(view) _binding = FragmentBackupBinding.bind(view)
initAdapter() initAdapter()
setupRecyclerview() setupRecyclerview()
backupViewModel.backupsLiveData.observe(this) { backupViewModel.backupsLiveData.observe(viewLifecycleOwner) {
if (it.isNotEmpty()) if (it.isNotEmpty())
backupAdapter?.swapDataset(it) backupAdapter?.swapDataset(it)
else else

View file

@ -315,11 +315,13 @@ abstract class AbsPlayerFragment(@LayoutRes layout: Int) : AbsMainActivityFragme
} }
} }
requireView().setOnTouchListener( requireView().setOnTouchListener(
if (PreferenceUtil.swipeAnywhereToChangeSong) {
SwipeDetector( SwipeDetector(
requireContext(), requireContext(),
playerAlbumCoverFragment?.viewPager, playerAlbumCoverFragment?.viewPager,
requireView() requireView()
) )
} else null
) )
} }

View file

@ -86,11 +86,11 @@ abstract class AbsRecyclerViewFragment<A : RecyclerView.Adapter<*>, LM : Recycle
} else { } else {
binding.shuffleButton.isVisible = false binding.shuffleButton.isVisible = false
} }
libraryViewModel.getFabMargin().observe(viewLifecycleOwner, { libraryViewModel.getFabMargin().observe(viewLifecycleOwner) {
binding.shuffleButton.updateLayoutParams<ViewGroup.MarginLayoutParams> { binding.shuffleButton.updateLayoutParams<ViewGroup.MarginLayoutParams> {
bottomMargin = it bottomMargin = it
} }
}) }
} }
open fun onShuffleClicked() { open fun onShuffleClicked() {

View file

@ -62,9 +62,9 @@ class GenreDetailsFragment : AbsMainActivityFragment(R.layout.fragment_playlist_
genre = arguments.extraGenre genre = arguments.extraGenre
binding.toolbar.title = arguments.extraGenre.name binding.toolbar.title = arguments.extraGenre.name
setupRecyclerView() setupRecyclerView()
detailsViewModel.getSongs().observe(viewLifecycleOwner, { detailsViewModel.getSongs().observe(viewLifecycleOwner) {
songs(it) songs(it)
}) }
postponeEnterTransition() postponeEnterTransition()
view.doOnPreDraw { view.doOnPreDraw {
startPostponedEnterTransition() startPostponedEnterTransition()

View file

@ -40,12 +40,12 @@ GenresFragment : AbsRecyclerViewFragment<GenreAdapter, LinearLayoutManager>(),
IGenreClickListener { IGenreClickListener {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
libraryViewModel.getGenre().observe(viewLifecycleOwner, { libraryViewModel.getGenre().observe(viewLifecycleOwner) {
if (it.isNotEmpty()) if (it.isNotEmpty())
adapter?.swapDataSet(it) adapter?.swapDataSet(it)
else else
adapter?.swapDataSet(listOf()) adapter?.swapDataSet(listOf())
}) }
requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner) { requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner) {
remove() remove()
requireActivity().onBackPressed() requireActivity().onBackPressed()

View file

@ -77,12 +77,12 @@ class HomeFragment :
layoutManager = LinearLayoutManager(mainActivity) layoutManager = LinearLayoutManager(mainActivity)
adapter = homeAdapter adapter = homeAdapter
} }
libraryViewModel.getHome().observe(viewLifecycleOwner, { libraryViewModel.getHome().observe(viewLifecycleOwner) {
homeAdapter.swapData(it) homeAdapter.swapData(it)
}) }
libraryViewModel.getSuggestions().observe(viewLifecycleOwner, { libraryViewModel.getSuggestions().observe(viewLifecycleOwner) {
loadSuggestions(it) loadSuggestions(it)
}) }
loadProfile() loadProfile()
setupTitle() setupTitle()

View file

@ -32,6 +32,7 @@ import androidx.fragment.app.FragmentActivity
import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.findNavController
import androidx.transition.Fade import androidx.transition.Fade
import androidx.viewpager2.adapter.FragmentStateAdapter import androidx.viewpager2.adapter.FragmentStateAdapter
import code.name.monkey.appthemehelper.common.ATHToolbarActivity
import code.name.monkey.appthemehelper.util.ToolbarContentTintHelper import code.name.monkey.appthemehelper.util.ToolbarContentTintHelper
import code.name.monkey.appthemehelper.util.VersionUtils import code.name.monkey.appthemehelper.util.VersionUtils
import code.name.monkey.retromusic.R import code.name.monkey.retromusic.R
@ -50,12 +51,16 @@ import code.name.monkey.retromusic.helper.MusicProgressViewUpdateHelper
import code.name.monkey.retromusic.lyrics.LrcView import code.name.monkey.retromusic.lyrics.LrcView
import code.name.monkey.retromusic.model.AudioTagInfo import code.name.monkey.retromusic.model.AudioTagInfo
import code.name.monkey.retromusic.model.Song import code.name.monkey.retromusic.model.Song
import code.name.monkey.retromusic.util.* import code.name.monkey.retromusic.util.FileUtils
import code.name.monkey.retromusic.util.LyricUtil
import code.name.monkey.retromusic.util.RetroUtil
import code.name.monkey.retromusic.util.UriUtil
import com.afollestad.materialdialogs.input.input import com.afollestad.materialdialogs.input.input
import com.google.android.material.color.MaterialColors import com.google.android.material.color.MaterialColors
import com.google.android.material.tabs.TabLayoutMediator import com.google.android.material.tabs.TabLayoutMediator
import com.google.android.material.transition.platform.MaterialContainerTransform import com.google.android.material.transition.platform.MaterialContainerTransform
import kotlinx.coroutines.* import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import org.jaudiotagger.audio.AudioFileIO import org.jaudiotagger.audio.AudioFileIO
import org.jaudiotagger.tag.FieldKey import org.jaudiotagger.tag.FieldKey
import java.io.File import java.io.File
@ -177,6 +182,20 @@ class LyricsFragment : AbsMusicServiceFragment(R.layout.fragment_lyrics) {
} }
} }
override fun onPlayingMetaChanged() {
super.onPlayingMetaChanged()
updateTitleSong()
}
override fun onServiceConnected() {
super.onServiceConnected()
updateTitleSong()
}
private fun updateTitleSong() {
song = MusicPlayerRemote.currentSong
}
private fun setupToolbar() { private fun setupToolbar() {
mainActivity.setSupportActionBar(binding.toolbar) mainActivity.setSupportActionBar(binding.toolbar)
ToolbarContentTintHelper.colorBackButton(binding.toolbar) ToolbarContentTintHelper.colorBackButton(binding.toolbar)
@ -191,6 +210,12 @@ class LyricsFragment : AbsMusicServiceFragment(R.layout.fragment_lyrics) {
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
inflater.inflate(R.menu.menu_search, menu) inflater.inflate(R.menu.menu_search, menu)
ToolbarContentTintHelper.handleOnCreateOptionsMenu(
requireContext(),
binding.toolbar,
menu,
ATHToolbarActivity.getToolbarBackgroundColor(binding.toolbar)
)
return super.onCreateOptionsMenu(menu, inflater) return super.onCreateOptionsMenu(menu, inflater)
} }

View file

@ -114,11 +114,11 @@ class UserInfoFragment : Fragment() {
view.doOnPreDraw { view.doOnPreDraw {
startPostponedEnterTransition() startPostponedEnterTransition()
} }
libraryViewModel.getFabMargin().observe(viewLifecycleOwner, { libraryViewModel.getFabMargin().observe(viewLifecycleOwner) {
binding.next.updateLayoutParams<ViewGroup.MarginLayoutParams> { binding.next.updateLayoutParams<ViewGroup.MarginLayoutParams> {
bottomMargin = it bottomMargin = it
} }
}) }
} }
private fun loadProfile() { private fun loadProfile() {

View file

@ -14,12 +14,10 @@
*/ */
package code.name.monkey.retromusic.fragments.player.blur package code.name.monkey.retromusic.fragments.player.blur
import android.animation.ObjectAnimator
import android.graphics.Color import android.graphics.Color
import android.os.Bundle import android.os.Bundle
import android.view.View import android.view.View
import android.view.animation.DecelerateInterpolator import android.view.animation.DecelerateInterpolator
import android.view.animation.LinearInterpolator
import android.widget.ImageButton import android.widget.ImageButton
import android.widget.SeekBar import android.widget.SeekBar
import android.widget.TextView import android.widget.TextView
@ -29,6 +27,7 @@ import code.name.monkey.appthemehelper.util.MaterialValueHelper
import code.name.monkey.appthemehelper.util.TintHelper import code.name.monkey.appthemehelper.util.TintHelper
import code.name.monkey.retromusic.R import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.databinding.FragmentBlurPlayerPlaybackControlsBinding import code.name.monkey.retromusic.databinding.FragmentBlurPlayerPlaybackControlsBinding
import code.name.monkey.retromusic.extensions.applyColor
import code.name.monkey.retromusic.extensions.getSongInfo import code.name.monkey.retromusic.extensions.getSongInfo
import code.name.monkey.retromusic.extensions.hide import code.name.monkey.retromusic.extensions.hide
import code.name.monkey.retromusic.extensions.show import code.name.monkey.retromusic.extensions.show
@ -36,7 +35,6 @@ import code.name.monkey.retromusic.fragments.base.AbsPlayerControlsFragment
import code.name.monkey.retromusic.fragments.base.goToAlbum import code.name.monkey.retromusic.fragments.base.goToAlbum
import code.name.monkey.retromusic.fragments.base.goToArtist import code.name.monkey.retromusic.fragments.base.goToArtist
import code.name.monkey.retromusic.helper.MusicPlayerRemote import code.name.monkey.retromusic.helper.MusicPlayerRemote
import code.name.monkey.retromusic.util.MusicUtil
import code.name.monkey.retromusic.util.PreferenceUtil import code.name.monkey.retromusic.util.PreferenceUtil
import code.name.monkey.retromusic.util.color.MediaNotificationProcessor import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
@ -134,7 +132,7 @@ class BlurPlaybackControlsFragment :
binding.text.setTextColor(lastPlaybackControlsColor) binding.text.setTextColor(lastPlaybackControlsColor)
binding.songInfo.setTextColor(lastDisabledPlaybackControlsColor) binding.songInfo.setTextColor(lastDisabledPlaybackControlsColor)
TintHelper.setTintAuto(binding.progressSlider, lastPlaybackControlsColor, false) binding.progressSlider.applyColor(lastPlaybackControlsColor)
volumeFragment?.setTintableColor(lastPlaybackControlsColor) volumeFragment?.setTintableColor(lastPlaybackControlsColor)
setFabColor(lastPlaybackControlsColor) setFabColor(lastPlaybackControlsColor)
} }

View file

@ -14,13 +14,12 @@
*/ */
package code.name.monkey.retromusic.fragments.player.flat package code.name.monkey.retromusic.fragments.player.flat
import android.animation.ObjectAnimator
import android.os.Bundle import android.os.Bundle
import android.view.View import android.view.View
import android.view.animation.DecelerateInterpolator import android.view.animation.DecelerateInterpolator
import android.view.animation.LinearInterpolator
import android.widget.ImageButton import android.widget.ImageButton
import android.widget.SeekBar import android.widget.SeekBar
import android.widget.TextView
import code.name.monkey.appthemehelper.ThemeStore import code.name.monkey.appthemehelper.ThemeStore
import code.name.monkey.appthemehelper.util.ATHUtil import code.name.monkey.appthemehelper.util.ATHUtil
import code.name.monkey.appthemehelper.util.ColorUtil import code.name.monkey.appthemehelper.util.ColorUtil
@ -35,7 +34,6 @@ import code.name.monkey.retromusic.fragments.base.goToArtist
import code.name.monkey.retromusic.helper.MusicPlayerRemote import code.name.monkey.retromusic.helper.MusicPlayerRemote
import code.name.monkey.retromusic.helper.MusicProgressViewUpdateHelper.Callback import code.name.monkey.retromusic.helper.MusicProgressViewUpdateHelper.Callback
import code.name.monkey.retromusic.helper.PlayPauseButtonOnClickHandler import code.name.monkey.retromusic.helper.PlayPauseButtonOnClickHandler
import code.name.monkey.retromusic.util.MusicUtil
import code.name.monkey.retromusic.util.PreferenceUtil import code.name.monkey.retromusic.util.PreferenceUtil
import code.name.monkey.retromusic.util.color.MediaNotificationProcessor import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
@ -60,6 +58,12 @@ class FlatPlaybackControlsFragment :
override val previousButton: ImageButton? override val previousButton: ImageButton?
get() = null get() = null
override val songTotalTime: TextView
get() = binding.songTotalTime
override val songCurrentProgress: TextView
get() = binding.songCurrentProgress
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
_binding = FragmentFlatPlayerPlaybackControlsBinding.bind(view) _binding = FragmentFlatPlayerPlaybackControlsBinding.bind(view)

View file

@ -132,7 +132,7 @@ class FullPlayerFragment : AbsPlayerFragment(R.layout.fragment_full) {
private fun updateArtistImage() { private fun updateArtistImage() {
libraryViewModel.artist(MusicPlayerRemote.currentSong.artistId) libraryViewModel.artist(MusicPlayerRemote.currentSong.artistId)
.observe(viewLifecycleOwner, { artist -> .observe(viewLifecycleOwner) { artist ->
if (artist.id != -1L) { if (artist.id != -1L) {
GlideApp.with(requireActivity()).asBitmapPalette().artistImageOptions(artist) GlideApp.with(requireActivity()).asBitmapPalette().artistImageOptions(artist)
.load(RetroGlideExtension.getArtistModel(artist)) .load(RetroGlideExtension.getArtistModel(artist))
@ -142,7 +142,7 @@ class FullPlayerFragment : AbsPlayerFragment(R.layout.fragment_full) {
}) })
} }
}) }
} }
override fun onQueueChanged() { override fun onQueueChanged() {

View file

@ -1,7 +1,6 @@
package code.name.monkey.retromusic.fragments.playlists package code.name.monkey.retromusic.fragments.playlists
import android.os.Bundle import android.os.Bundle
import android.util.Log
import android.view.Menu import android.view.Menu
import android.view.MenuInflater import android.view.MenuInflater
import android.view.MenuItem import android.view.MenuItem
@ -20,7 +19,6 @@ import code.name.monkey.retromusic.db.PlaylistWithSongs
import code.name.monkey.retromusic.db.toSongs import code.name.monkey.retromusic.db.toSongs
import code.name.monkey.retromusic.extensions.dip import code.name.monkey.retromusic.extensions.dip
import code.name.monkey.retromusic.extensions.surfaceColor import code.name.monkey.retromusic.extensions.surfaceColor
import code.name.monkey.retromusic.extensions.updateMargin
import code.name.monkey.retromusic.fragments.base.AbsMainActivityFragment import code.name.monkey.retromusic.fragments.base.AbsMainActivityFragment
import code.name.monkey.retromusic.helper.MusicPlayerRemote import code.name.monkey.retromusic.helper.MusicPlayerRemote
import code.name.monkey.retromusic.helper.menu.PlaylistMenuHelper import code.name.monkey.retromusic.helper.menu.PlaylistMenuHelper
@ -51,7 +49,6 @@ class PlaylistDetailsFragment : AbsMainActivityFragment(R.layout.fragment_playli
private var _binding: FragmentPlaylistDetailBinding? = null private var _binding: FragmentPlaylistDetailBinding? = null
private val binding get() = _binding!! private val binding get() = _binding!!
private lateinit var playlist: PlaylistWithSongs private lateinit var playlist: PlaylistWithSongs
private lateinit var playlistSongAdapter: OrderablePlaylistSongAdapter private lateinit var playlistSongAdapter: OrderablePlaylistSongAdapter
@ -67,9 +64,9 @@ class PlaylistDetailsFragment : AbsMainActivityFragment(R.layout.fragment_playli
playlist = arguments.extraPlaylist playlist = arguments.extraPlaylist
binding.toolbar.title = playlist.playlistEntity.playlistName binding.toolbar.title = playlist.playlistEntity.playlistName
setUpRecyclerView() setUpRecyclerView()
viewModel.getSongs().observe(viewLifecycleOwner, { viewModel.getSongs().observe(viewLifecycleOwner) {
songs(it.toSongs()) songs(it.toSongs())
}) }
postponeEnterTransition() postponeEnterTransition()
requireView().doOnPreDraw { startPostponedEnterTransition() } requireView().doOnPreDraw { startPostponedEnterTransition() }
requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner) { requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner) {
@ -157,7 +154,6 @@ class PlaylistDetailsFragment : AbsMainActivityFragment(R.layout.fragment_playli
fun songs(songs: List<Song>) { fun songs(songs: List<Song>) {
binding.progressIndicator.hide() binding.progressIndicator.hide()
if (songs.isNotEmpty()) { if (songs.isNotEmpty()) {
Log.i("Updated", songs[0].title)
playlistSongAdapter.swapDataSet(songs) playlistSongAdapter.swapDataSet(songs)
} else { } else {
showEmptyView() showEmptyView()

View file

@ -40,12 +40,12 @@ class PlaylistsFragment :
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
libraryViewModel.getPlaylists().observe(viewLifecycleOwner, { libraryViewModel.getPlaylists().observe(viewLifecycleOwner) {
if (it.isNotEmpty()) if (it.isNotEmpty())
adapter?.swapDataSet(it) adapter?.swapDataSet(it)
else else
adapter?.swapDataSet(listOf()) adapter?.swapDataSet(listOf())
}) }
requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner) { requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner) {
remove() remove()
requireActivity().onBackPressed() requireActivity().onBackPressed()

View file

@ -88,19 +88,19 @@ class SearchFragment : AbsMainActivityFragment(R.layout.fragment_search), TextWa
if (savedInstanceState != null) { if (savedInstanceState != null) {
query = savedInstanceState.getString(QUERY) query = savedInstanceState.getString(QUERY)
} }
libraryViewModel.getSearchResult().observe(viewLifecycleOwner, { libraryViewModel.getSearchResult().observe(viewLifecycleOwner) {
showData(it) showData(it)
}) }
setupChips() setupChips()
postponeEnterTransition() postponeEnterTransition()
view.doOnPreDraw { view.doOnPreDraw {
startPostponedEnterTransition() startPostponedEnterTransition()
} }
libraryViewModel.getFabMargin().observe(viewLifecycleOwner, { libraryViewModel.getFabMargin().observe(viewLifecycleOwner) {
binding.keyboardPopup.updateLayoutParams<ViewGroup.MarginLayoutParams> { binding.keyboardPopup.updateLayoutParams<ViewGroup.MarginLayoutParams> {
bottomMargin = it bottomMargin = it
} }
}) }
KeyboardVisibilityEvent.setEventListener(requireActivity(), viewLifecycleOwner) { KeyboardVisibilityEvent.setEventListener(requireActivity(), viewLifecycleOwner) {
if (it) { if (it) {
binding.keyboardPopup.isGone = true binding.keyboardPopup.isGone = true
@ -192,6 +192,7 @@ class SearchFragment : AbsMainActivityFragment(R.layout.fragment_search), TextWa
R.id.chip_albums -> Filter.ALBUMS R.id.chip_albums -> Filter.ALBUMS
R.id.chip_album_artists -> Filter.ALBUM_ARTISTS R.id.chip_album_artists -> Filter.ALBUM_ARTISTS
R.id.chip_genres -> Filter.GENRES R.id.chip_genres -> Filter.GENRES
R.id.chip_playlists -> Filter.PLAYLISTS
else -> Filter.NO_FILTER else -> Filter.NO_FILTER
} }
} }
@ -245,6 +246,7 @@ enum class Filter {
ALBUMS, ALBUMS,
ALBUM_ARTISTS, ALBUM_ARTISTS,
GENRES, GENRES,
PLAYLISTS,
NO_FILTER NO_FILTER
} }

View file

@ -42,12 +42,12 @@ class SongsFragment : AbsRecyclerViewCustomGridSizeFragment<SongAdapter, GridLay
ICabHolder { ICabHolder {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
libraryViewModel.getSongs().observe(viewLifecycleOwner, { libraryViewModel.getSongs().observe(viewLifecycleOwner) {
if (it.isNotEmpty()) if (it.isNotEmpty())
adapter?.swapDataSet(it) adapter?.swapDataSet(it)
else else
adapter?.swapDataSet(listOf()) adapter?.swapDataSet(listOf())
}) }
requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner) { requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner) {
if (!handleBackPress()) { if (!handleBackPress()) {
remove() remove()

View file

@ -72,7 +72,8 @@ object M3UWriter : M3UConstants {
it.songPrimaryKey it.songPrimaryKey
}.toSongs() }.toSongs()
if (songs.isNotEmpty()) { if (songs.isNotEmpty()) {
outputStream.bufferedWriter().use{ bw-> outputStream.use { os ->
os.bufferedWriter().use { bw->
bw.write(M3UConstants.HEADER) bw.write(M3UConstants.HEADER)
songs.forEach { songs.forEach {
bw.newLine() bw.newLine()
@ -82,7 +83,6 @@ object M3UWriter : M3UConstants {
} }
} }
} }
outputStream.flush() }
outputStream.close()
} }
} }

View file

@ -21,7 +21,6 @@ import code.name.monkey.retromusic.model.Song
import code.name.monkey.retromusic.repository.RealSongRepository import code.name.monkey.retromusic.repository.RealSongRepository
import org.koin.core.component.KoinComponent import org.koin.core.component.KoinComponent
import org.koin.core.component.inject import org.koin.core.component.inject
import java.util.*
object SearchQueryHelper : KoinComponent { object SearchQueryHelper : KoinComponent {
private const val TITLE_SELECTION = "lower(" + MediaStore.Audio.AudioColumns.TITLE + ") = ?" private const val TITLE_SELECTION = "lower(" + MediaStore.Audio.AudioColumns.TITLE + ") = ?"

View file

@ -36,7 +36,6 @@ import android.widget.Scroller
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import code.name.monkey.retromusic.R import code.name.monkey.retromusic.R
import java.io.File import java.io.File
import java.util.*
import kotlin.math.abs import kotlin.math.abs
/** /**

View file

@ -16,19 +16,19 @@ package code.name.monkey.retromusic.repository
import android.content.ContentResolver import android.content.ContentResolver
import android.database.Cursor import android.database.Cursor
import android.net.Uri
import android.provider.BaseColumns import android.provider.BaseColumns
import android.provider.MediaStore.Audio.Genres import android.provider.MediaStore.Audio.Genres
import code.name.monkey.retromusic.Constants.IS_MUSIC import code.name.monkey.retromusic.Constants.IS_MUSIC
import code.name.monkey.retromusic.Constants.baseProjection import code.name.monkey.retromusic.Constants.baseProjection
import code.name.monkey.retromusic.extensions.getLong import code.name.monkey.retromusic.extensions.getLong
import code.name.monkey.retromusic.extensions.getString
import code.name.monkey.retromusic.extensions.getStringOrNull import code.name.monkey.retromusic.extensions.getStringOrNull
import code.name.monkey.retromusic.model.Genre import code.name.monkey.retromusic.model.Genre
import code.name.monkey.retromusic.model.Song import code.name.monkey.retromusic.model.Song
import code.name.monkey.retromusic.util.PreferenceUtil import code.name.monkey.retromusic.util.PreferenceUtil
interface GenreRepository { interface GenreRepository {
fun genres(query: String): List<Genre>
fun genres(): List<Genre> fun genres(): List<Genre>
fun songs(genreId: Long): List<Song> fun songs(genreId: Long): List<Song>
@ -41,6 +41,10 @@ class RealGenreRepository(
private val songRepository: RealSongRepository private val songRepository: RealSongRepository
) : GenreRepository { ) : GenreRepository {
override fun genres(query: String): List<Genre> {
return getGenresFromCursor(makeGenreCursor(query))
}
override fun genres(): List<Genre> { override fun genres(): List<Genre> {
return getGenresFromCursor(makeGenreCursor()) return getGenresFromCursor(makeGenreCursor())
} }
@ -57,18 +61,23 @@ class RealGenreRepository(
return songRepository.song(makeGenreSongCursor(genreId)) return songRepository.song(makeGenreSongCursor(genreId))
} }
private fun getSongCount(genreId: Long): Int {
contentResolver.query(
Genres.Members.getContentUri("external", genreId),
null,
null,
null,
null
).use {
return it?.count ?: 0
}
}
private fun getGenreFromCursor(cursor: Cursor): Genre { private fun getGenreFromCursor(cursor: Cursor): Genre {
val id = cursor.getLong(Genres._ID) val id = cursor.getLong(Genres._ID)
val name = cursor.getStringOrNull(Genres.NAME) val name = cursor.getStringOrNull(Genres.NAME)
val songCount = songs(id).size val songCount = getSongCount(id)
return Genre(id, name ?: "", songCount) return Genre(id, name ?: "", songCount)
}
private fun getGenreFromCursorWithOutSongs(cursor: Cursor): Genre {
val id = cursor.getLong(Genres._ID)
val name = cursor.getString(Genres.NAME)
return Genre(id, name, -1)
} }
private fun getSongsWithNoGenre(): List<Song> { private fun getSongsWithNoGenre(): List<Song> {
@ -77,28 +86,6 @@ class RealGenreRepository(
return songRepository.songs(songRepository.makeSongCursor(selection, null)) return songRepository.songs(songRepository.makeSongCursor(selection, null))
} }
private fun hasSongsWithNoGenre(): Boolean {
val allSongsCursor = songRepository.makeSongCursor(null, null)
val allSongsWithGenreCursor = makeAllSongsWithGenreCursor()
if (allSongsCursor == null || allSongsWithGenreCursor == null) {
return false
}
val hasSongsWithNoGenre = allSongsCursor.count > allSongsWithGenreCursor.count
allSongsCursor.close()
allSongsWithGenreCursor.close()
return hasSongsWithNoGenre
}
private fun makeAllSongsWithGenreCursor(): Cursor? {
println(Genres.EXTERNAL_CONTENT_URI.toString())
return contentResolver.query(
Uri.parse("content://media/external/audio/genres/all/members"),
arrayOf(Genres.Members.AUDIO_ID), null, null, null
)
}
private fun makeGenreSongCursor(genreId: Long): Cursor? { private fun makeGenreSongCursor(genreId: Long): Cursor? {
return try { return try {
contentResolver.query( contentResolver.query(
@ -121,37 +108,13 @@ class RealGenreRepository(
val genre = getGenreFromCursor(cursor) val genre = getGenreFromCursor(cursor)
if (genre.songCount > 0) { if (genre.songCount > 0) {
genres.add(genre) genres.add(genre)
} else {
// try to remove the empty genre from the media store
try {
contentResolver.delete(
Genres.EXTERNAL_CONTENT_URI,
Genres._ID + " == " + genre.id,
null
)
} catch (e: Exception) {
e.printStackTrace()
}
} }
} while (cursor.moveToNext()) } while (cursor.moveToNext())
} }
cursor.close()
} }
return genres return genres
} }
private fun getGenresFromCursorForSearch(cursor: Cursor?): List<Genre> {
val genres = mutableListOf<Genre>()
if (cursor != null && cursor.moveToFirst()) {
do {
genres.add(getGenreFromCursorWithOutSongs(cursor))
} while (cursor.moveToNext())
}
cursor?.close()
return genres
}
private fun makeGenreCursor(): Cursor? { private fun makeGenreCursor(): Cursor? {
val projection = arrayOf(Genres._ID, Genres.NAME) val projection = arrayOf(Genres._ID, Genres.NAME)
return try { return try {
@ -166,4 +129,19 @@ class RealGenreRepository(
return null return null
} }
} }
private fun makeGenreCursor(query: String): Cursor? {
val projection = arrayOf(Genres._ID, Genres.NAME)
return try {
contentResolver.query(
Genres.EXTERNAL_CONTENT_URI,
projection,
Genres.NAME + " = ?",
arrayOf(query),
PreferenceUtil.genreSortOrder
)
} catch (e: SecurityException) {
return null
}
}
} }

View file

@ -16,6 +16,7 @@ package code.name.monkey.retromusic.repository
import android.content.Context import android.content.Context
import code.name.monkey.retromusic.R import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.db.PlaylistEntity
import code.name.monkey.retromusic.fragments.search.Filter import code.name.monkey.retromusic.fragments.search.Filter
import code.name.monkey.retromusic.model.Album import code.name.monkey.retromusic.model.Album
import code.name.monkey.retromusic.model.Artist import code.name.monkey.retromusic.model.Artist
@ -29,20 +30,23 @@ class RealSearchRepository(
private val roomRepository: RoomRepository, private val roomRepository: RoomRepository,
private val genreRepository: GenreRepository, private val genreRepository: GenreRepository,
) { ) {
fun searchAll(context: Context, query: String?, filter: Filter): MutableList<Any> { suspend fun searchAll(context: Context, query: String?, filter: Filter): MutableList<Any> {
val results = mutableListOf<Any>() val results = mutableListOf<Any>()
if (query.isNullOrEmpty()) return results if (query.isNullOrEmpty()) return results
query.let { searchString -> query.let { searchString ->
/** Songs **/
val songs: List<Song> = if (filter == Filter.SONGS || filter == Filter.NO_FILTER) { val songs: List<Song> = if (filter == Filter.SONGS || filter == Filter.NO_FILTER) {
songRepository.songs(searchString) songRepository.songs(searchString)
} else { } else {
emptyList() emptyList()
} }
if (songs.isNotEmpty()) { if (songs.isNotEmpty()) {
results.add(context.resources.getString(R.string.songs)) results.add(context.resources.getString(R.string.songs))
results.addAll(songs) results.addAll(songs)
} }
/** Artists **/
val artists: List<Artist> = val artists: List<Artist> =
if (filter == Filter.ARTISTS || filter == Filter.NO_FILTER) { if (filter == Filter.ARTISTS || filter == Filter.NO_FILTER) {
artistRepository.artists(searchString) artistRepository.artists(searchString)
@ -53,6 +57,8 @@ class RealSearchRepository(
results.add(context.resources.getString(R.string.artists)) results.add(context.resources.getString(R.string.artists))
results.addAll(artists) results.addAll(artists)
} }
/** Albums **/
val albums: List<Album> = if (filter == Filter.ALBUMS || filter == Filter.NO_FILTER) { val albums: List<Album> = if (filter == Filter.ALBUMS || filter == Filter.NO_FILTER) {
albumRepository.albums(searchString) albumRepository.albums(searchString)
} else { } else {
@ -62,6 +68,8 @@ class RealSearchRepository(
results.add(context.resources.getString(R.string.albums)) results.add(context.resources.getString(R.string.albums))
results.addAll(albums) results.addAll(albums)
} }
/** Album-Artists **/
val albumArtists: List<Artist> = val albumArtists: List<Artist> =
if (filter == Filter.ALBUM_ARTISTS || filter == Filter.NO_FILTER) { if (filter == Filter.ALBUM_ARTISTS || filter == Filter.NO_FILTER) {
artistRepository.albumArtists(searchString) artistRepository.albumArtists(searchString)
@ -72,11 +80,10 @@ class RealSearchRepository(
results.add(context.resources.getString(R.string.album_artist)) results.add(context.resources.getString(R.string.album_artist))
results.addAll(albumArtists) results.addAll(albumArtists)
} }
/** Genres **/
val genres: List<Genre> = if (filter == Filter.GENRES || filter == Filter.NO_FILTER) { val genres: List<Genre> = if (filter == Filter.GENRES || filter == Filter.NO_FILTER) {
genreRepository.genres().filter { genre -> genreRepository.genres(query)
genre.name.lowercase()
.contains(searchString.lowercase())
}
} else { } else {
emptyList() emptyList()
} }
@ -84,14 +91,21 @@ class RealSearchRepository(
results.add(context.resources.getString(R.string.genres)) results.add(context.resources.getString(R.string.genres))
results.addAll(genres) results.addAll(genres)
} }
/* val playlist = roomRepository.playlists().filter { playlist ->
playlist.playlistName.toLowerCase(Locale.getDefault()) /** Playlists **/
.contains(searchString.toLowerCase(Locale.getDefault())) val playlist: List<PlaylistEntity> =
if (filter == Filter.PLAYLISTS || filter == Filter.NO_FILTER) {
roomRepository.playlists().filter { playlist ->
playlist.playlistName.lowercase().contains(searchString.lowercase())
} }
} else {
emptyList()
}
if (playlist.isNotEmpty()) { if (playlist.isNotEmpty()) {
results.add(context.getString(R.string.playlists)) results.add(context.getString(R.string.playlists))
results.addAll(playlist) results.addAll(playlist)
}*/ }
} }
return results return results
} }

View file

@ -30,6 +30,7 @@ import androidx.annotation.ColorInt;
import androidx.annotation.DrawableRes; import androidx.annotation.DrawableRes;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.core.content.res.ResourcesCompat;
import java.io.File; import java.io.File;
import java.io.FileOutputStream; import java.io.FileOutputStream;
@ -100,7 +101,7 @@ public class ImageUtil {
public static Drawable getVectorDrawable( public static Drawable getVectorDrawable(
@NonNull Resources res, @DrawableRes int resId, @Nullable Resources.Theme theme) { @NonNull Resources res, @DrawableRes int resId, @Nullable Resources.Theme theme) {
return res.getDrawable(resId, theme); return ResourcesCompat.getDrawable(res,resId, theme);
} }
/** Makes sure that {@code mTempBuffer} has at least length {@code size}. */ /** Makes sure that {@code mTempBuffer} has at least length {@code size}. */

View file

@ -35,7 +35,6 @@ import java.io.IOException
import java.security.MessageDigest import java.security.MessageDigest
import java.security.NoSuchAlgorithmException import java.security.NoSuchAlgorithmException
import java.util.* import java.util.*
import kotlin.collections.LinkedHashMap
/** /**
* Validates that the calling package is authorized to browse a [MediaBrowserServiceCompat]. * Validates that the calling package is authorized to browse a [MediaBrowserServiceCompat].

View file

@ -708,6 +708,9 @@ object PreferenceUtil {
val circlePlayButton val circlePlayButton
get() = sharedPreferences.getBoolean(CIRCLE_PLAY_BUTTON, false) get() = sharedPreferences.getBoolean(CIRCLE_PLAY_BUTTON, false)
val swipeAnywhereToChangeSong
get() = sharedPreferences.getBoolean(SWIPE_ANYWHERE_NOW_PLAYING, true)
} }
enum class LyricsType { enum class LyricsType {
REPLACE_COVER, OVER_COVER REPLACE_COVER, OVER_COVER

View file

@ -26,13 +26,6 @@ object ThemeManager {
fun getNightMode(): Int = when (App.getContext().generalThemeValue) { fun getNightMode(): Int = when (App.getContext().generalThemeValue) {
LIGHT -> AppCompatDelegate.MODE_NIGHT_NO LIGHT -> AppCompatDelegate.MODE_NIGHT_NO
DARK -> AppCompatDelegate.MODE_NIGHT_YES DARK -> AppCompatDelegate.MODE_NIGHT_YES
BLACK -> {
if (PreferenceUtil.baseTheme == "dark") {
AppCompatDelegate.MODE_NIGHT_YES
} else {
AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM
}
}
else -> AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM else -> AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM
} }
} }

View file

@ -222,7 +222,7 @@ public class SeekArc extends View {
* provides notifications of when the user starts and stops a touch gesture within the SeekArc. * provides notifications of when the user starts and stops a touch gesture within the SeekArc.
* *
* @param l The seek bar notification listener * @param l The seek bar notification listener
* @see SeekArc.OnSeekBarChangeListener * @see SeekArc.OnSeekArcChangeListener
*/ */
public void setOnSeekArcChangeListener(OnSeekArcChangeListener l) { public void setOnSeekArcChangeListener(OnSeekArcChangeListener l) {
mOnSeekArcChangeListener = l; mOnSeekArcChangeListener = l;

View file

@ -3,7 +3,6 @@ package code.name.monkey.retromusic.views.insets
import android.content.Context import android.content.Context
import android.util.AttributeSet import android.util.AttributeSet
import android.widget.LinearLayout import android.widget.LinearLayout
import androidx.constraintlayout.widget.ConstraintLayout
import code.name.monkey.retromusic.extensions.drawAboveSystemBarsWithPadding import code.name.monkey.retromusic.extensions.drawAboveSystemBarsWithPadding
import code.name.monkey.retromusic.util.RetroUtil import code.name.monkey.retromusic.util.RetroUtil

View file

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<code.name.monkey.retromusic.views.insets.InsetsConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
@ -83,14 +83,16 @@
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/albumRecyclerView"/> app:layout_constraintTop_toBottomOf="@id/albumRecyclerView"/>
<ImageButton <com.google.android.material.button.MaterialButton
android:id="@+id/song_sort_order" android:id="@+id/song_sort_order"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginEnd="16dp" android:layout_marginEnd="16dp"
android:background="@null" style="@style/Widget.Material3.Button.IconButton"
android:padding="8dp" app:iconTint="?colorControlNormal"
android:src="@drawable/ic_sort" app:iconSize="24dp"
android:background="?roundSelector"
app:icon="@drawable/ic_sort"
app:layout_constraintBottom_toBottomOf="@+id/songTitle" app:layout_constraintBottom_toBottomOf="@+id/songTitle"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/songTitle" app:layout_constraintStart_toEndOf="@id/songTitle"
@ -206,4 +208,4 @@
android:layout_height="72dp" android:layout_height="72dp"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/listeners" /> app:layout_constraintTop_toBottomOf="@id/listeners" />
</code.name.monkey.retromusic.views.insets.InsetsConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -26,14 +26,12 @@
android:id="@+id/progressSlider" android:id="@+id/progressSlider"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="8"
android:paddingVertical="@dimen/seekbar_padding" android:paddingVertical="@dimen/seekbar_padding"
android:splitTrack="false" android:splitTrack="false"
android:thumb="@drawable/switch_square" android:thumb="@drawable/switch_square"
app:layout_constraintEnd_toStartOf="@id/songTotalTime" app:layout_constraintEnd_toStartOf="@id/songTotalTime"
app:layout_constraintStart_toEndOf="@id/songCurrentProgress" app:layout_constraintStart_toEndOf="@id/songCurrentProgress"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
tools:ignore="RtlHardcoded,UnusedAttribute"
tools:progress="20" /> tools:progress="20" />
<com.google.android.material.textview.MaterialTextView <com.google.android.material.textview.MaterialTextView

View file

@ -117,6 +117,13 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@string/genres" /> android:text="@string/genres" />
<com.google.android.material.chip.Chip
android:id="@+id/chip_playlists"
style="@style/SearchChipStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/playlists" />
</com.google.android.material.chip.ChipGroup> </com.google.android.material.chip.ChipGroup>
</HorizontalScrollView> </HorizontalScrollView>

View file

@ -6,6 +6,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:clickable="true" android:clickable="true"
android:focusable="true" android:focusable="true"
android:background="?rectSelector"
android:transitionGroup="true"> android:transitionGroup="true">
<FrameLayout <FrameLayout
android:id="@+id/dummy_view" android:id="@+id/dummy_view"

View file

@ -347,6 +347,7 @@
<string name="pref_summary_remember_tab">Navigate to the last used tab on start</string> <string name="pref_summary_remember_tab">Navigate to the last used tab on start</string>
<string name="pref_summary_show_lyrics">Display synced lyrics over album cover</string> <string name="pref_summary_show_lyrics">Display synced lyrics over album cover</string>
<string name="pref_summary_suggestions">Show New Music Mix on homescreen</string> <string name="pref_summary_suggestions">Show New Music Mix on homescreen</string>
<string name="pref_summary_swipe_anywhere_now_playing">Enables changing song by swiping anywhere on the now playing screen</string>
<string name="pref_summary_toggle_full_screen">Immersive mode</string> <string name="pref_summary_toggle_full_screen">Immersive mode</string>
<string name="pref_summary_toggle_headset">Start playing immediately after headphones are connected</string> <string name="pref_summary_toggle_headset">Start playing immediately after headphones are connected</string>
<string name="pref_summary_toggle_shuffle">Shuffle mode will turn off when playing a new list of songs</string> <string name="pref_summary_toggle_shuffle">Shuffle mode will turn off when playing a new list of songs</string>
@ -390,6 +391,7 @@
<string name="pref_title_remember_tab">Remember last tab</string> <string name="pref_title_remember_tab">Remember last tab</string>
<string name="pref_title_show_lyrics">Show lyrics</string> <string name="pref_title_show_lyrics">Show lyrics</string>
<string name="pref_title_suggestions">Show suggestions</string> <string name="pref_title_suggestions">Show suggestions</string>
<string name="pref_title_swipe_anywhere_now_playing">Swipe anywhere to change song</string>
<string name="pref_title_tab_text_mode">Tab titles mode</string> <string name="pref_title_tab_text_mode">Tab titles mode</string>
<string name="pref_title_toggle_carousel_effect">Carousel effect</string> <string name="pref_title_toggle_carousel_effect">Carousel effect</string>
<string name="pref_title_toggle_full_screen">Fullscreen app</string> <string name="pref_title_toggle_full_screen">Fullscreen app</string>

View file

@ -207,7 +207,6 @@
<item name="android:textSize">16sp</item> <item name="android:textSize">16sp</item>
<item name="checkedIconEnabled">true</item> <item name="checkedIconEnabled">true</item>
<item name="chipEndPadding">10dp</item> <item name="chipEndPadding">10dp</item>
<item name="chipIconEnabled">true</item>
<item name="chipMinHeight">40dp</item> <item name="chipMinHeight">40dp</item>
<item name="chipStartPadding">10dp</item> <item name="chipStartPadding">10dp</item>
</style> </style>

View file

@ -29,7 +29,7 @@
<item name="popupMenuBackground">@drawable/popup_background</item> <item name="popupMenuBackground">@drawable/popup_background</item>
</style> </style>
<style name="Theme.RetroMusic.Base.Black" parent="Theme.Material3.DayNight.NoActionBar"> <style name="Theme.RetroMusic.Base.Black" parent="Theme.Material3.Dark.NoActionBar">
<item name="roundSelector">@drawable/round_selector</item> <item name="roundSelector">@drawable/round_selector</item>
<item name="rectSelector">@drawable/rect_selector</item> <item name="rectSelector">@drawable/rect_selector</item>
<item name="materialAlertDialogTheme">@style/MaterialAlertDialogTheme</item> <item name="materialAlertDialogTheme">@style/MaterialAlertDialogTheme</item>

View file

@ -42,6 +42,13 @@
android:layout="@layout/list_item_view_switch_no_title" android:layout="@layout/list_item_view_switch_no_title"
android:title="@string/pref_title_circle_button" /> android:title="@string/pref_title_circle_button" />
<code.name.monkey.appthemehelper.common.prefs.supportv7.ATESwitchPreference
android:defaultValue="true"
android:key="swipe_anywhere_now_playing"
android:layout="@layout/list_item_view_switch"
android:summary="@string/pref_summary_swipe_anywhere_now_playing"
android:title="@string/pref_title_swipe_anywhere_now_playing" />
<code.name.monkey.appthemehelper.common.prefs.supportv7.ATEPreferenceCategory <code.name.monkey.appthemehelper.common.prefs.supportv7.ATEPreferenceCategory
android:layout="@layout/preference_category_title" android:layout="@layout/preference_category_title"
android:title="@string/pref_header_album"> android:title="@string/pref_header_album">