Merge branch 'dev' into reset_image

This commit is contained in:
Phani-22 2022-03-18 07:51:40 +05:30 committed by GitHub
commit 647e504f3d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
37 changed files with 384 additions and 120 deletions

View file

@ -14,8 +14,8 @@ android {
vectorDrawables.useSupportLibrary = true
applicationId "code.name.monkey.retromusic"
versionCode 10567
versionName '5.7.2'
versionCode 10569
versionName '5.7.3'
buildConfigField("String", "GOOGLE_PLAY_LICENSING_KEY", "\"${getProperty(getProperties('../public.properties'), 'GOOGLE_PLAY_LICENSE_KEY')}\"")
}
@ -93,7 +93,7 @@ dependencies {
implementation "androidx.appcompat:appcompat:$appcompat_version"
implementation 'androidx.annotation:annotation:1.3.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
implementation 'androidx.recyclerview:recyclerview:1.3.0-alpha01'
implementation 'androidx.recyclerview:recyclerview:1.2.1'
implementation "androidx.preference:preference-ktx:$preference_version"
implementation 'androidx.core:core-ktx:1.7.0'
implementation 'androidx.palette:palette-ktx:1.0.0'
@ -126,7 +126,7 @@ dependencies {
def retrofit_version = '2.9.0'
implementation "com.squareup.retrofit2:retrofit:$retrofit_version"
implementation "com.squareup.retrofit2:converter-gson:$retrofit_version"
implementation 'com.squareup.okhttp3:logging-interceptor:5.0.0-alpha.5'
implementation 'com.squareup.okhttp3:logging-interceptor:5.0.0-alpha.6'
def material_dialog_version = "3.3.0"
implementation "com.afollestad.material-dialogs:core:$material_dialog_version"

View file

@ -62,6 +62,22 @@
</head>
<body>
<div>
<h5>March 13, 2022</h5>
<h2>v5.7.3</h2>
<h3>What's New</h3>
<ul>
<li>Added adaptive color in Material now playing theme</li>
<li>Added an option to share crash report</li>
<li>Added options to clear, pause history</li>
</ul>
<h3>Fixed</h3>
<ul>
<li>Adapt Wallpaper accent for better readability</li>
<li>Optimized search</li>
<li>Made sleep timer precise</li>
</ul>
</div>
<div>
<h5>February 13, 2022</h5>
<h2>v5.7.2<span class="tag"><i>Beta</i></span></h2>

View file

@ -164,3 +164,4 @@ const val WALLPAPER_ACCENT = "wallpaper_accent"
const val SCREEN_ON_LYRICS = "screen_on_lyrics"
const val CIRCLE_PLAY_BUTTON = "circle_play_button"
const val SWIPE_ANYWHERE_NOW_PLAYING = "swipe_anywhere_now_playing"
const val PAUSE_HISTORY = "pause_history"

View file

@ -31,6 +31,7 @@ import code.name.monkey.retromusic.service.MusicService.Companion.PLAY_STATE_CHA
import code.name.monkey.retromusic.service.MusicService.Companion.QUEUE_CHANGED
import code.name.monkey.retromusic.service.MusicService.Companion.REPEAT_MODE_CHANGED
import code.name.monkey.retromusic.service.MusicService.Companion.SHUFFLE_MODE_CHANGED
import code.name.monkey.retromusic.util.PreferenceUtil
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import org.koin.android.ext.android.inject
@ -123,8 +124,11 @@ abstract class AbsMusicServiceActivity : AbsBaseActivity(), IMusicServiceEventLi
if (entity != null) {
repository.updateHistorySong(MusicPlayerRemote.currentSong)
} else {
// Check whether pause history option is ON or OFF
if (!PreferenceUtil.pauseHistory) {
repository.addSongToHistory(MusicPlayerRemote.currentSong)
}
}
val songs = repository.checkSongExistInPlayCount(MusicPlayerRemote.currentSong.id)
if (songs.isNotEmpty()) {
repository.updateSongInPlayCount(songs.first().apply {

View file

@ -35,7 +35,7 @@ import kotlinx.coroutines.withContext
import java.io.File
class LibraryViewModel(
private val repository: RealRepository
private val repository: RealRepository,
) : ViewModel(), IMusicServiceEventListener {
private val _paletteColor = MutableLiveData<Int>()
@ -50,6 +50,7 @@ class LibraryViewModel(
private val searchResults = MutableLiveData<List<Any>>()
private val fabMargin = MutableLiveData(0)
private val songHistory = MutableLiveData<List<Song>>()
private var previousSongHistory = ArrayList<HistoryEntity>()
val paletteColor: LiveData<Int> = _paletteColor
init {
@ -143,12 +144,11 @@ class LibraryViewModel(
suggestions.postValue(repository.suggestions())
}
fun search(query: String?, filter: Filter) {
fun search(query: String?, filter: Filter) =
viewModelScope.launch(IO) {
val result =repository.search(query, filter)
searchResults.postValue(result)
}
}
fun forceReload(reloadType: ReloadType) = viewModelScope.launch(IO) {
when (reloadType) {
@ -342,11 +342,27 @@ class LibraryViewModel(
fun clearHistory() {
viewModelScope.launch(IO) {
previousSongHistory = repository.historySong() as ArrayList<HistoryEntity>
repository.clearSongHistory()
}
songHistory.value = emptyList()
}
fun restoreHistory() {
viewModelScope.launch(IO) {
if (previousSongHistory.isNotEmpty()) {
val history = ArrayList<Song>()
for (song in previousSongHistory) {
repository.addSongToHistory(song.toSong())
history.add(song.toSong())
}
songHistory.postValue(history)
}
}
}
fun favorites() = repository.favorites()
fun clearSearchResult() {
@ -363,6 +379,14 @@ class LibraryViewModel(
createPlaylist(PlaylistEntity(playlistName = playlistName))
insertSongs(songs.map { it.toSongEntity(playlistId) })
forceReload(Playlists)
withContext(Main) {
Toast.makeText(
App.getContext(),
App.getContext()
.getString(R.string.playlist_created_sucessfully, playlistName),
Toast.LENGTH_SHORT
).show()
}
} else {
val playlist = playlists.firstOrNull()
if (playlist != null) {
@ -370,21 +394,13 @@ class LibraryViewModel(
it.toSongEntity(playListId = playlist.playListId)
})
}
}
withContext(Main) {
Toast.makeText(
App.getContext(),
"Playlist already exists",
Toast.LENGTH_SHORT
).show()
if (songs.isNotEmpty()) {
Toast.makeText(
App.getContext(),
"Adding songs to $playlistName",
Toast.LENGTH_SHORT
).show()
}
}
Toast.makeText(App.getContext(), App.getContext().getString(
R.string.added_song_count_to_playlist,
songs.size,
playlistName
), Toast.LENGTH_SHORT).show()
}
}
}

View file

@ -80,6 +80,7 @@ import kotlinx.coroutines.withContext
import org.koin.android.ext.android.get
import org.koin.androidx.viewmodel.ext.android.viewModel
import org.koin.core.parameter.parametersOf
import java.text.Collator
class AlbumDetailsFragment : AbsMainActivityFragment(R.layout.fragment_album_details),
IAlbumClickListener, ICabHolder {
@ -437,15 +438,13 @@ class AlbumDetailsFragment : AbsMainActivityFragment(R.layout.fragment_album_det
o2.trackNumber
)
}
SONG_A_Z -> album.songs.sortedWith { o1, o2 ->
o1.title.compareTo(
o2.title
)
SONG_A_Z -> {
val collator = Collator.getInstance()
album.songs.sortedWith { o1, o2 -> collator.compare(o1.title, o2.title) }
}
SONG_Z_A -> album.songs.sortedWith { o1, o2 ->
o2.title.compareTo(
o1.title
)
SONG_Z_A -> {
val collator = Collator.getInstance()
album.songs.sortedWith { o1, o2 -> collator.compare(o2.title, o1.title) }
}
SONG_DURATION -> album.songs.sortedWith { o1, o2 ->
o1.duration.compareTo(

View file

@ -187,7 +187,7 @@ class HomeFragment :
}
GlideApp.with(requireActivity())
.load(RetroGlideExtension.getUserModel())
.userProfileOptions(RetroGlideExtension.getUserModel())
.userProfileOptions(RetroGlideExtension.getUserModel(), requireContext())
.into(binding.userImage)
}

View file

@ -14,6 +14,7 @@
*/
package code.name.monkey.retromusic.fragments.other
import android.graphics.Color
import android.os.Bundle
import android.view.Menu
import android.view.MenuInflater
@ -22,6 +23,7 @@ import android.view.View
import androidx.activity.addCallback
import androidx.core.os.bundleOf
import androidx.core.view.doOnPreDraw
import androidx.core.view.isVisible
import androidx.navigation.fragment.FragmentNavigatorExtras
import androidx.navigation.fragment.findNavController
import androidx.navigation.fragment.navArgs
@ -51,8 +53,10 @@ import com.afollestad.materialcab.attached.destroy
import com.afollestad.materialcab.attached.isActive
import com.afollestad.materialcab.createCab
import com.google.android.material.shape.MaterialShapeDrawable
import com.google.android.material.snackbar.Snackbar
import com.google.android.material.transition.MaterialSharedAxis
class DetailListFragment : AbsMainActivityFragment(R.layout.fragment_playlist_detail),
IArtistClickListener, IAlbumClickListener, ICabHolder {
private val args by navArgs<DetailListFragmentArgs>()
@ -162,9 +166,12 @@ class DetailListFragment : AbsMainActivityFragment(R.layout.fragment_playlist_de
adapter = songAdapter
layoutManager = linearLayoutManager()
}
libraryViewModel.observableHistorySongs().observe(viewLifecycleOwner) {
songAdapter.swapDataSet(it)
binding.empty.isVisible = it.isEmpty()
}
}
private fun loadFavorite() {
@ -236,6 +243,7 @@ class DetailListFragment : AbsMainActivityFragment(R.layout.fragment_playlist_de
return if (RetroUtil.isLandscape()) 4 else 2
}
override fun onArtist(artistId: Long, view: View) {
findNavController().navigate(
R.id.artistDetailsFragment,
@ -305,11 +313,24 @@ class DetailListFragment : AbsMainActivityFragment(R.layout.fragment_playlist_de
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
R.id.action_clear_history -> libraryViewModel.clearHistory()
/*
TODO("Show a snackbar showing that history has been successfully
cleared and that will have an undo button")
*/
R.id.action_clear_history -> {
if (binding.recyclerView.adapter?.itemCount!! > 0) {
libraryViewModel.clearHistory()
val snackBar =
Snackbar.make(binding.container,
getString(R.string.history_cleared),
Snackbar.LENGTH_LONG)
.setAction(getString(R.string.history_undo_button)) {
libraryViewModel.restoreHistory()
}
.setActionTextColor(Color.YELLOW)
val snackBarView = snackBar.view
snackBarView.translationY =
-(resources.getDimension(R.dimen.mini_player_height))
snackBar.show()
}
}
}
return false
}

View file

@ -167,7 +167,7 @@ class UserInfoFragment : Fragment() {
}
GlideApp.with(this)
.load(RetroGlideExtension.getUserModel())
.userProfileOptions(RetroGlideExtension.getUserModel())
.userProfileOptions(RetroGlideExtension.getUserModel(), requireContext())
.into(binding.userImage)
}

View file

@ -14,6 +14,9 @@
*/
package code.name.monkey.retromusic.fragments.player.material
import android.animation.ArgbEvaluator
import android.animation.ValueAnimator
import android.graphics.drawable.GradientDrawable
import android.os.Bundle
import android.view.View
import androidx.appcompat.widget.Toolbar
@ -22,12 +25,16 @@ import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.databinding.FragmentMaterialBinding
import code.name.monkey.retromusic.extensions.colorControlNormal
import code.name.monkey.retromusic.extensions.drawAboveSystemBars
import code.name.monkey.retromusic.extensions.surfaceColor
import code.name.monkey.retromusic.fragments.base.AbsPlayerFragment
import code.name.monkey.retromusic.fragments.player.PlayerAlbumCoverFragment
import code.name.monkey.retromusic.fragments.player.normal.PlayerFragment
import code.name.monkey.retromusic.helper.MusicPlayerRemote
import code.name.monkey.retromusic.model.Song
import code.name.monkey.retromusic.util.PreferenceUtil
import code.name.monkey.retromusic.util.ViewUtil
import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
import code.name.monkey.retromusic.views.DrawableGradient
/**
* @author Hemanth S (h4h13).
@ -48,6 +55,33 @@ class MaterialFragment : AbsPlayerFragment(R.layout.fragment_material) {
private var _binding: FragmentMaterialBinding? = null
private val binding get() = _binding!!
private var valueAnimator: ValueAnimator? = null
private fun colorize(i: Int) {
if (valueAnimator != null) {
valueAnimator?.cancel()
}
valueAnimator = ValueAnimator.ofObject(
ArgbEvaluator(),
surfaceColor(),
i
)
valueAnimator?.addUpdateListener { animation ->
if (isAdded) {
val drawable = DrawableGradient(
GradientDrawable.Orientation.TOP_BOTTOM,
intArrayOf(
animation.animatedValue as Int,
surfaceColor()
), 0
)
binding.colorGradientBackground.background = drawable
}
}
valueAnimator?.setDuration(ViewUtil.RETRO_MUSIC_ANIM_TIME.toLong())?.start()
}
override fun onShow() {
playbackControlsFragment.show()
@ -74,6 +108,10 @@ class MaterialFragment : AbsPlayerFragment(R.layout.fragment_material) {
colorControlNormal(),
requireActivity()
)
if (PreferenceUtil.isAdaptiveColor) {
colorize(color.backgroundColor)
}
}
override fun toggleFavorite(song: Song) {

View file

@ -46,6 +46,7 @@ import com.google.android.material.chip.ChipGroup
import com.google.android.material.shape.MaterialShapeDrawable
import com.google.android.material.textfield.TextInputEditText
import com.google.android.material.transition.MaterialFadeThrough
import kotlinx.coroutines.Job
import net.yslibrary.android.keyboardvisibilityevent.KeyboardVisibilityEvent
import java.util.*
@ -63,6 +64,8 @@ class SearchFragment : AbsMainActivityFragment(R.layout.fragment_search), TextWa
private lateinit var searchAdapter: SearchAdapter
private var query: String? = null
private var job: Job? = null
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
enterTransition = MaterialFadeThrough().addTarget(view)
@ -184,7 +187,8 @@ class SearchFragment : AbsMainActivityFragment(R.layout.fragment_search), TextWa
binding.voiceSearch.isGone = query.isNotEmpty()
binding.clearText.isVisible = query.isNotEmpty()
val filter = getFilter()
libraryViewModel.search(query, filter)
job?.cancel()
job = libraryViewModel.search(query, filter)
}
private fun getFilter(): Filter {

View file

@ -1,5 +1,6 @@
package code.name.monkey.retromusic.glide
import android.content.Context
import android.graphics.drawable.Drawable
import code.name.monkey.appthemehelper.ThemeStore.Companion.accentColor
import code.name.monkey.appthemehelper.util.TintHelper
@ -150,10 +151,11 @@ object RetroGlideExtension {
@GlideOption
fun userProfileOptions(
baseRequestOptions: BaseRequestOptions<*>,
file: File
file: File,
context: Context
): BaseRequestOptions<*> {
return baseRequestOptions.diskCacheStrategy(DEFAULT_DISK_CACHE_STRATEGY)
.error(getErrorUserProfile())
.error(getErrorUserProfile(context))
.signature(createSignature(file))
}
@ -201,11 +203,11 @@ object RetroGlideExtension {
return File(dir, USER_BANNER)
}
private fun getErrorUserProfile(): Drawable {
private fun getErrorUserProfile(context: Context): Drawable {
return TintHelper.createTintedDrawable(
getContext(),
R.drawable.ic_account,
accentColor(getContext())
accentColor(context)
)
}

View file

@ -43,9 +43,7 @@ class WallpaperAccentManager(val context: Context) {
.getWallpaperColors(WallpaperManager.FLAG_SYSTEM)
if (colors != null) {
val primaryColor = colors.primaryColor.toArgb()
if (primaryColor != ThemeStore.wallpaperColor(context)) {
ThemeStore.editTheme(context).wallpaperColor(primaryColor).commit()
}
ThemeStore.editTheme(context).wallpaperColor(context, primaryColor).commit()
}
}
}

View file

@ -17,6 +17,7 @@ package code.name.monkey.retromusic.model
import code.name.monkey.retromusic.helper.SortOrder
import code.name.monkey.retromusic.util.MusicUtil
import code.name.monkey.retromusic.util.PreferenceUtil
import java.text.Collator
data class Artist(
val id: Long,
@ -60,22 +61,18 @@ data class Artist(
get() = albums.flatMap { it.songs }
val sortedSongs: List<Song>
get() = songs.sortedWith(
get() {
val collator = Collator.getInstance()
return songs.sortedWith(
when (PreferenceUtil.artistDetailSongSortOrder) {
SortOrder.ArtistSongSortOrder.SONG_A_Z -> { o1, o2 ->
o1.title.compareTo(
o2.title
)
collator.compare(o1.title, o2.title)
}
SortOrder.ArtistSongSortOrder.SONG_Z_A -> { o1, o2 ->
o2.title.compareTo(
o1.title
)
collator.compare(o2.title, o1.title)
}
SortOrder.ArtistSongSortOrder.SONG_ALBUM -> { o1, o2 ->
o1.albumName.compareTo(
o2.albumName
)
collator.compare(o1.albumName, o2.albumName)
}
SortOrder.ArtistSongSortOrder.SONG_YEAR -> { o1, o2 ->
o2.year.compareTo(
@ -91,6 +88,7 @@ data class Artist(
throw IllegalArgumentException("invalid ${PreferenceUtil.artistDetailSongSortOrder}")
}
})
}
fun safeGetFirstAlbum(): Album {
return albums.firstOrNull() ?: Album.empty

View file

@ -19,6 +19,7 @@ import code.name.monkey.retromusic.helper.SortOrder
import code.name.monkey.retromusic.model.Album
import code.name.monkey.retromusic.model.Song
import code.name.monkey.retromusic.util.PreferenceUtil
import java.text.Collator
/**
@ -65,8 +66,7 @@ class RealAlbumRepository(private val songRepository: RealSongRepository) :
)
val songs = songRepository.songs(cursor)
val album = Album(albumId, songs)
sortAlbumSongs(album)
return album
return sortAlbumSongs(album)
}
// We don't need sorted list of songs (with sortAlbumSongs())
@ -74,23 +74,36 @@ class RealAlbumRepository(private val songRepository: RealSongRepository) :
fun splitIntoAlbums(
songs: List<Song>
): List<Album> {
return if (PreferenceUtil.albumSortOrder != SortOrder.AlbumSortOrder.ALBUM_NUMBER_OF_SONGS) songs.groupBy { it.albumId }
.map { Album(it.key, it.value) }
// We can't sort Album with the help of MediaStore so a hack
else songs.groupBy { it.albumId }.map { Album(it.key, it.value) }
.sortedByDescending { it.songCount }
val grouped = songs.groupBy { it.albumId }.map { Album(it.key, it.value) }
val collator = Collator.getInstance()
return when (PreferenceUtil.albumSortOrder) {
SortOrder.AlbumSortOrder.ALBUM_A_Z -> {
grouped.sortedWith { a1, a2 -> collator.compare(a1.title, a2.title) }
}
SortOrder.AlbumSortOrder.ALBUM_Z_A -> {
grouped.sortedWith { a1, a2 -> collator.compare(a2.title, a1.title) }
}
SortOrder.AlbumSortOrder.ALBUM_ARTIST -> {
grouped.sortedWith { a1, a2 -> collator.compare(a1.albumArtist, a2.albumArtist) }
}
SortOrder.AlbumSortOrder.ALBUM_NUMBER_OF_SONGS -> {
grouped.sortedByDescending { it.songCount }
}
else -> grouped
}
}
private fun sortAlbumSongs(album: Album): Album {
val collator = Collator.getInstance()
val songs = when (PreferenceUtil.albumDetailSongSortOrder) {
SortOrder.AlbumSongSortOrder.SONG_TRACK_LIST -> album.songs.sortedWith { o1, o2 ->
o1.trackNumber.compareTo(o2.trackNumber)
}
SortOrder.AlbumSongSortOrder.SONG_A_Z -> album.songs.sortedWith { o1, o2 ->
o1.title.compareTo(o2.title)
SortOrder.AlbumSongSortOrder.SONG_A_Z -> {
album.songs.sortedWith { o1, o2 -> collator.compare(o1.title, o2.title) }
}
SortOrder.AlbumSongSortOrder.SONG_Z_A -> album.songs.sortedWith { o1, o2 ->
o2.title.compareTo(o1.title)
SortOrder.AlbumSongSortOrder.SONG_Z_A -> {
album.songs.sortedWith { o1, o2 -> collator.compare(o2.title, o1.title) }
}
SortOrder.AlbumSongSortOrder.SONG_DURATION -> album.songs.sortedWith { o1, o2 ->
o1.duration.compareTo(o2.duration)

View file

@ -20,6 +20,7 @@ import code.name.monkey.retromusic.helper.SortOrder
import code.name.monkey.retromusic.model.Album
import code.name.monkey.retromusic.model.Artist
import code.name.monkey.retromusic.util.PreferenceUtil
import java.text.Collator
interface ArtistRepository {
fun artists(): List<Artist>
@ -103,7 +104,8 @@ class RealArtistRepository(
getSongLoaderSortOrder()
)
)
return splitIntoArtists(albumRepository.splitIntoAlbums(songs))
val artists = splitIntoArtists(albumRepository.splitIntoAlbums(songs))
return sortArtists(artists)
}
override fun albumArtists(): List<Artist> {
@ -115,7 +117,8 @@ class RealArtistRepository(
if (PreferenceUtil.artistSortOrder == SortOrder.ArtistSortOrder.ARTIST_A_Z) "" else " DESC"
)
)
return splitIntoAlbumArtists(albumRepository.splitIntoAlbums(songs))
val artists = splitIntoAlbumArtists(albumRepository.splitIntoAlbums(songs))
return sortArtists(artists)
}
override fun albumArtists(query: String): List<Artist> {
@ -126,7 +129,8 @@ class RealArtistRepository(
getSongLoaderSortOrder()
)
)
return splitIntoAlbumArtists(albumRepository.splitIntoAlbums(songs))
val artists = splitIntoAlbumArtists(albumRepository.splitIntoAlbums(songs))
return sortArtists(artists)
}
override fun artists(query: String): List<Artist> {
@ -137,7 +141,8 @@ class RealArtistRepository(
getSongLoaderSortOrder()
)
)
return splitIntoArtists(albumRepository.splitIntoAlbums(songs))
val artists = splitIntoArtists(albumRepository.splitIntoAlbums(songs))
return sortArtists(artists)
}
@ -165,4 +170,17 @@ class RealArtistRepository(
return albums.groupBy { it.artistId }
.map { Artist(it.key, it.value) }
}
private fun sortArtists(artists: List<Artist>): List<Artist> {
val collator = Collator.getInstance()
return when (PreferenceUtil.artistSortOrder) {
SortOrder.ArtistSortOrder.ARTIST_A_Z -> {
artists.sortedWith { a1, a2 -> collator.compare(a1.name, a2.name) }
}
SortOrder.ArtistSortOrder.ARTIST_Z_A -> {
artists.sortedWith { a1, a2 -> collator.compare(a2.name, a1.name) }
}
else -> artists
}
}
}

View file

@ -28,9 +28,11 @@ import code.name.monkey.retromusic.extensions.getInt
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.helper.SortOrder
import code.name.monkey.retromusic.model.Song
import code.name.monkey.retromusic.providers.BlacklistStore
import code.name.monkey.retromusic.util.PreferenceUtil
import java.text.Collator
/**
* Created by hemanths on 10/08/17.
@ -66,7 +68,28 @@ class RealSongRepository(private val context: Context) : SongRepository {
} while (cursor.moveToNext())
}
cursor?.close()
return songs
val collator = Collator.getInstance()
return when (PreferenceUtil.songSortOrder) {
SortOrder.SongSortOrder.SONG_A_Z -> {
songs.sortedWith{ s1, s2 -> collator.compare(s1.title, s2.title) }
}
SortOrder.SongSortOrder.SONG_Z_A -> {
songs.sortedWith{ s1, s2 -> collator.compare(s2.title, s1.title) }
}
SortOrder.SongSortOrder.SONG_ALBUM -> {
songs.sortedWith{ s1, s2 -> collator.compare(s1.albumName, s2.albumName) }
}
SortOrder.SongSortOrder.SONG_ALBUM_ARTIST -> {
songs.sortedWith{ s1, s2 -> collator.compare(s1.albumArtist, s2.albumArtist) }
}
SortOrder.SongSortOrder.SONG_ARTIST -> {
songs.sortedWith{ s1, s2 -> collator.compare(s1.artistName, s2.artistName) }
}
SortOrder.SongSortOrder.COMPOSER -> {
songs.sortedWith{ s1, s2 -> collator.compare(s1.composer, s2.composer) }
}
else -> songs
}
}
override fun song(cursor: Cursor?): Song {

View file

@ -125,8 +125,14 @@ class PlayingNotificationImpl24(
}
override fun updateMetadata(song: Song, onUpdate: () -> Unit) {
setContentTitle(song.title)
setContentText(
setContentTitle(
HtmlCompat.fromHtml(
"<b>" + song.title + "</b>",
HtmlCompat.FROM_HTML_MODE_LEGACY
)
)
setContentText(song.artistName)
setSubText(
HtmlCompat.fromHtml(
"<b>" + song.albumName + "</b>",
HtmlCompat.FROM_HTML_MODE_LEGACY
@ -169,10 +175,12 @@ class PlayingNotificationImpl24(
}
override fun onLoadCleared(placeholder: Drawable?) {
setLargeIcon(BitmapFactory.decodeResource(
setLargeIcon(
BitmapFactory.decodeResource(
context.resources,
R.drawable.default_audio_art
))
)
)
onUpdate()
}
})

View file

@ -637,6 +637,12 @@ object PreferenceUtil {
true
)
val pauseHistory: Boolean
get() = sharedPreferences.getBoolean(
PAUSE_HISTORY,
false
)
var audioFadeDuration
get() = sharedPreferences
.getInt(AUDIO_FADE_DURATION, 0)

View file

@ -49,7 +49,6 @@ import java.util.Collections;
import java.util.List;
import code.name.monkey.appthemehelper.util.TintHelper;
import code.name.monkey.appthemehelper.util.VersionUtils;
import code.name.monkey.retromusic.App;
public class RetroUtil {

View file

@ -17,12 +17,10 @@ package code.name.monkey.retromusic.util
import android.content.Context
import android.content.Intent
import android.net.Uri
import android.os.Build
import android.provider.BaseColumns
import android.provider.MediaStore
import android.provider.Settings
import android.widget.Toast
import androidx.annotation.RequiresApi
import code.name.monkey.appthemehelper.util.VersionUtils
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.model.Song

View file

@ -14,6 +14,15 @@
<include layout="@layout/shadow_statusbar_toolbar" />
<View
android:id="@+id/colorGradientBackground"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"

View file

@ -10,6 +10,15 @@
<include layout="@layout/shadow_statusbar_toolbar" />
<View
android:id="@+id/colorGradientBackground"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<FrameLayout
android:id="@+id/statusBarContainer"
android:layout_width="match_parent"

View file

@ -67,6 +67,7 @@
android:textAppearance="@style/TextViewHeadline5"
android:textColor="?android:attr/textColorSecondary"
tools:visibility="visible" />
</LinearLayout>
<com.google.android.material.progressindicator.CircularProgressIndicator

View file

@ -31,6 +31,8 @@
android:id="@android:id/icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingStart="0dp"
android:paddingEnd="16dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:tint="?attr/colorControlNormal"
@ -53,6 +55,8 @@
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="2dp"
android:paddingStart="0dp"
android:paddingEnd="16dp"
android:textAppearance="@style/TextViewNormal"
android:textColor="?android:attr/textColorSecondary"
app:layout_constrainedWidth="true"

View file

@ -12,7 +12,7 @@
~ See the GNU General Public License for more details.
-->
<resources xmlns:tools="http://schemas.android.com/tools">
<resources>
<style name="Theme.RetroMusic.Base.Adaptive" parent="Theme.Material3.DayNight.NoActionBar">
<item name="toolbarPopupTheme">@style/ThemeOverlay.AppCompat.Dark</item>

View file

@ -1,5 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<bool name="wallpaper_accent_enabled">true</bool>
<bool name="wallpaper_accent_visible">true</bool>
</resources>

View file

@ -12,7 +12,7 @@
~ See the GNU General Public License for more details.
-->
<resources xmlns:tools="http://schemas.android.com/tools">
<resources>
<style name="Theme.RetroMusic.Base.Adaptive" parent="Theme.Material3.DayNight.NoActionBar">
<item name="toolbarPopupTheme">@style/ThemeOverlay.AppCompat.Light</item>

View file

@ -4,6 +4,5 @@
<bool name="md3_enabled">true</bool>
<integer name="overScrollMode">0</integer>
<bool name="wallpaper_accent_enabled">false</bool>
<bool name="wallpaper_accent_visible">false</bool>
</resources>

View file

@ -356,6 +356,7 @@
<string name="pref_summary_toggle_volume">If enough space is available, show volume controls in the now playing screen</string>
<string name="pref_summary_wallpaper_accent">Extract accent color from wallpaper</string>
<string name="pref_summary_whitelist">Only show music from /Music Folder</string>
<string name="pref_summary_pause_history">When enabled, newly played songs won\'t show in history</string>
<string name="pref_title_album_art_on_lockscreen">Show album cover</string>
<string name="pref_title_album_artists_only">Navigate by Album Artist</string>
<string name="pref_title_album_cover_style">Album cover theme</string>
@ -402,6 +403,7 @@
<string name="pref_title_toggle_volume">Volume controls</string>
<string name="pref_title_wallpaper_accent">Wallpaper accent color</string>
<string name="pref_title_whitelist">Whitelist music</string>
<string name="pref_title_pause_history">Pause history</string>
<string name="pro">Pro</string>
<string name="pro_summary">Black theme, Now playing themes, Carousel effect and more..</string>
<string name="profile">Profile</string>
@ -544,6 +546,11 @@
<string name="you_will_be_forwarded_to_the_issue_tracker_website">You will be forwarded to the issue tracker website.</string>
<string name="your_account_data_is_only_used_for_authentication">Your account data is only used for authentication.</string>
<string name="customactivityoncrash_error_activity_error_details_share">Share Crash Report</string>
<string name="playlist_created_sucessfully">%s created successfully</string>
<string name="playList_already_exits">Playlist already exists</string>
<string name="added_song_count_to_playlist">Added %d song(s) to %s</string>
<string name="history_cleared">History cleared</string>
<string name="history_undo_button">Undo</string>
<string name="choose_image">Choose Image</string>
<string name="remove_image">Remove Image</string>
</resources>

View file

@ -211,7 +211,7 @@
<style name="SearchChipStyle" parent="Widget.Material3.Chip.Filter">
<item name="android:checked">false</item>
<item name="android:textSize">16sp</item>
<item name="checkedIconEnabled">true</item>
<item name="checkedIconVisible">false</item>
<item name="chipEndPadding">10dp</item>
<item name="chipMinHeight">40dp</item>
<item name="chipStartPadding">10dp</item>

View file

@ -48,8 +48,7 @@
android:key="wallpaper_accent"
android:layout="@layout/list_item_view_switch"
android:summary="@string/pref_summary_wallpaper_accent"
android:title="@string/pref_title_wallpaper_accent"
app:isPreferenceVisible="@bool/wallpaper_accent_visible" />
android:title="@string/pref_title_wallpaper_accent" />
<code.name.monkey.appthemehelper.common.prefs.supportv7.ATEColorPreference
android:dependency="material_you"

View file

@ -40,6 +40,13 @@
android:summary="@string/pref_summary_suggestions"
android:title="@string/pref_title_suggestions" />
<code.name.monkey.appthemehelper.common.prefs.supportv7.ATESwitchPreference
android:defaultValue="false"
android:key="pause_history"
android:layout="@layout/list_item_view_switch"
android:summary="@string/pref_summary_pause_history"
android:title="@string/pref_title_pause_history" />
</code.name.monkey.appthemehelper.common.prefs.supportv7.ATEPreferenceCategory>
<code.name.monkey.appthemehelper.common.prefs.supportv7.ATEPreferenceCategory

View file

@ -59,8 +59,26 @@ private constructor(private val mContext: Context) : ThemeStorePrefKeys, ThemeSt
return this
}
override fun wallpaperColor(color: Int): ThemeStore {
mEditor.putInt(ThemeStorePrefKeys.KEY_WALLPAPER_COLOR, color)
override fun wallpaperColor(context: Context, color: Int): ThemeStore {
if (ColorUtil.isColorLight(color)) {
mEditor.putInt(ThemeStorePrefKeys.KEY_WALLPAPER_COLOR_DARK, color)
mEditor.putInt(
ThemeStorePrefKeys.KEY_WALLPAPER_COLOR_LIGHT,
ColorUtil.getReadableColorLight(
color,
Color.WHITE
)
)
} else {
mEditor.putInt(ThemeStorePrefKeys.KEY_WALLPAPER_COLOR_LIGHT, color)
mEditor.putInt(
ThemeStorePrefKeys.KEY_WALLPAPER_COLOR_DARK,
ColorUtil.getReadableColorDark(
color,
Color.parseColor("#202124")
)
)
}
return this
}
@ -217,7 +235,7 @@ private constructor(private val mContext: Context) : ThemeStorePrefKeys, ThemeSt
}
val desaturatedColor = prefs(context).getBoolean("desaturated_color", false)
val color = if (isWallpaperAccentEnabled(context)) {
wallpaperColor(context)
wallpaperColor(context, isWindowBackgroundDark(context))
} else {
prefs(context).getInt(
ThemeStorePrefKeys.KEY_ACCENT_COLOR,
@ -232,9 +250,9 @@ private constructor(private val mContext: Context) : ThemeStorePrefKeys, ThemeSt
@CheckResult
@ColorInt
fun wallpaperColor(context: Context): Int {
fun wallpaperColor(context: Context, isDarkMode: Boolean): Int {
return prefs(context).getInt(
ThemeStorePrefKeys.KEY_WALLPAPER_COLOR,
if (isDarkMode) ThemeStorePrefKeys.KEY_WALLPAPER_COLOR_DARK else ThemeStorePrefKeys.KEY_WALLPAPER_COLOR_LIGHT,
resolveColor(context, R.attr.colorAccent, Color.parseColor("#263238"))
)
}

View file

@ -1,5 +1,6 @@
package code.name.monkey.appthemehelper
import android.content.Context
import androidx.annotation.AttrRes
import androidx.annotation.ColorInt
import androidx.annotation.ColorRes
@ -34,7 +35,7 @@ internal interface ThemeStoreInterface {
fun accentColor(@ColorInt color: Int): ThemeStore
fun wallpaperColor(@ColorInt color: Int): ThemeStore
fun wallpaperColor(context: Context, color: Int): ThemeStore
fun accentColorRes(@ColorRes colorRes: Int): ThemeStore

View file

@ -29,6 +29,7 @@ internal interface ThemeStorePrefKeys {
const val KEY_AUTO_GENERATE_PRIMARYDARK = "auto_generate_primarydark"
const val KEY_MATERIAL_YOU = "material_you"
const val KEY_WALLPAPER_COLOR = "wallpaper_color"
const val KEY_WALLPAPER_COLOR_LIGHT = "wallpaper_color_light"
const val KEY_WALLPAPER_COLOR_DARK = "wallpaper_color_dark"
}
}

View file

@ -3,7 +3,11 @@ package code.name.monkey.appthemehelper.util
import android.graphics.Color
import androidx.annotation.ColorInt
import androidx.annotation.FloatRange
import kotlin.math.*
import androidx.core.graphics.ColorUtils
import kotlin.math.abs
import kotlin.math.max
import kotlin.math.min
import kotlin.math.roundToInt
object ColorUtil {
fun desaturateColor(color: Int, ratio: Float): Int {
@ -44,6 +48,50 @@ object ColorUtil {
return shiftColor(color, 1.1f)
}
@ColorInt
fun lightenColor(
@ColorInt color: Int,
value: Float
): Int {
val hsl = FloatArray(3)
ColorUtils.colorToHSL(color, hsl)
hsl[2] += value
hsl[2] = hsl[2].coerceIn(0f, 1f)
return ColorUtils.HSLToColor(hsl)
}
@ColorInt
fun darkenColor(
@ColorInt color: Int,
value: Float
): Int {
val hsl = FloatArray(3)
ColorUtils.colorToHSL(color, hsl)
hsl[2] -= value
hsl[2] = hsl[2].coerceIn(0f, 1f)
return ColorUtils.HSLToColor(hsl)
}
@ColorInt
fun getReadableColorLight(@ColorInt color: Int, @ColorInt bgColor: Int): Int {
var foregroundColor = color
while (ColorUtils.calculateContrast(foregroundColor, bgColor) <= 3.0
) {
foregroundColor = darkenColor(foregroundColor, 0.1F)
}
return foregroundColor
}
@ColorInt
fun getReadableColorDark(@ColorInt color: Int, @ColorInt bgColor: Int): Int {
var foregroundColor = color
while (ColorUtils.calculateContrast(foregroundColor, bgColor) <= 3.0
) {
foregroundColor = lightenColor(foregroundColor, 0.1F)
}
return foregroundColor
}
fun isColorLight(@ColorInt color: Int): Boolean {
val darkness =
1 - (0.299 * Color.red(color) + 0.587 * Color.green(color) + 0.114 * Color.blue(color)) / 255