Add sorting to LibraryFragment
Add basic sorting to LibraryFragment.
This commit is contained in:
parent
aad42b5201
commit
37c52d9e5c
17 changed files with 227 additions and 174 deletions
10
AuxioTODO
10
AuxioTODO
|
@ -5,7 +5,6 @@ TODO:
|
|||
|
||||
/detail/
|
||||
|
||||
- Add genre detail
|
||||
- ? Implement Toolbar update functionality ?
|
||||
- ! Implement shared element transitions !
|
||||
|
||||
|
@ -24,11 +23,14 @@ TODO:
|
|||
|
||||
/library/
|
||||
|
||||
- ? Move into ViewPager ?
|
||||
- Sorting
|
||||
- Re-add albums/genres into a single adapter
|
||||
- Add highlighting to the current sortmode
|
||||
- Search
|
||||
- ? Show Artists, Albums, and Songs in search ?
|
||||
- Exit functionality
|
||||
- ? Show Artists, Albums, and Songs in search ?
|
||||
- ? Move into ViewPager ?
|
||||
- ! Move Adapter functionality to ListAdapter!
|
||||
|
||||
|
||||
To be added:
|
||||
/prefs/
|
||||
|
|
|
@ -15,7 +15,6 @@ import org.oxycblt.auxio.databinding.FragmentAlbumDetailBinding
|
|||
import org.oxycblt.auxio.detail.adapters.DetailSongAdapter
|
||||
import org.oxycblt.auxio.music.MusicViewModel
|
||||
import org.oxycblt.auxio.recycler.ClickListener
|
||||
import org.oxycblt.auxio.recycler.SortMode
|
||||
import org.oxycblt.auxio.theme.applyDivider
|
||||
import org.oxycblt.auxio.theme.toColor
|
||||
|
||||
|
@ -65,7 +64,7 @@ class AlbumDetailFragment : Fragment() {
|
|||
|
||||
// If the album was shown directly from LibraryFragment, Then enable the ability to
|
||||
// navigate upwards to the parent artist
|
||||
if (args.fromLibrary) {
|
||||
if (args.enableParentNav) {
|
||||
detailModel.navToParent.observe(viewLifecycleOwner) {
|
||||
if (it) {
|
||||
findNavController().navigate(
|
||||
|
@ -89,14 +88,7 @@ class AlbumDetailFragment : Fragment() {
|
|||
|
||||
// Then update the sort mode of the album adapter.
|
||||
songAdapter.submitList(
|
||||
detailModel.currentAlbum.value!!.songs.sortedWith(
|
||||
SortMode.songSortComparators.getOrDefault(
|
||||
mode,
|
||||
|
||||
// If any invalid value is given, just default to the normal sort order.
|
||||
compareByDescending { it.track }
|
||||
)
|
||||
)
|
||||
mode.getSortedSongList(detailModel.currentAlbum.value!!.songs)
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -16,7 +16,6 @@ import org.oxycblt.auxio.detail.adapters.DetailAlbumAdapter
|
|||
import org.oxycblt.auxio.music.Album
|
||||
import org.oxycblt.auxio.music.MusicViewModel
|
||||
import org.oxycblt.auxio.recycler.ClickListener
|
||||
import org.oxycblt.auxio.recycler.SortMode
|
||||
import org.oxycblt.auxio.theme.applyDivider
|
||||
import org.oxycblt.auxio.theme.toColor
|
||||
|
||||
|
@ -72,14 +71,7 @@ class ArtistDetailFragment : Fragment() {
|
|||
|
||||
// Then update the sort mode of the album adapter.
|
||||
albumAdapter.submitList(
|
||||
detailModel.currentArtist.value!!.albums.sortedWith(
|
||||
SortMode.albumSortComparators.getOrDefault(
|
||||
mode,
|
||||
|
||||
// If any invalid value is given, just default to the normal sort order.
|
||||
compareByDescending { it.year }
|
||||
)
|
||||
)
|
||||
mode.getSortedAlbumList(detailModel.currentArtist.value!!.albums)
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -16,7 +16,6 @@ import org.oxycblt.auxio.detail.adapters.DetailArtistAdapter
|
|||
import org.oxycblt.auxio.music.Artist
|
||||
import org.oxycblt.auxio.music.MusicViewModel
|
||||
import org.oxycblt.auxio.recycler.ClickListener
|
||||
import org.oxycblt.auxio.recycler.SortMode
|
||||
import org.oxycblt.auxio.theme.applyDivider
|
||||
import org.oxycblt.auxio.theme.toColor
|
||||
|
||||
|
@ -70,14 +69,7 @@ class GenreDetailFragment : Fragment() {
|
|||
|
||||
// Then update the sort mode of the artist adapter.
|
||||
albumAdapter.submitList(
|
||||
detailModel.currentGenre.value!!.artists.sortedWith(
|
||||
SortMode.artistSortComparators.getOrDefault(
|
||||
mode,
|
||||
|
||||
// If any invalid value is given, just default to the normal sort order.
|
||||
compareByDescending { it.name }
|
||||
)
|
||||
)
|
||||
mode.getSortedArtistList(detailModel.currentGenre.value!!.artists)
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -5,29 +5,24 @@ import android.util.Log
|
|||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.activityViewModels
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import org.oxycblt.auxio.MainFragmentDirections
|
||||
import org.oxycblt.auxio.R
|
||||
import org.oxycblt.auxio.databinding.FragmentLibraryBinding
|
||||
import org.oxycblt.auxio.library.adapters.AlbumAdapter
|
||||
import org.oxycblt.auxio.library.adapters.ArtistAdapter
|
||||
import org.oxycblt.auxio.library.adapters.GenreAdapter
|
||||
import org.oxycblt.auxio.music.Album
|
||||
import org.oxycblt.auxio.music.Artist
|
||||
import org.oxycblt.auxio.music.BaseModel
|
||||
import org.oxycblt.auxio.music.Genre
|
||||
import org.oxycblt.auxio.music.MusicViewModel
|
||||
import org.oxycblt.auxio.recycler.ClickListener
|
||||
import org.oxycblt.auxio.theme.SHOW_ALBUMS
|
||||
import org.oxycblt.auxio.theme.SHOW_ARTISTS
|
||||
import org.oxycblt.auxio.theme.SHOW_GENRES
|
||||
import org.oxycblt.auxio.theme.applyDivider
|
||||
|
||||
class LibraryFragment : Fragment() {
|
||||
|
||||
// FIXME: Temp value, remove when there are actual preferences
|
||||
private val libraryMode = SHOW_ARTISTS
|
||||
|
||||
private val musicModel: MusicViewModel by activityViewModels()
|
||||
private val libraryModel: LibraryViewModel by activityViewModels()
|
||||
|
||||
|
@ -38,34 +33,34 @@ class LibraryFragment : Fragment() {
|
|||
): View? {
|
||||
val binding = FragmentLibraryBinding.inflate(inflater)
|
||||
|
||||
binding.libraryRecycler.adapter = when (libraryMode) {
|
||||
SHOW_ARTISTS -> ArtistAdapter(
|
||||
musicModel.artists.value!!,
|
||||
ClickListener {
|
||||
navToArtist(it)
|
||||
}
|
||||
val artistAdapter = ArtistAdapter(
|
||||
ClickListener { navToItem(it) }
|
||||
)
|
||||
|
||||
SHOW_ALBUMS -> AlbumAdapter(
|
||||
musicModel.albums.value!!,
|
||||
ClickListener {
|
||||
navToAlbum(it)
|
||||
}
|
||||
)
|
||||
|
||||
SHOW_GENRES -> GenreAdapter(
|
||||
musicModel.genres.value!!,
|
||||
ClickListener {
|
||||
navToGenre(it)
|
||||
}
|
||||
)
|
||||
|
||||
else -> null
|
||||
}
|
||||
|
||||
binding.libraryRecycler.adapter = artistAdapter
|
||||
binding.libraryRecycler.applyDivider()
|
||||
binding.libraryRecycler.setHasFixedSize(true)
|
||||
|
||||
libraryModel.sortMode.observe(viewLifecycleOwner) { mode ->
|
||||
binding.libraryToolbar.overflowIcon = ContextCompat.getDrawable(
|
||||
requireContext(), mode.iconRes
|
||||
)
|
||||
|
||||
artistAdapter.updateData(
|
||||
mode.getSortedArtistList(
|
||||
musicModel.artists.value!!
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
binding.libraryToolbar.setOnMenuItemClickListener {
|
||||
libraryModel.updateSortMode(it)
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
binding.libraryToolbar.inflateMenu(R.menu.menu_library)
|
||||
|
||||
Log.d(this::class.simpleName, "Fragment created.")
|
||||
|
||||
return binding.root
|
||||
|
@ -77,39 +72,19 @@ class LibraryFragment : Fragment() {
|
|||
libraryModel.isAlreadyNavigating = false
|
||||
}
|
||||
|
||||
private fun navToArtist(artist: Artist) {
|
||||
// Dont navigate if an item has already been selected
|
||||
private fun navToItem(baseModel: BaseModel) {
|
||||
// Don't navigate if an item has already been selected
|
||||
if (!libraryModel.isAlreadyNavigating) {
|
||||
libraryModel.isAlreadyNavigating = true
|
||||
|
||||
findNavController().navigate(
|
||||
MainFragmentDirections.actionShowArtist(
|
||||
artist.id
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
when (baseModel) {
|
||||
is Genre -> MainFragmentDirections.actionShowGenre(baseModel.id)
|
||||
is Artist -> MainFragmentDirections.actionShowArtist(baseModel.id)
|
||||
is Album -> MainFragmentDirections.actionShowAlbum(baseModel.id, true)
|
||||
|
||||
private fun navToAlbum(album: Album) {
|
||||
if (!libraryModel.isAlreadyNavigating) {
|
||||
libraryModel.isAlreadyNavigating = true
|
||||
|
||||
findNavController().navigate(
|
||||
MainFragmentDirections.actionShowAlbum(
|
||||
album.id, true
|
||||
)
|
||||
)
|
||||
else -> return
|
||||
}
|
||||
}
|
||||
|
||||
private fun navToGenre(genre: Genre) {
|
||||
if (!libraryModel.isAlreadyNavigating) {
|
||||
libraryModel.isAlreadyNavigating = true
|
||||
|
||||
findNavController().navigate(
|
||||
MainFragmentDirections.actionShowGenre(
|
||||
genre.id
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,34 @@
|
|||
package org.oxycblt.auxio.library
|
||||
|
||||
import android.view.MenuItem
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import org.oxycblt.auxio.R
|
||||
import org.oxycblt.auxio.recycler.SortMode
|
||||
import org.oxycblt.auxio.theme.SHOW_ARTISTS
|
||||
|
||||
class LibraryViewModel : ViewModel() {
|
||||
var isAlreadyNavigating = false
|
||||
|
||||
// TODO: Move these to pref values when they're added
|
||||
private val mShowMode = MutableLiveData(SHOW_ARTISTS)
|
||||
val showMode: LiveData<Int> get() = mShowMode
|
||||
|
||||
private val mSortMode = MutableLiveData(SortMode.ALPHA_UP)
|
||||
val sortMode: LiveData<SortMode> get() = mSortMode
|
||||
|
||||
fun updateSortMode(item: MenuItem) {
|
||||
val mode = when (item.itemId) {
|
||||
R.id.sort_none -> SortMode.NONE
|
||||
R.id.sort_alpha_down -> SortMode.ALPHA_DOWN
|
||||
R.id.sort_alpha_up -> SortMode.ALPHA_UP
|
||||
|
||||
else -> SortMode.NONE
|
||||
}
|
||||
|
||||
if (mode != mSortMode.value) {
|
||||
mSortMode.value = mode
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,18 +2,16 @@ package org.oxycblt.auxio.library.adapters
|
|||
|
||||
import android.view.LayoutInflater
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.recyclerview.widget.ListAdapter
|
||||
import org.oxycblt.auxio.databinding.ItemAlbumBinding
|
||||
import org.oxycblt.auxio.music.Album
|
||||
import org.oxycblt.auxio.recycler.BaseViewHolder
|
||||
import org.oxycblt.auxio.recycler.ClickListener
|
||||
import org.oxycblt.auxio.recycler.DiffCallback
|
||||
|
||||
class AlbumAdapter(
|
||||
private val data: List<Album>,
|
||||
private val listener: ClickListener<Album>
|
||||
) : RecyclerView.Adapter<AlbumAdapter.ViewHolder>() {
|
||||
|
||||
override fun getItemCount(): Int = data.size
|
||||
) : ListAdapter<Album, AlbumAdapter.ViewHolder>(DiffCallback()) {
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||
return ViewHolder(
|
||||
|
@ -22,7 +20,7 @@ class AlbumAdapter(
|
|||
}
|
||||
|
||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||
holder.bind(data[position])
|
||||
holder.bind(getItem(position))
|
||||
}
|
||||
|
||||
inner class ViewHolder(
|
||||
|
|
|
@ -9,10 +9,11 @@ import org.oxycblt.auxio.recycler.BaseViewHolder
|
|||
import org.oxycblt.auxio.recycler.ClickListener
|
||||
|
||||
class ArtistAdapter(
|
||||
private val data: List<Artist>,
|
||||
private val listener: ClickListener<Artist>
|
||||
) : RecyclerView.Adapter<ArtistAdapter.ViewHolder>() {
|
||||
|
||||
private var data = listOf<Artist>()
|
||||
|
||||
override fun getItemCount(): Int = data.size
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||
|
@ -25,6 +26,12 @@ class ArtistAdapter(
|
|||
holder.bind(data[position])
|
||||
}
|
||||
|
||||
fun updateData(newData: List<Artist>) {
|
||||
data = newData
|
||||
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
|
||||
inner class ViewHolder(
|
||||
private val binding: ItemArtistBinding
|
||||
) : BaseViewHolder<Artist>(binding, listener) {
|
||||
|
|
|
@ -2,18 +2,16 @@ package org.oxycblt.auxio.library.adapters
|
|||
|
||||
import android.view.LayoutInflater
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.recyclerview.widget.ListAdapter
|
||||
import org.oxycblt.auxio.databinding.ItemGenreBinding
|
||||
import org.oxycblt.auxio.music.Genre
|
||||
import org.oxycblt.auxio.recycler.BaseViewHolder
|
||||
import org.oxycblt.auxio.recycler.ClickListener
|
||||
import org.oxycblt.auxio.recycler.DiffCallback
|
||||
|
||||
class GenreAdapter(
|
||||
private val data: List<Genre>,
|
||||
private val listener: ClickListener<Genre>
|
||||
) : RecyclerView.Adapter<GenreAdapter.ViewHolder>() {
|
||||
|
||||
override fun getItemCount(): Int = data.size
|
||||
) : ListAdapter<Genre, GenreAdapter.ViewHolder>(DiffCallback()) {
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||
return ViewHolder(
|
||||
|
@ -22,7 +20,7 @@ class GenreAdapter(
|
|||
}
|
||||
|
||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||
holder.bind(data[position])
|
||||
holder.bind(getItem(position))
|
||||
}
|
||||
|
||||
inner class ViewHolder(
|
||||
|
|
|
@ -21,7 +21,11 @@ class MusicSorter(
|
|||
sortAlbumsIntoArtists()
|
||||
sortArtistsIntoGenres()
|
||||
|
||||
finalizeMusic()
|
||||
// Remove genre duplicates at the end, as duplicate genres can be added during
|
||||
// the sorting process as well.
|
||||
genres = genres.distinctBy {
|
||||
it.name
|
||||
}.toMutableList()
|
||||
}
|
||||
|
||||
private fun sortSongsIntoAlbums() {
|
||||
|
@ -155,25 +159,4 @@ class MusicSorter(
|
|||
)
|
||||
}
|
||||
}
|
||||
|
||||
// Finalize music
|
||||
private fun finalizeMusic() {
|
||||
// Remove genre duplicates now, as duplicate genres can be added during the sorting process.
|
||||
genres = genres.distinctBy {
|
||||
it.name
|
||||
}.toMutableList()
|
||||
|
||||
// Then finally sort the music
|
||||
genres.sortWith(
|
||||
compareBy(String.CASE_INSENSITIVE_ORDER, { it.name })
|
||||
)
|
||||
|
||||
artists.sortWith(
|
||||
compareBy(String.CASE_INSENSITIVE_ORDER, { it.name })
|
||||
)
|
||||
|
||||
albums.sortWith(
|
||||
compareBy(String.CASE_INSENSITIVE_ORDER, { it.name })
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,11 +3,7 @@ package org.oxycblt.auxio.recycler
|
|||
import androidx.databinding.ViewDataBinding
|
||||
import androidx.recyclerview.widget.DiffUtil
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import org.oxycblt.auxio.R
|
||||
import org.oxycblt.auxio.music.Album
|
||||
import org.oxycblt.auxio.music.Artist
|
||||
import org.oxycblt.auxio.music.BaseModel
|
||||
import org.oxycblt.auxio.music.Song
|
||||
|
||||
// RecyclerView click listener
|
||||
class ClickListener<T>(val onClick: (T) -> Unit)
|
||||
|
@ -44,44 +40,3 @@ abstract class BaseViewHolder<T : BaseModel>(
|
|||
|
||||
abstract fun onBind(model: T)
|
||||
}
|
||||
|
||||
// Sorting modes
|
||||
enum class SortMode(val iconRes: Int) {
|
||||
// Icons for each mode are assigned to the enums themselves
|
||||
NONE(R.drawable.ic_sort_alpha_down),
|
||||
ALPHA_UP(R.drawable.ic_sort_alpha_up),
|
||||
ALPHA_DOWN(R.drawable.ic_sort_alpha_down),
|
||||
NUMERIC_UP(R.drawable.ic_sort_numeric_up),
|
||||
NUMERIC_DOWN(R.drawable.ic_sort_numeric_down);
|
||||
|
||||
companion object {
|
||||
// Sort comparators are different for each music model, so they are static maps instead.
|
||||
val songSortComparators = mapOf<SortMode, Comparator<Song>>(
|
||||
NUMERIC_DOWN to compareBy { it.track },
|
||||
NUMERIC_UP to compareByDescending { it.track }
|
||||
)
|
||||
|
||||
val albumSortComparators = mapOf<SortMode, Comparator<Album>>(
|
||||
NUMERIC_DOWN to compareByDescending { it.year },
|
||||
NUMERIC_UP to compareBy { it.year },
|
||||
|
||||
// Alphabetic sorting needs to be case-insensitive
|
||||
ALPHA_DOWN to compareByDescending(
|
||||
String.CASE_INSENSITIVE_ORDER
|
||||
) { it.name },
|
||||
ALPHA_UP to compareBy(
|
||||
String.CASE_INSENSITIVE_ORDER
|
||||
) { it.name }
|
||||
)
|
||||
|
||||
val artistSortComparators = mapOf<SortMode, Comparator<Artist>>(
|
||||
// Alphabetic sorting needs to be case-insensitive
|
||||
ALPHA_DOWN to compareBy(
|
||||
String.CASE_INSENSITIVE_ORDER
|
||||
) { it.name },
|
||||
ALPHA_UP to compareByDescending(
|
||||
String.CASE_INSENSITIVE_ORDER
|
||||
) { it.name }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
89
app/src/main/java/org/oxycblt/auxio/recycler/SortMode.kt
Normal file
89
app/src/main/java/org/oxycblt/auxio/recycler/SortMode.kt
Normal file
|
@ -0,0 +1,89 @@
|
|||
package org.oxycblt.auxio.recycler
|
||||
|
||||
import org.oxycblt.auxio.R
|
||||
import org.oxycblt.auxio.music.Album
|
||||
import org.oxycblt.auxio.music.Artist
|
||||
import org.oxycblt.auxio.music.Genre
|
||||
import org.oxycblt.auxio.music.Song
|
||||
|
||||
// Sorting modes
|
||||
enum class SortMode(val iconRes: Int) {
|
||||
// Icons for each mode are assigned to the enums themselves
|
||||
NONE(R.drawable.ic_sort_none),
|
||||
ALPHA_UP(R.drawable.ic_sort_alpha_up),
|
||||
ALPHA_DOWN(R.drawable.ic_sort_alpha_down),
|
||||
NUMERIC_UP(R.drawable.ic_sort_numeric_up),
|
||||
NUMERIC_DOWN(R.drawable.ic_sort_numeric_down);
|
||||
|
||||
fun getSortedGenreList(list: List<Genre>): List<Genre> {
|
||||
return when (this) {
|
||||
ALPHA_UP -> list.sortedWith(
|
||||
compareByDescending(String.CASE_INSENSITIVE_ORDER) { it.name }
|
||||
)
|
||||
|
||||
ALPHA_DOWN -> list.sortedWith(
|
||||
compareBy(String.CASE_INSENSITIVE_ORDER) { it.name }
|
||||
)
|
||||
|
||||
else -> list
|
||||
}
|
||||
}
|
||||
|
||||
fun getSortedArtistList(list: List<Artist>): List<Artist> {
|
||||
return when (this) {
|
||||
ALPHA_UP -> list.sortedWith(
|
||||
compareByDescending(String.CASE_INSENSITIVE_ORDER) { it.name }
|
||||
)
|
||||
|
||||
ALPHA_DOWN -> list.sortedWith(
|
||||
compareBy(String.CASE_INSENSITIVE_ORDER) { it.name }
|
||||
)
|
||||
|
||||
else -> list
|
||||
}
|
||||
}
|
||||
|
||||
fun getSortedAlbumList(list: List<Album>): List<Album> {
|
||||
return when (this) {
|
||||
ALPHA_UP -> list.sortedWith(
|
||||
compareByDescending(String.CASE_INSENSITIVE_ORDER) { it.name }
|
||||
)
|
||||
|
||||
ALPHA_DOWN -> list.sortedWith(
|
||||
compareBy(String.CASE_INSENSITIVE_ORDER) { it.name }
|
||||
)
|
||||
|
||||
NUMERIC_UP -> list.sortedBy { it.year }
|
||||
NUMERIC_DOWN -> list.sortedByDescending { it.year }
|
||||
|
||||
else -> list
|
||||
}
|
||||
}
|
||||
|
||||
fun getSortedSongList(list: List<Song>): List<Song> {
|
||||
return when (this) {
|
||||
ALPHA_UP -> list.sortedWith(
|
||||
compareByDescending(String.CASE_INSENSITIVE_ORDER) { it.name }
|
||||
)
|
||||
|
||||
ALPHA_DOWN -> list.sortedWith(
|
||||
compareBy(String.CASE_INSENSITIVE_ORDER) { it.name }
|
||||
)
|
||||
|
||||
NUMERIC_UP -> list.sortedWith(compareByDescending { it.track })
|
||||
NUMERIC_DOWN -> list.sortedWith(compareBy { it.track })
|
||||
|
||||
else -> list
|
||||
}
|
||||
}
|
||||
|
||||
fun toMenuId(): Int {
|
||||
return when (this) {
|
||||
NONE -> R.id.sort_none
|
||||
ALPHA_UP -> R.id.sort_alpha_up
|
||||
ALPHA_DOWN -> R.id.sort_alpha_down
|
||||
|
||||
else -> R.id.sort_none
|
||||
}
|
||||
}
|
||||
}
|
11
app/src/main/res/drawable/ic_sort_none.xml
Normal file
11
app/src/main/res/drawable/ic_sort_none.xml
Normal file
|
@ -0,0 +1,11 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:tint="?attr/colorPrimary">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M3,18h6v-2L3,16v2zM3,6v2h18L21,6L3,6zM3,13h12v-2L3,11v2z"/>
|
||||
</vector>
|
|
@ -7,7 +7,8 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:animateLayoutChanges="true">
|
||||
android:animateLayoutChanges="true"
|
||||
android:descendantFocusability="blocksDescendants">
|
||||
|
||||
<androidx.appcompat.widget.Toolbar
|
||||
android:id="@+id/library_toolbar"
|
||||
|
|
18
app/src/main/res/menu/menu_library.xml
Normal file
18
app/src/main/res/menu/menu_library.xml
Normal file
|
@ -0,0 +1,18 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item
|
||||
android:id="@+id/sort_none"
|
||||
android:icon="@drawable/ic_sort_none"
|
||||
android:title="@string/label_sort_none"
|
||||
android:contentDescription="@string/description_sort_none"/>
|
||||
<item
|
||||
android:id="@+id/sort_alpha_down"
|
||||
android:icon="@drawable/ic_sort_alpha_down"
|
||||
android:title="@string/label_sort_alpha_down"
|
||||
android:contentDescription="@string/description_sort_alpha_down"/>
|
||||
<item
|
||||
android:id="@+id/sort_alpha_up"
|
||||
android:icon="@drawable/ic_sort_alpha_up"
|
||||
android:title="@string/label_sort_alpha_up"
|
||||
android:contentDescription="@string/description_sort_alpha_up"/>
|
||||
</menu>
|
|
@ -73,7 +73,7 @@
|
|||
android:name="albumId"
|
||||
app:argType="long" />
|
||||
<argument
|
||||
android:name="fromLibrary"
|
||||
android:name="enableParentNav"
|
||||
app:argType="boolean" />
|
||||
<action
|
||||
android:id="@+id/action_show_parent_artist"
|
||||
|
|
|
@ -2,35 +2,48 @@
|
|||
<resources>
|
||||
<string name="app_name">Auxio</string>
|
||||
|
||||
<!-- Title Namespace | Toolbar titles -->
|
||||
<string name="title_library_fragment">Library</string>
|
||||
<string name="title_all_songs">All Songs</string>
|
||||
|
||||
<!-- Error Namespace | Error Labels -->
|
||||
<string name="error_no_music">No music found.</string>
|
||||
<string name="error_music_load_failed">Music loading failed.</string>
|
||||
<string name="error_no_perms">Permissions to read storage are needed.</string>
|
||||
|
||||
<!-- Label Namespace | Static Labels -->
|
||||
<string name="label_retry">Retry</string>
|
||||
<string name="label_grant">Grant</string>
|
||||
<string name="label_artists">Artists</string>
|
||||
<string name="label_albums">Albums</string>
|
||||
<string name="label_songs">Songs</string>
|
||||
<string name="label_sort_none">Default</string>
|
||||
<string name="label_sort_alpha_down">A-Z</string>
|
||||
<string name="label_sort_alpha_up">Z-A</string>
|
||||
|
||||
<!-- Description Namespace | Accessibility Strings -->
|
||||
<string name="description_album_cover">Album Cover for %s</string>
|
||||
<string name="description_artist_image">Artist Image for %s</string>
|
||||
<string name="description_genre_image">Genre Image for %s</string>
|
||||
<string name="description_track_number">Track %s</string>
|
||||
<string name="description_error">Error</string>
|
||||
<string name="description_sort_button">Change Sorting Mode</string>
|
||||
<string name="description_sort_none">Default Sort Order</string>
|
||||
<string name="description_sort_alpha_down">Sort from A to Z</string>
|
||||
<string name="description_sort_alpha_up">Sort from Z to A</string>
|
||||
|
||||
<!-- Placeholder Namespace | Placeholder values -->
|
||||
<string name="placeholder_genre">Unknown Genre</string>
|
||||
<string name="placeholder_artist">Unknown Artist</string>
|
||||
<string name="placeholder_album">Unknown Album</string>
|
||||
<string name="placeholder_no_date">No Date</string>
|
||||
|
||||
<!-- Format Namespace | Value formatting -->
|
||||
<string name="format_info">%1$s / %2$s</string>
|
||||
<string name="format_double_info">%1$s / %2$s / %3$s</string>
|
||||
<string name="format_double_counts">%1$s, %2$s</string>
|
||||
|
||||
<!-- Format Namespace | Value formatting with plurals -->
|
||||
<plurals name="format_song_count">
|
||||
<item quantity="one">%s Song</item>
|
||||
<item quantity="other">%s Songs</item>
|
||||
|
|
Loading…
Reference in a new issue