home: switch to sort dialogs
Switch the home view to sort dialogs, and simplify away any listeners that expected popup menus.
This commit is contained in:
parent
3340914c51
commit
a1947c4102
26 changed files with 544 additions and 395 deletions
|
@ -21,7 +21,6 @@ package org.oxycblt.auxio.detail
|
|||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import androidx.fragment.app.activityViewModels
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import androidx.navigation.fragment.navArgs
|
||||
|
@ -111,7 +110,7 @@ class AlbumDetailFragment :
|
|||
adapter = ConcatAdapter(albumHeaderAdapter, albumListAdapter)
|
||||
(layoutManager as GridLayoutManager).setFullWidthLookup {
|
||||
if (it != 0) {
|
||||
val item = detailModel.albumList.value[it - 1]
|
||||
val item = detailModel.albumSongList.value[it - 1]
|
||||
item is Divider || item is Header || item is Disc
|
||||
} else {
|
||||
true
|
||||
|
@ -123,7 +122,7 @@ class AlbumDetailFragment :
|
|||
// DetailViewModel handles most initialization from the navigation argument.
|
||||
detailModel.setAlbum(args.albumUid)
|
||||
collectImmediately(detailModel.currentAlbum, ::updateAlbum)
|
||||
collectImmediately(detailModel.albumList, ::updateList)
|
||||
collectImmediately(detailModel.albumSongList, ::updateList)
|
||||
collect(detailModel.toShow.flow, ::handleShow)
|
||||
collect(listModel.menu.flow, ::handleMenu)
|
||||
collectImmediately(listModel.selected, ::updateSelection)
|
||||
|
@ -139,7 +138,7 @@ class AlbumDetailFragment :
|
|||
binding.detailRecycler.adapter = null
|
||||
// Avoid possible race conditions that could cause a bad replace instruction to be consumed
|
||||
// during list initialization and crash the app. Could happen if the user is fast enough.
|
||||
detailModel.albumInstructions.consume()
|
||||
detailModel.albumSongInstructions.consume()
|
||||
}
|
||||
|
||||
override fun onMenuItemClick(item: MenuItem): Boolean {
|
||||
|
@ -182,7 +181,7 @@ class AlbumDetailFragment :
|
|||
playbackModel.play(item, detailModel.playInAlbumWith)
|
||||
}
|
||||
|
||||
override fun onOpenMenu(item: Song, anchor: View) {
|
||||
override fun onOpenMenu(item: Song) {
|
||||
listModel.openMenu(R.menu.item_album_song, item, detailModel.playInAlbumWith)
|
||||
}
|
||||
|
||||
|
@ -194,7 +193,7 @@ class AlbumDetailFragment :
|
|||
playbackModel.shuffle(unlikelyToBeNull(detailModel.currentAlbum.value))
|
||||
}
|
||||
|
||||
override fun onOpenSortMenu(anchor: View) {
|
||||
override fun onOpenSortMenu() {
|
||||
findNavController().navigateSafe(AlbumDetailFragmentDirections.sort())
|
||||
}
|
||||
|
||||
|
@ -213,7 +212,7 @@ class AlbumDetailFragment :
|
|||
}
|
||||
|
||||
private fun updateList(list: List<Item>) {
|
||||
albumListAdapter.update(list, detailModel.albumInstructions.consume())
|
||||
albumListAdapter.update(list, detailModel.albumSongInstructions.consume())
|
||||
}
|
||||
|
||||
private fun handleShow(show: Show?) {
|
||||
|
@ -339,7 +338,7 @@ class AlbumDetailFragment :
|
|||
|
||||
private fun scrollToAlbumSong(song: Song) {
|
||||
// Calculate where the item for the currently played song is
|
||||
val pos = detailModel.albumList.value.indexOf(song)
|
||||
val pos = detailModel.albumSongList.value.indexOf(song)
|
||||
|
||||
if (pos != -1) {
|
||||
// Only scroll if the song is within this album.
|
||||
|
|
|
@ -21,7 +21,6 @@ package org.oxycblt.auxio.detail
|
|||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import androidx.fragment.app.activityViewModels
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import androidx.navigation.fragment.navArgs
|
||||
|
@ -110,7 +109,7 @@ class ArtistDetailFragment :
|
|||
(layoutManager as GridLayoutManager).setFullWidthLookup {
|
||||
if (it != 0) {
|
||||
val item =
|
||||
detailModel.artistList.value.getOrElse(it - 1) {
|
||||
detailModel.artistSongList.value.getOrElse(it - 1) {
|
||||
return@setFullWidthLookup false
|
||||
}
|
||||
item is Divider || item is Header
|
||||
|
@ -124,7 +123,7 @@ class ArtistDetailFragment :
|
|||
// DetailViewModel handles most initialization from the navigation argument.
|
||||
detailModel.setArtist(args.artistUid)
|
||||
collectImmediately(detailModel.currentArtist, ::updateArtist)
|
||||
collectImmediately(detailModel.artistList, ::updateList)
|
||||
collectImmediately(detailModel.artistSongList, ::updateList)
|
||||
collect(detailModel.toShow.flow, ::handleShow)
|
||||
collect(listModel.menu.flow, ::handleMenu)
|
||||
collectImmediately(listModel.selected, ::updateSelection)
|
||||
|
@ -140,7 +139,7 @@ class ArtistDetailFragment :
|
|||
binding.detailRecycler.adapter = null
|
||||
// Avoid possible race conditions that could cause a bad replace instruction to be consumed
|
||||
// during list initialization and crash the app. Could happen if the user is fast enough.
|
||||
detailModel.artistInstructions.consume()
|
||||
detailModel.artistSongInstructions.consume()
|
||||
}
|
||||
|
||||
override fun onMenuItemClick(item: MenuItem): Boolean {
|
||||
|
@ -183,7 +182,7 @@ class ArtistDetailFragment :
|
|||
}
|
||||
}
|
||||
|
||||
override fun onOpenMenu(item: Music, anchor: View) {
|
||||
override fun onOpenMenu(item: Music) {
|
||||
when (item) {
|
||||
is Song ->
|
||||
listModel.openMenu(R.menu.item_artist_song, item, detailModel.playInArtistWith)
|
||||
|
@ -200,7 +199,7 @@ class ArtistDetailFragment :
|
|||
playbackModel.shuffle(unlikelyToBeNull(detailModel.currentArtist.value))
|
||||
}
|
||||
|
||||
override fun onOpenSortMenu(anchor: View) {
|
||||
override fun onOpenSortMenu() {
|
||||
findNavController().navigateSafe(ArtistDetailFragmentDirections.sort())
|
||||
}
|
||||
|
||||
|
@ -227,7 +226,7 @@ class ArtistDetailFragment :
|
|||
}
|
||||
|
||||
private fun updateList(list: List<Item>) {
|
||||
artistListAdapter.update(list, detailModel.artistInstructions.consume())
|
||||
artistListAdapter.update(list, detailModel.artistSongInstructions.consume())
|
||||
}
|
||||
|
||||
private fun handleShow(show: Show?) {
|
||||
|
|
|
@ -98,17 +98,17 @@ constructor(
|
|||
val currentAlbum: StateFlow<Album?>
|
||||
get() = _currentAlbum
|
||||
|
||||
private val _albumList = MutableStateFlow(listOf<Item>())
|
||||
private val _albumSongList = MutableStateFlow(listOf<Item>())
|
||||
/** The current list data derived from [currentAlbum]. */
|
||||
val albumList: StateFlow<List<Item>>
|
||||
get() = _albumList
|
||||
val albumSongList: StateFlow<List<Item>>
|
||||
get() = _albumSongList
|
||||
|
||||
private val _albumInstructions = MutableEvent<UpdateInstructions>()
|
||||
/** Instructions for updating [albumList] in the UI. */
|
||||
val albumInstructions: Event<UpdateInstructions>
|
||||
get() = _albumInstructions
|
||||
private val _albumSongInstructions = MutableEvent<UpdateInstructions>()
|
||||
/** Instructions for updating [albumSongList] in the UI. */
|
||||
val albumSongInstructions: Event<UpdateInstructions>
|
||||
get() = _albumSongInstructions
|
||||
|
||||
/** The current [Sort] used for [Song]s in [albumList]. */
|
||||
/** The current [Sort] used for [Song]s in [albumSongList]. */
|
||||
val albumSongSort: Sort
|
||||
get() = musicSettings.albumSongSort
|
||||
|
||||
|
@ -123,15 +123,16 @@ constructor(
|
|||
val currentArtist: StateFlow<Artist?>
|
||||
get() = _currentArtist
|
||||
|
||||
private val _artistList = MutableStateFlow(listOf<Item>())
|
||||
private val _artistSongList = MutableStateFlow(listOf<Item>())
|
||||
/** The current list derived from [currentArtist]. */
|
||||
val artistList: StateFlow<List<Item>> = _artistList
|
||||
private val _artistInstructions = MutableEvent<UpdateInstructions>()
|
||||
/** Instructions for updating [artistList] in the UI. */
|
||||
val artistInstructions: Event<UpdateInstructions>
|
||||
get() = _artistInstructions
|
||||
val artistSongList: StateFlow<List<Item>> = _artistSongList
|
||||
|
||||
/** The current [Sort] used for [Song]s in [artistList]. */
|
||||
private val _artistSongInstructions = MutableEvent<UpdateInstructions>()
|
||||
/** Instructions for updating [artistSongList] in the UI. */
|
||||
val artistSongInstructions: Event<UpdateInstructions>
|
||||
get() = _artistSongInstructions
|
||||
|
||||
/** The current [Sort] used for [Song]s in [artistSongList]. */
|
||||
var artistSongSort: Sort
|
||||
get() = musicSettings.artistSongSort
|
||||
set(value) {
|
||||
|
@ -151,15 +152,16 @@ constructor(
|
|||
val currentGenre: StateFlow<Genre?>
|
||||
get() = _currentGenre
|
||||
|
||||
private val _genreList = MutableStateFlow(listOf<Item>())
|
||||
private val _genreSongList = MutableStateFlow(listOf<Item>())
|
||||
/** The current list data derived from [currentGenre]. */
|
||||
val genreList: StateFlow<List<Item>> = _genreList
|
||||
private val _genreInstructions = MutableEvent<UpdateInstructions>()
|
||||
/** Instructions for updating [artistList] in the UI. */
|
||||
val genreInstructions: Event<UpdateInstructions>
|
||||
get() = _genreInstructions
|
||||
val genreSongList: StateFlow<List<Item>> = _genreSongList
|
||||
|
||||
/** The current [Sort] used for [Song]s in [genreList]. */
|
||||
private val _genreSongInstructions = MutableEvent<UpdateInstructions>()
|
||||
/** Instructions for updating [artistSongList] in the UI. */
|
||||
val genreSongInstructions: Event<UpdateInstructions>
|
||||
get() = _genreSongInstructions
|
||||
|
||||
/** The current [Sort] used for [Song]s in [genreSongList]. */
|
||||
var genreSongSort: Sort
|
||||
get() = musicSettings.genreSongSort
|
||||
set(value) {
|
||||
|
@ -179,13 +181,14 @@ constructor(
|
|||
val currentPlaylist: StateFlow<Playlist?>
|
||||
get() = _currentPlaylist
|
||||
|
||||
private val _playlistList = MutableStateFlow(listOf<Item>())
|
||||
private val _playlistSongList = MutableStateFlow(listOf<Item>())
|
||||
/** The current list data derived from [currentPlaylist] */
|
||||
val playlistList: StateFlow<List<Item>> = _playlistList
|
||||
private val _playlistInstructions = MutableEvent<UpdateInstructions>()
|
||||
/** Instructions for updating [playlistList] in the UI. */
|
||||
val playlistInstructions: Event<UpdateInstructions>
|
||||
get() = _playlistInstructions
|
||||
val playlistSongList: StateFlow<List<Item>> = _playlistSongList
|
||||
|
||||
private val _playlistSongInstructions = MutableEvent<UpdateInstructions>()
|
||||
/** Instructions for updating [playlistSongList] in the UI. */
|
||||
val playlistSongInstructions: Event<UpdateInstructions>
|
||||
get() = _playlistSongInstructions
|
||||
|
||||
private val _editedPlaylist = MutableStateFlow<List<Song>?>(null)
|
||||
/**
|
||||
|
@ -346,7 +349,7 @@ constructor(
|
|||
}
|
||||
|
||||
/**
|
||||
* Set a new [currentAlbum] from it's [Music.UID]. [currentAlbum] and [albumList] will be
|
||||
* Set a new [currentAlbum] from it's [Music.UID]. [currentAlbum] and [albumSongList] will be
|
||||
* updated to align with the new [Album].
|
||||
*
|
||||
* @param uid The [Music.UID] of the [Album] to update [currentAlbum] to. Must be valid.
|
||||
|
@ -360,13 +363,18 @@ constructor(
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply a new [Sort] to [albumSongList].
|
||||
*
|
||||
* @param sort The [Sort] to apply.
|
||||
*/
|
||||
fun applyAlbumSongSort(sort: Sort) {
|
||||
musicSettings.albumSongSort = sort
|
||||
_currentAlbum.value?.let { refreshAlbumList(it, true) }
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a new [currentArtist] from it's [Music.UID]. [currentArtist] and [artistList] will be
|
||||
* Set a new [currentArtist] from it's [Music.UID]. [currentArtist] and [artistSongList] will be
|
||||
* updated to align with the new [Artist].
|
||||
*
|
||||
* @param uid The [Music.UID] of the [Artist] to update [currentArtist] to. Must be valid.
|
||||
|
@ -380,13 +388,18 @@ constructor(
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply a new [Sort] to [artistSongList].
|
||||
*
|
||||
* @param sort The [Sort] to apply.
|
||||
*/
|
||||
fun applyArtistSongSort(sort: Sort) {
|
||||
musicSettings.artistSongSort = sort
|
||||
_currentArtist.value?.let { refreshArtistList(it, true) }
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a new [currentGenre] from it's [Music.UID]. [currentGenre] and [genreList] will be
|
||||
* Set a new [currentGenre] from it's [Music.UID]. [currentGenre] and [genreSongList] will be
|
||||
* updated to align with the new album.
|
||||
*
|
||||
* @param uid The [Music.UID] of the [Genre] to update [currentGenre] to. Must be valid.
|
||||
|
@ -400,6 +413,11 @@ constructor(
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply a new [Sort] to [genreSongList].
|
||||
*
|
||||
* @param sort The [Sort] to apply.
|
||||
*/
|
||||
fun applyGenreSongSort(sort: Sort) {
|
||||
musicSettings.genreSongSort = sort
|
||||
_currentGenre.value?.let { refreshGenreList(it, true) }
|
||||
|
@ -554,8 +572,8 @@ constructor(
|
|||
}
|
||||
|
||||
logD("Update album list to ${list.size} items with $instructions")
|
||||
_albumInstructions.put(instructions)
|
||||
_albumList.value = list
|
||||
_albumSongInstructions.put(instructions)
|
||||
_albumSongList.value = list
|
||||
}
|
||||
|
||||
private fun refreshArtistList(artist: Artist, replace: Boolean = false) {
|
||||
|
@ -617,8 +635,8 @@ constructor(
|
|||
}
|
||||
|
||||
logD("Updating artist list to ${list.size} items with $instructions")
|
||||
_artistInstructions.put(instructions)
|
||||
_artistList.value = list.toList()
|
||||
_artistSongInstructions.put(instructions)
|
||||
_artistSongList.value = list.toList()
|
||||
}
|
||||
|
||||
private fun refreshGenreList(genre: Genre, replace: Boolean = false) {
|
||||
|
@ -643,8 +661,8 @@ constructor(
|
|||
list.addAll(genreSongSort.songs(genre.songs))
|
||||
|
||||
logD("Updating genre list to ${list.size} items with $instructions")
|
||||
_genreInstructions.put(instructions)
|
||||
_genreList.value = list
|
||||
_genreSongInstructions.put(instructions)
|
||||
_genreSongList.value = list
|
||||
}
|
||||
|
||||
private fun refreshPlaylistList(
|
||||
|
@ -663,8 +681,8 @@ constructor(
|
|||
}
|
||||
|
||||
logD("Updating playlist list to ${list.size} items with $instructions")
|
||||
_playlistInstructions.put(instructions)
|
||||
_playlistList.value = list
|
||||
_playlistSongInstructions.put(instructions)
|
||||
_playlistSongList.value = list
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -21,7 +21,6 @@ package org.oxycblt.auxio.detail
|
|||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import androidx.fragment.app.activityViewModels
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import androidx.navigation.fragment.navArgs
|
||||
|
@ -108,7 +107,7 @@ class GenreDetailFragment :
|
|||
(layoutManager as GridLayoutManager).setFullWidthLookup {
|
||||
if (it != 0) {
|
||||
val item =
|
||||
detailModel.genreList.value.getOrElse(it - 1) {
|
||||
detailModel.genreSongList.value.getOrElse(it - 1) {
|
||||
return@setFullWidthLookup false
|
||||
}
|
||||
item is Divider || item is Header
|
||||
|
@ -122,7 +121,7 @@ class GenreDetailFragment :
|
|||
// DetailViewModel handles most initialization from the navigation argument.
|
||||
detailModel.setGenre(args.genreUid)
|
||||
collectImmediately(detailModel.currentGenre, ::updatePlaylist)
|
||||
collectImmediately(detailModel.genreList, ::updateList)
|
||||
collectImmediately(detailModel.genreSongList, ::updateList)
|
||||
collect(detailModel.toShow.flow, ::handleShow)
|
||||
collect(listModel.menu.flow, ::handleMenu)
|
||||
collectImmediately(listModel.selected, ::updateSelection)
|
||||
|
@ -138,7 +137,7 @@ class GenreDetailFragment :
|
|||
binding.detailRecycler.adapter = null
|
||||
// Avoid possible race conditions that could cause a bad replace instruction to be consumed
|
||||
// during list initialization and crash the app. Could happen if the user is fast enough.
|
||||
detailModel.genreInstructions.consume()
|
||||
detailModel.genreSongInstructions.consume()
|
||||
}
|
||||
|
||||
override fun onMenuItemClick(item: MenuItem): Boolean {
|
||||
|
@ -181,7 +180,7 @@ class GenreDetailFragment :
|
|||
}
|
||||
}
|
||||
|
||||
override fun onOpenMenu(item: Music, anchor: View) {
|
||||
override fun onOpenMenu(item: Music) {
|
||||
when (item) {
|
||||
is Artist -> listModel.openMenu(R.menu.item_parent, item)
|
||||
is Song -> listModel.openMenu(R.menu.item_song, item, detailModel.playInGenreWith)
|
||||
|
@ -197,7 +196,7 @@ class GenreDetailFragment :
|
|||
playbackModel.shuffle(unlikelyToBeNull(detailModel.currentGenre.value))
|
||||
}
|
||||
|
||||
override fun onOpenSortMenu(anchor: View) {
|
||||
override fun onOpenSortMenu() {
|
||||
findNavController().navigateSafe(GenreDetailFragmentDirections.sort())
|
||||
}
|
||||
|
||||
|
@ -212,7 +211,7 @@ class GenreDetailFragment :
|
|||
}
|
||||
|
||||
private fun updateList(list: List<Item>) {
|
||||
genreListAdapter.update(list, detailModel.genreInstructions.consume())
|
||||
genreListAdapter.update(list, detailModel.genreSongInstructions.consume())
|
||||
}
|
||||
|
||||
private fun handleShow(show: Show?) {
|
||||
|
|
|
@ -21,7 +21,6 @@ package org.oxycblt.auxio.detail
|
|||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import androidx.fragment.app.activityViewModels
|
||||
import androidx.navigation.NavController
|
||||
import androidx.navigation.NavDestination
|
||||
|
@ -123,7 +122,7 @@ class PlaylistDetailFragment :
|
|||
(layoutManager as GridLayoutManager).setFullWidthLookup {
|
||||
if (it != 0) {
|
||||
val item =
|
||||
detailModel.playlistList.value.getOrElse(it - 1) {
|
||||
detailModel.playlistSongList.value.getOrElse(it - 1) {
|
||||
return@setFullWidthLookup false
|
||||
}
|
||||
item is Divider || item is Header
|
||||
|
@ -137,7 +136,7 @@ class PlaylistDetailFragment :
|
|||
// DetailViewModel handles most initialization from the navigation argument.
|
||||
detailModel.setPlaylist(args.playlistUid)
|
||||
collectImmediately(detailModel.currentPlaylist, ::updatePlaylist)
|
||||
collectImmediately(detailModel.playlistList, ::updateList)
|
||||
collectImmediately(detailModel.playlistSongList, ::updateList)
|
||||
collectImmediately(detailModel.editedPlaylist, ::updateEditedList)
|
||||
collect(detailModel.toShow.flow, ::handleShow)
|
||||
collect(listModel.menu.flow, ::handleMenu)
|
||||
|
@ -168,7 +167,7 @@ class PlaylistDetailFragment :
|
|||
binding.detailRecycler.adapter = null
|
||||
// Avoid possible race conditions that could cause a bad replace instruction to be consumed
|
||||
// during list initialization and crash the app. Could happen if the user is fast enough.
|
||||
detailModel.playlistInstructions.consume()
|
||||
detailModel.playlistSongInstructions.consume()
|
||||
}
|
||||
|
||||
override fun onDestinationChanged(
|
||||
|
@ -236,7 +235,7 @@ class PlaylistDetailFragment :
|
|||
requireNotNull(touchHelper) { "ItemTouchHelper was not available" }.startDrag(viewHolder)
|
||||
}
|
||||
|
||||
override fun onOpenMenu(item: Song, anchor: View) {
|
||||
override fun onOpenMenu(item: Song) {
|
||||
listModel.openMenu(R.menu.item_playlist_song, item, detailModel.playInPlaylistWith)
|
||||
}
|
||||
|
||||
|
@ -252,7 +251,7 @@ class PlaylistDetailFragment :
|
|||
detailModel.startPlaylistEdit()
|
||||
}
|
||||
|
||||
override fun onOpenSortMenu(anchor: View) {}
|
||||
override fun onOpenSortMenu() {}
|
||||
|
||||
private fun updatePlaylist(playlist: Playlist?) {
|
||||
if (playlist == null) {
|
||||
|
@ -278,7 +277,7 @@ class PlaylistDetailFragment :
|
|||
}
|
||||
|
||||
private fun updateList(list: List<Item>) {
|
||||
playlistListAdapter.update(list, detailModel.playlistInstructions.consume())
|
||||
playlistListAdapter.update(list, detailModel.playlistSongInstructions.consume())
|
||||
}
|
||||
|
||||
private fun updateEditedList(editedPlaylist: List<Song>?) {
|
||||
|
|
|
@ -82,7 +82,7 @@ abstract class DetailListAdapter(
|
|||
* Called when the button in a [SortHeader] item is pressed, requesting that the sort menu
|
||||
* should be opened.
|
||||
*/
|
||||
fun onOpenSortMenu(anchor: View)
|
||||
fun onOpenSortMenu()
|
||||
}
|
||||
|
||||
protected companion object {
|
||||
|
@ -132,7 +132,7 @@ private class SortHeaderViewHolder(private val binding: ItemSortHeaderBinding) :
|
|||
// Add a Tooltip based on the content description so that the purpose of this
|
||||
// button can be clear.
|
||||
TooltipCompat.setTooltipText(this, contentDescription)
|
||||
setOnClickListener(listener::onOpenSortMenu)
|
||||
setOnClickListener { listener.onOpenSortMenu() }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -30,6 +30,11 @@ import org.oxycblt.auxio.music.Album
|
|||
import org.oxycblt.auxio.util.collectImmediately
|
||||
import org.oxycblt.auxio.util.logD
|
||||
|
||||
/**
|
||||
* A [SortDialog] that controls the [Sort] of [DetailViewModel.albumSongSort].
|
||||
*
|
||||
* @author Alexander Capehart (OxygenCobalt)
|
||||
*/
|
||||
@AndroidEntryPoint
|
||||
class AlbumSongSortDialog : SortDialog() {
|
||||
private val detailModel: DetailViewModel by activityViewModels()
|
||||
|
|
|
@ -30,6 +30,11 @@ import org.oxycblt.auxio.music.Artist
|
|||
import org.oxycblt.auxio.util.collectImmediately
|
||||
import org.oxycblt.auxio.util.logD
|
||||
|
||||
/**
|
||||
* A [SortDialog] that controls the [Sort] of [DetailViewModel.artistSongSort].
|
||||
*
|
||||
* @author Alexander Capehart (OxygenCobalt)
|
||||
*/
|
||||
@AndroidEntryPoint
|
||||
class ArtistSongSortDialog : SortDialog() {
|
||||
private val detailModel: DetailViewModel by activityViewModels()
|
||||
|
|
|
@ -30,6 +30,11 @@ import org.oxycblt.auxio.music.Genre
|
|||
import org.oxycblt.auxio.util.collectImmediately
|
||||
import org.oxycblt.auxio.util.logD
|
||||
|
||||
/**
|
||||
* A [SortDialog] that controls the [Sort] of [DetailViewModel.genreSongSort].
|
||||
*
|
||||
* @author Alexander Capehart (OxygenCobalt)
|
||||
*/
|
||||
@AndroidEntryPoint
|
||||
class GenreSongSortDialog : SortDialog() {
|
||||
private val detailModel: DetailViewModel by activityViewModels()
|
||||
|
|
|
@ -26,7 +26,6 @@ import androidx.activity.result.ActivityResultLauncher
|
|||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.core.view.MenuCompat
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.core.view.iterator
|
||||
import androidx.core.view.updatePadding
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.FragmentManager
|
||||
|
@ -57,7 +56,6 @@ import org.oxycblt.auxio.home.tabs.Tab
|
|||
import org.oxycblt.auxio.list.ListViewModel
|
||||
import org.oxycblt.auxio.list.Menu
|
||||
import org.oxycblt.auxio.list.SelectionFragment
|
||||
import org.oxycblt.auxio.list.Sort
|
||||
import org.oxycblt.auxio.music.IndexingProgress
|
||||
import org.oxycblt.auxio.music.IndexingState
|
||||
import org.oxycblt.auxio.music.Music
|
||||
|
@ -76,7 +74,6 @@ import org.oxycblt.auxio.util.lazyReflectedField
|
|||
import org.oxycblt.auxio.util.logD
|
||||
import org.oxycblt.auxio.util.logW
|
||||
import org.oxycblt.auxio.util.navigateSafe
|
||||
import org.oxycblt.auxio.util.unlikelyToBeNull
|
||||
|
||||
/**
|
||||
* The starting [SelectionFragment] of Auxio. Shows the user's music library and enables navigation
|
||||
|
@ -172,7 +169,7 @@ class HomeFragment :
|
|||
// --- VIEWMODEL SETUP ---
|
||||
collect(homeModel.recreateTabs.flow, ::handleRecreate)
|
||||
collectImmediately(homeModel.currentTabType, ::updateCurrentTab)
|
||||
collectImmediately(homeModel.songsList, homeModel.isFastScrolling, ::updateFab)
|
||||
collectImmediately(homeModel.songList, homeModel.isFastScrolling, ::updateFab)
|
||||
collect(listModel.menu.flow, ::handleMenu)
|
||||
collectImmediately(listModel.selected, ::updateSelection)
|
||||
collectImmediately(musicModel.indexingState, ::updateIndexerState)
|
||||
|
@ -232,41 +229,22 @@ class HomeFragment :
|
|||
}
|
||||
|
||||
// Handle sort menu
|
||||
R.id.submenu_sorting -> {
|
||||
R.id.action_sort -> {
|
||||
// Junk click event when opening the menu
|
||||
true
|
||||
}
|
||||
R.id.option_sort_asc -> {
|
||||
logD("Switching to ascending sorting")
|
||||
item.isChecked = true
|
||||
homeModel.setSortForCurrentTab(
|
||||
homeModel
|
||||
.getSortForTab(homeModel.currentTabType.value)
|
||||
.withDirection(Sort.Direction.ASCENDING))
|
||||
true
|
||||
}
|
||||
R.id.option_sort_dec -> {
|
||||
logD("Switching to descending sorting")
|
||||
item.isChecked = true
|
||||
homeModel.setSortForCurrentTab(
|
||||
homeModel
|
||||
.getSortForTab(homeModel.currentTabType.value)
|
||||
.withDirection(Sort.Direction.DESCENDING))
|
||||
val directions =
|
||||
when (homeModel.currentTabType.value) {
|
||||
MusicType.SONGS -> HomeFragmentDirections.sortSongs()
|
||||
MusicType.ALBUMS -> HomeFragmentDirections.sortAlbums()
|
||||
MusicType.ARTISTS -> HomeFragmentDirections.sortArtists()
|
||||
MusicType.GENRES -> HomeFragmentDirections.sortGenres()
|
||||
MusicType.PLAYLISTS -> HomeFragmentDirections.sortPlaylists()
|
||||
}
|
||||
findNavController().navigateSafe(directions)
|
||||
true
|
||||
}
|
||||
else -> {
|
||||
val newMode = Sort.Mode.fromItemId(item.itemId)
|
||||
if (newMode != null) {
|
||||
// Sorting option was selected, mark it as selected and update the mode
|
||||
logD("Updating sort mode")
|
||||
item.isChecked = true
|
||||
homeModel.setSortForCurrentTab(
|
||||
homeModel.getSortForTab(homeModel.currentTabType.value).withMode(newMode))
|
||||
true
|
||||
} else {
|
||||
logW("Unexpected menu item selected")
|
||||
false
|
||||
}
|
||||
logW("Unexpected menu item selected")
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -300,61 +278,6 @@ class HomeFragment :
|
|||
|
||||
private fun updateCurrentTab(tabType: MusicType) {
|
||||
val binding = requireBinding()
|
||||
// Update the sort options to align with those allowed by the tab
|
||||
val isVisible: (Int) -> Boolean =
|
||||
when (tabType) {
|
||||
// Disallow sorting by count for songs
|
||||
MusicType.SONGS -> {
|
||||
logD("Using song-specific menu options")
|
||||
({ id -> id != R.id.option_sort_count })
|
||||
}
|
||||
// Disallow sorting by album for albums
|
||||
MusicType.ALBUMS -> {
|
||||
logD("Using album-specific menu options")
|
||||
({ id -> id != R.id.option_sort_album })
|
||||
}
|
||||
// Only allow sorting by name, count, and duration for parents
|
||||
else -> {
|
||||
logD("Using parent-specific menu options")
|
||||
({ id ->
|
||||
id == R.id.option_sort_asc ||
|
||||
id == R.id.option_sort_dec ||
|
||||
id == R.id.option_sort_name ||
|
||||
id == R.id.option_sort_count ||
|
||||
id == R.id.option_sort_duration
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
val sortMenu =
|
||||
unlikelyToBeNull(binding.homeNormalToolbar.menu.findItem(R.id.submenu_sorting).subMenu)
|
||||
val toHighlight = homeModel.getSortForTab(tabType)
|
||||
|
||||
for (option in sortMenu) {
|
||||
val isCurrentMode = option.itemId == toHighlight.mode.itemId
|
||||
val isCurrentlyAscending =
|
||||
option.itemId == R.id.option_sort_asc &&
|
||||
toHighlight.direction == Sort.Direction.ASCENDING
|
||||
val isCurrentlyDescending =
|
||||
option.itemId == R.id.option_sort_dec &&
|
||||
toHighlight.direction == Sort.Direction.DESCENDING
|
||||
// Check the corresponding direction and mode sort options to align with
|
||||
// the current sort of the tab.
|
||||
if (isCurrentMode || isCurrentlyAscending || isCurrentlyDescending) {
|
||||
logD(
|
||||
"Checking $option option [mode: $isCurrentMode asc: $isCurrentlyAscending dec: $isCurrentlyDescending]")
|
||||
// Note: We cannot inline this boolean assignment since it unchecks all other radio
|
||||
// buttons (even when setting it to false), which would result in nothing being
|
||||
// selected.
|
||||
option.isChecked = true
|
||||
}
|
||||
|
||||
// Disable options that are not allowed by the isVisible lambda
|
||||
option.isVisible = isVisible(option.itemId)
|
||||
if (!option.isVisible) {
|
||||
logD("Hiding $option option")
|
||||
}
|
||||
}
|
||||
|
||||
// Update the scrolling view in AppBarLayout to align with the current tab's
|
||||
// scrolling state. This prevents the lift state from being confused as one
|
||||
|
|
|
@ -55,63 +55,83 @@ constructor(
|
|||
private val musicSettings: MusicSettings
|
||||
) : ViewModel(), MusicRepository.UpdateListener, HomeSettings.Listener {
|
||||
|
||||
private val _songsList = MutableStateFlow(listOf<Song>())
|
||||
private val _songList = MutableStateFlow(listOf<Song>())
|
||||
/** A list of [Song]s, sorted by the preferred [Sort], to be shown in the home view. */
|
||||
val songsList: StateFlow<List<Song>>
|
||||
get() = _songsList
|
||||
val songList: StateFlow<List<Song>>
|
||||
get() = _songList
|
||||
|
||||
private val _songsInstructions = MutableEvent<UpdateInstructions>()
|
||||
/** Instructions for how to update [songsList] in the UI. */
|
||||
val songsInstructions: Event<UpdateInstructions>
|
||||
get() = _songsInstructions
|
||||
private val _songInstructions = MutableEvent<UpdateInstructions>()
|
||||
/** Instructions for how to update [songList] in the UI. */
|
||||
val songInstructions: Event<UpdateInstructions>
|
||||
get() = _songInstructions
|
||||
|
||||
private val _albumsLists = MutableStateFlow(listOf<Album>())
|
||||
/** A list of [Album]s, sorted by the preferred [Sort], to be shown in the home view. */
|
||||
val albumsList: StateFlow<List<Album>>
|
||||
get() = _albumsLists
|
||||
|
||||
private val _albumsInstructions = MutableEvent<UpdateInstructions>()
|
||||
/** Instructions for how to update [albumsList] in the UI. */
|
||||
val albumsInstructions: Event<UpdateInstructions>
|
||||
get() = _albumsInstructions
|
||||
|
||||
private val _artistsList = MutableStateFlow(listOf<Artist>())
|
||||
/**
|
||||
* A list of [Artist]s, sorted by the preferred [Sort], to be shown in the home view. Note that
|
||||
* if "Hide collaborators" is on, this list will not include collaborator [Artist]s.
|
||||
*/
|
||||
val artistsList: MutableStateFlow<List<Artist>>
|
||||
get() = _artistsList
|
||||
|
||||
private val _artistsInstructions = MutableEvent<UpdateInstructions>()
|
||||
/** Instructions for how to update [artistsList] in the UI. */
|
||||
val artistsInstructions: Event<UpdateInstructions>
|
||||
get() = _artistsInstructions
|
||||
|
||||
private val _genresList = MutableStateFlow(listOf<Genre>())
|
||||
/** A list of [Genre]s, sorted by the preferred [Sort], to be shown in the home view. */
|
||||
val genresList: StateFlow<List<Genre>>
|
||||
get() = _genresList
|
||||
|
||||
private val _genresInstructions = MutableEvent<UpdateInstructions>()
|
||||
/** Instructions for how to update [genresList] in the UI. */
|
||||
val genresInstructions: Event<UpdateInstructions>
|
||||
get() = _genresInstructions
|
||||
|
||||
private val _playlistsList = MutableStateFlow(listOf<Playlist>())
|
||||
/** A list of [Playlist]s, sorted by the preferred [Sort], to be shown in the home view. */
|
||||
val playlistsList: StateFlow<List<Playlist>>
|
||||
get() = _playlistsList
|
||||
|
||||
private val _playlistsInstructions = MutableEvent<UpdateInstructions>()
|
||||
/** Instructions for how to update [genresList] in the UI. */
|
||||
val playlistsInstructions: Event<UpdateInstructions>
|
||||
get() = _playlistsInstructions
|
||||
/** The current [Sort] used for [songList]. */
|
||||
val songSort: Sort
|
||||
get() = musicSettings.songSort
|
||||
|
||||
/** The [PlaySong] instructions to use when playing a [Song]. */
|
||||
val playWith
|
||||
get() = playbackSettings.playInListWith
|
||||
|
||||
private val _albumList = MutableStateFlow(listOf<Album>())
|
||||
/** A list of [Album]s, sorted by the preferred [Sort], to be shown in the home view. */
|
||||
val albumList: StateFlow<List<Album>>
|
||||
get() = _albumList
|
||||
|
||||
private val _albumInstructions = MutableEvent<UpdateInstructions>()
|
||||
/** Instructions for how to update [albumList] in the UI. */
|
||||
val albumInstructions: Event<UpdateInstructions>
|
||||
get() = _albumInstructions
|
||||
|
||||
/** The current [Sort] used for [albumList]. */
|
||||
val albumSort: Sort
|
||||
get() = musicSettings.albumSort
|
||||
|
||||
private val _artistList = MutableStateFlow(listOf<Artist>())
|
||||
/**
|
||||
* A list of [Artist]s, sorted by the preferred [Sort], to be shown in the home view. Note that
|
||||
* if "Hide collaborators" is on, this list will not include collaborator [Artist]s.
|
||||
*/
|
||||
val artistList: MutableStateFlow<List<Artist>>
|
||||
get() = _artistList
|
||||
|
||||
private val _artistInstructions = MutableEvent<UpdateInstructions>()
|
||||
/** Instructions for how to update [artistList] in the UI. */
|
||||
val artistInstructions: Event<UpdateInstructions>
|
||||
get() = _artistInstructions
|
||||
|
||||
/** The current [Sort] used for [artistList]. */
|
||||
val artistSort: Sort
|
||||
get() = musicSettings.artistSort
|
||||
|
||||
private val _genreList = MutableStateFlow(listOf<Genre>())
|
||||
/** A list of [Genre]s, sorted by the preferred [Sort], to be shown in the home view. */
|
||||
val genreList: StateFlow<List<Genre>>
|
||||
get() = _genreList
|
||||
|
||||
private val _genreInstructions = MutableEvent<UpdateInstructions>()
|
||||
/** Instructions for how to update [genreList] in the UI. */
|
||||
val genreInstructions: Event<UpdateInstructions>
|
||||
get() = _genreInstructions
|
||||
|
||||
/** The current [Sort] used for [genreList]. */
|
||||
val genreSort: Sort
|
||||
get() = musicSettings.genreSort
|
||||
|
||||
private val _playlistList = MutableStateFlow(listOf<Playlist>())
|
||||
/** A list of [Playlist]s, sorted by the preferred [Sort], to be shown in the home view. */
|
||||
val playlistList: StateFlow<List<Playlist>>
|
||||
get() = _playlistList
|
||||
|
||||
private val _playlistInstructions = MutableEvent<UpdateInstructions>()
|
||||
/** Instructions for how to update [genreList] in the UI. */
|
||||
val playlistInstructions: Event<UpdateInstructions>
|
||||
get() = _playlistInstructions
|
||||
|
||||
/** The current [Sort] used for [genreList]. */
|
||||
val playlistSort: Sort
|
||||
get() = musicSettings.playlistSort
|
||||
|
||||
/**
|
||||
* A list of [MusicType] corresponding to the current [Tab] configuration, excluding invisible
|
||||
* [Tab]s.
|
||||
|
@ -157,12 +177,12 @@ constructor(
|
|||
logD("Refreshing library")
|
||||
// Get the each list of items in the library to use as our list data.
|
||||
// Applying the preferred sorting to them.
|
||||
_songsInstructions.put(UpdateInstructions.Diff)
|
||||
_songsList.value = musicSettings.songSort.songs(deviceLibrary.songs)
|
||||
_albumsInstructions.put(UpdateInstructions.Diff)
|
||||
_albumsLists.value = musicSettings.albumSort.albums(deviceLibrary.albums)
|
||||
_artistsInstructions.put(UpdateInstructions.Diff)
|
||||
_artistsList.value =
|
||||
_songInstructions.put(UpdateInstructions.Diff)
|
||||
_songList.value = musicSettings.songSort.songs(deviceLibrary.songs)
|
||||
_albumInstructions.put(UpdateInstructions.Diff)
|
||||
_albumList.value = musicSettings.albumSort.albums(deviceLibrary.albums)
|
||||
_artistInstructions.put(UpdateInstructions.Diff)
|
||||
_artistList.value =
|
||||
musicSettings.artistSort.artists(
|
||||
if (homeSettings.shouldHideCollaborators) {
|
||||
logD("Filtering collaborator artists")
|
||||
|
@ -172,15 +192,15 @@ constructor(
|
|||
logD("Using all artists")
|
||||
deviceLibrary.artists
|
||||
})
|
||||
_genresInstructions.put(UpdateInstructions.Diff)
|
||||
_genresList.value = musicSettings.genreSort.genres(deviceLibrary.genres)
|
||||
_genreInstructions.put(UpdateInstructions.Diff)
|
||||
_genreList.value = musicSettings.genreSort.genres(deviceLibrary.genres)
|
||||
}
|
||||
|
||||
val userLibrary = musicRepository.userLibrary
|
||||
if (changes.userLibrary && userLibrary != null) {
|
||||
logD("Refreshing playlists")
|
||||
_playlistsInstructions.put(UpdateInstructions.Diff)
|
||||
_playlistsList.value = musicSettings.playlistSort.playlists(userLibrary.playlists)
|
||||
_playlistInstructions.put(UpdateInstructions.Diff)
|
||||
_playlistList.value = musicSettings.playlistSort.playlists(userLibrary.playlists)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -199,59 +219,58 @@ constructor(
|
|||
}
|
||||
|
||||
/**
|
||||
* Get the preferred [Sort] for a given [Tab].
|
||||
* Apply a new [Sort] to [songList].
|
||||
*
|
||||
* @param tabType The [MusicType] of the [Tab] desired.
|
||||
* @return The [Sort] preferred for that [Tab]
|
||||
* @param sort The [Sort] to apply.
|
||||
*/
|
||||
fun getSortForTab(tabType: MusicType) =
|
||||
when (tabType) {
|
||||
MusicType.SONGS -> musicSettings.songSort
|
||||
MusicType.ALBUMS -> musicSettings.albumSort
|
||||
MusicType.ARTISTS -> musicSettings.artistSort
|
||||
MusicType.GENRES -> musicSettings.genreSort
|
||||
MusicType.PLAYLISTS -> musicSettings.playlistSort
|
||||
}
|
||||
fun applySongSort(sort: Sort) {
|
||||
musicSettings.songSort = sort
|
||||
_songInstructions.put(UpdateInstructions.Replace(0))
|
||||
_songList.value = musicSettings.songSort.songs(_songList.value)
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the preferred [Sort] for the current [Tab]. Will update corresponding list.
|
||||
* Apply a new [Sort] to [albumList].
|
||||
*
|
||||
* @param sort The new [Sort] to apply. Assumed to be an allowed sort for the current [Tab].
|
||||
* @param sort The [Sort] to apply.
|
||||
*/
|
||||
fun setSortForCurrentTab(sort: Sort) {
|
||||
// Can simply re-sort the current list of items without having to access the library.
|
||||
when (val type = _currentTabType.value) {
|
||||
MusicType.SONGS -> {
|
||||
logD("Updating song [$type] sort mode to $sort")
|
||||
musicSettings.songSort = sort
|
||||
_songsInstructions.put(UpdateInstructions.Replace(0))
|
||||
_songsList.value = sort.songs(_songsList.value)
|
||||
}
|
||||
MusicType.ALBUMS -> {
|
||||
logD("Updating album [$type] sort mode to $sort")
|
||||
musicSettings.albumSort = sort
|
||||
_albumsInstructions.put(UpdateInstructions.Replace(0))
|
||||
_albumsLists.value = sort.albums(_albumsLists.value)
|
||||
}
|
||||
MusicType.ARTISTS -> {
|
||||
logD("Updating artist [$type] sort mode to $sort")
|
||||
musicSettings.artistSort = sort
|
||||
_artistsInstructions.put(UpdateInstructions.Replace(0))
|
||||
_artistsList.value = sort.artists(_artistsList.value)
|
||||
}
|
||||
MusicType.GENRES -> {
|
||||
logD("Updating genre [$type] sort mode to $sort")
|
||||
musicSettings.genreSort = sort
|
||||
_genresInstructions.put(UpdateInstructions.Replace(0))
|
||||
_genresList.value = sort.genres(_genresList.value)
|
||||
}
|
||||
MusicType.PLAYLISTS -> {
|
||||
logD("Updating playlist [$type] sort mode to $sort")
|
||||
musicSettings.playlistSort = sort
|
||||
_playlistsInstructions.put(UpdateInstructions.Replace(0))
|
||||
_playlistsList.value = sort.playlists(_playlistsList.value)
|
||||
}
|
||||
}
|
||||
fun applyAlbumSort(sort: Sort) {
|
||||
musicSettings.albumSort = sort
|
||||
_albumInstructions.put(UpdateInstructions.Replace(0))
|
||||
_albumList.value = musicSettings.albumSort.albums(_albumList.value)
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply a new [Sort] to [artistList].
|
||||
*
|
||||
* @param sort The [Sort] to apply.
|
||||
*/
|
||||
fun applyArtistSort(sort: Sort) {
|
||||
musicSettings.artistSort = sort
|
||||
_artistInstructions.put(UpdateInstructions.Replace(0))
|
||||
_artistList.value = musicSettings.artistSort.artists(_artistList.value)
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply a new [Sort] to [genreList].
|
||||
*
|
||||
* @param sort The [Sort] to apply.
|
||||
*/
|
||||
fun applyGenreSort(sort: Sort) {
|
||||
musicSettings.genreSort = sort
|
||||
_genreInstructions.put(UpdateInstructions.Replace(0))
|
||||
_genreList.value = musicSettings.genreSort.genres(_genreList.value)
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply a new [Sort] to [playlistList].
|
||||
*
|
||||
* @param sort The [Sort] to apply.
|
||||
*/
|
||||
fun applyPlaylistSort(sort: Sort) {
|
||||
musicSettings.playlistSort = sort
|
||||
_playlistInstructions.put(UpdateInstructions.Replace(0))
|
||||
_playlistList.value = musicSettings.playlistSort.playlists(_playlistList.value)
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -21,7 +21,6 @@ package org.oxycblt.auxio.home.list
|
|||
import android.os.Bundle
|
||||
import android.text.format.DateUtils
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.fragment.app.activityViewModels
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
|
@ -40,7 +39,6 @@ import org.oxycblt.auxio.list.recycler.AlbumViewHolder
|
|||
import org.oxycblt.auxio.music.Album
|
||||
import org.oxycblt.auxio.music.Music
|
||||
import org.oxycblt.auxio.music.MusicParent
|
||||
import org.oxycblt.auxio.music.MusicType
|
||||
import org.oxycblt.auxio.music.MusicViewModel
|
||||
import org.oxycblt.auxio.music.Song
|
||||
import org.oxycblt.auxio.playback.PlaybackViewModel
|
||||
|
@ -81,7 +79,7 @@ class AlbumListFragment :
|
|||
listener = this@AlbumListFragment
|
||||
}
|
||||
|
||||
collectImmediately(homeModel.albumsList, ::updateAlbums)
|
||||
collectImmediately(homeModel.albumList, ::updateAlbums)
|
||||
collectImmediately(listModel.selected, ::updateSelection)
|
||||
collectImmediately(
|
||||
playbackModel.song, playbackModel.parent, playbackModel.isPlaying, ::updatePlayback)
|
||||
|
@ -97,9 +95,9 @@ class AlbumListFragment :
|
|||
}
|
||||
|
||||
override fun getPopup(pos: Int): String? {
|
||||
val album = homeModel.albumsList.value[pos]
|
||||
val album = homeModel.albumList.value[pos]
|
||||
// Change how we display the popup depending on the current sort mode.
|
||||
return when (homeModel.getSortForTab(MusicType.ALBUMS).mode) {
|
||||
return when (homeModel.albumSort.mode) {
|
||||
// By Name -> Use Name
|
||||
is Sort.Mode.ByName -> album.name.thumb
|
||||
|
||||
|
@ -141,12 +139,12 @@ class AlbumListFragment :
|
|||
detailModel.showAlbum(item)
|
||||
}
|
||||
|
||||
override fun onOpenMenu(item: Album, anchor: View) {
|
||||
override fun onOpenMenu(item: Album) {
|
||||
listModel.openMenu(R.menu.item_album, item)
|
||||
}
|
||||
|
||||
private fun updateAlbums(albums: List<Album>) {
|
||||
albumAdapter.update(albums, homeModel.albumsInstructions.consume())
|
||||
albumAdapter.update(albums, homeModel.albumInstructions.consume())
|
||||
}
|
||||
|
||||
private fun updateSelection(selection: List<Music>) {
|
||||
|
|
|
@ -20,7 +20,6 @@ package org.oxycblt.auxio.home.list
|
|||
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.fragment.app.activityViewModels
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
|
@ -38,7 +37,6 @@ import org.oxycblt.auxio.list.recycler.ArtistViewHolder
|
|||
import org.oxycblt.auxio.music.Artist
|
||||
import org.oxycblt.auxio.music.Music
|
||||
import org.oxycblt.auxio.music.MusicParent
|
||||
import org.oxycblt.auxio.music.MusicType
|
||||
import org.oxycblt.auxio.music.MusicViewModel
|
||||
import org.oxycblt.auxio.music.Song
|
||||
import org.oxycblt.auxio.playback.PlaybackViewModel
|
||||
|
@ -76,7 +74,7 @@ class ArtistListFragment :
|
|||
listener = this@ArtistListFragment
|
||||
}
|
||||
|
||||
collectImmediately(homeModel.artistsList, ::updateArtists)
|
||||
collectImmediately(homeModel.artistList, ::updateArtists)
|
||||
collectImmediately(listModel.selected, ::updateSelection)
|
||||
collectImmediately(
|
||||
playbackModel.song, playbackModel.parent, playbackModel.isPlaying, ::updatePlayback)
|
||||
|
@ -92,9 +90,9 @@ class ArtistListFragment :
|
|||
}
|
||||
|
||||
override fun getPopup(pos: Int): String? {
|
||||
val artist = homeModel.artistsList.value[pos]
|
||||
val artist = homeModel.artistList.value[pos]
|
||||
// Change how we display the popup depending on the current sort mode.
|
||||
return when (homeModel.getSortForTab(MusicType.ARTISTS).mode) {
|
||||
return when (homeModel.artistSort.mode) {
|
||||
// By Name -> Use Name
|
||||
is Sort.Mode.ByName -> artist.name.thumb
|
||||
|
||||
|
@ -117,12 +115,12 @@ class ArtistListFragment :
|
|||
detailModel.showArtist(item)
|
||||
}
|
||||
|
||||
override fun onOpenMenu(item: Artist, anchor: View) {
|
||||
override fun onOpenMenu(item: Artist) {
|
||||
listModel.openMenu(R.menu.item_parent, item)
|
||||
}
|
||||
|
||||
private fun updateArtists(artists: List<Artist>) {
|
||||
artistAdapter.update(artists, homeModel.artistsInstructions.consume())
|
||||
artistAdapter.update(artists, homeModel.artistInstructions.consume())
|
||||
}
|
||||
|
||||
private fun updateSelection(selection: List<Music>) {
|
||||
|
|
|
@ -20,7 +20,6 @@ package org.oxycblt.auxio.home.list
|
|||
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.fragment.app.activityViewModels
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
|
@ -38,7 +37,6 @@ import org.oxycblt.auxio.list.recycler.GenreViewHolder
|
|||
import org.oxycblt.auxio.music.Genre
|
||||
import org.oxycblt.auxio.music.Music
|
||||
import org.oxycblt.auxio.music.MusicParent
|
||||
import org.oxycblt.auxio.music.MusicType
|
||||
import org.oxycblt.auxio.music.MusicViewModel
|
||||
import org.oxycblt.auxio.music.Song
|
||||
import org.oxycblt.auxio.playback.PlaybackViewModel
|
||||
|
@ -75,7 +73,7 @@ class GenreListFragment :
|
|||
listener = this@GenreListFragment
|
||||
}
|
||||
|
||||
collectImmediately(homeModel.genresList, ::updateGenres)
|
||||
collectImmediately(homeModel.genreList, ::updateGenres)
|
||||
collectImmediately(listModel.selected, ::updateSelection)
|
||||
collectImmediately(
|
||||
playbackModel.song, playbackModel.parent, playbackModel.isPlaying, ::updatePlayback)
|
||||
|
@ -91,9 +89,9 @@ class GenreListFragment :
|
|||
}
|
||||
|
||||
override fun getPopup(pos: Int): String? {
|
||||
val genre = homeModel.genresList.value[pos]
|
||||
val genre = homeModel.genreList.value[pos]
|
||||
// Change how we display the popup depending on the current sort mode.
|
||||
return when (homeModel.getSortForTab(MusicType.GENRES).mode) {
|
||||
return when (homeModel.genreSort.mode) {
|
||||
// By Name -> Use Name
|
||||
is Sort.Mode.ByName -> genre.name.thumb
|
||||
|
||||
|
@ -116,12 +114,12 @@ class GenreListFragment :
|
|||
detailModel.showGenre(item)
|
||||
}
|
||||
|
||||
override fun onOpenMenu(item: Genre, anchor: View) {
|
||||
override fun onOpenMenu(item: Genre) {
|
||||
listModel.openMenu(R.menu.item_parent, item)
|
||||
}
|
||||
|
||||
private fun updateGenres(genres: List<Genre>) {
|
||||
genreAdapter.update(genres, homeModel.genresInstructions.consume())
|
||||
genreAdapter.update(genres, homeModel.genreInstructions.consume())
|
||||
}
|
||||
|
||||
private fun updateSelection(selection: List<Music>) {
|
||||
|
|
|
@ -20,7 +20,6 @@ package org.oxycblt.auxio.home.list
|
|||
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.fragment.app.activityViewModels
|
||||
import org.oxycblt.auxio.R
|
||||
|
@ -36,7 +35,6 @@ import org.oxycblt.auxio.list.adapter.SelectionIndicatorAdapter
|
|||
import org.oxycblt.auxio.list.recycler.PlaylistViewHolder
|
||||
import org.oxycblt.auxio.music.Music
|
||||
import org.oxycblt.auxio.music.MusicParent
|
||||
import org.oxycblt.auxio.music.MusicType
|
||||
import org.oxycblt.auxio.music.MusicViewModel
|
||||
import org.oxycblt.auxio.music.Playlist
|
||||
import org.oxycblt.auxio.music.Song
|
||||
|
@ -73,7 +71,7 @@ class PlaylistListFragment :
|
|||
listener = this@PlaylistListFragment
|
||||
}
|
||||
|
||||
collectImmediately(homeModel.playlistsList, ::updatePlaylists)
|
||||
collectImmediately(homeModel.playlistList, ::updatePlaylists)
|
||||
collectImmediately(listModel.selected, ::updateSelection)
|
||||
collectImmediately(
|
||||
playbackModel.song, playbackModel.parent, playbackModel.isPlaying, ::updatePlayback)
|
||||
|
@ -89,9 +87,9 @@ class PlaylistListFragment :
|
|||
}
|
||||
|
||||
override fun getPopup(pos: Int): String? {
|
||||
val playlist = homeModel.playlistsList.value[pos]
|
||||
val playlist = homeModel.playlistList.value[pos]
|
||||
// Change how we display the popup depending on the current sort mode.
|
||||
return when (homeModel.getSortForTab(MusicType.GENRES).mode) {
|
||||
return when (homeModel.playlistSort.mode) {
|
||||
// By Name -> Use Name
|
||||
is Sort.Mode.ByName -> playlist.name.thumb
|
||||
|
||||
|
@ -114,12 +112,12 @@ class PlaylistListFragment :
|
|||
detailModel.showPlaylist(item)
|
||||
}
|
||||
|
||||
override fun onOpenMenu(item: Playlist, anchor: View) {
|
||||
override fun onOpenMenu(item: Playlist) {
|
||||
listModel.openMenu(R.menu.item_playlist, item)
|
||||
}
|
||||
|
||||
private fun updatePlaylists(playlists: List<Playlist>) {
|
||||
playlistAdapter.update(playlists, homeModel.playlistsInstructions.consume())
|
||||
playlistAdapter.update(playlists, homeModel.playlistInstructions.consume())
|
||||
}
|
||||
|
||||
private fun updateSelection(selection: List<Music>) {
|
||||
|
|
|
@ -21,7 +21,6 @@ package org.oxycblt.auxio.home.list
|
|||
import android.os.Bundle
|
||||
import android.text.format.DateUtils
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.fragment.app.activityViewModels
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
|
@ -38,7 +37,6 @@ import org.oxycblt.auxio.list.adapter.SelectionIndicatorAdapter
|
|||
import org.oxycblt.auxio.list.recycler.SongViewHolder
|
||||
import org.oxycblt.auxio.music.Music
|
||||
import org.oxycblt.auxio.music.MusicParent
|
||||
import org.oxycblt.auxio.music.MusicType
|
||||
import org.oxycblt.auxio.music.MusicViewModel
|
||||
import org.oxycblt.auxio.music.Song
|
||||
import org.oxycblt.auxio.playback.PlaybackViewModel
|
||||
|
@ -78,7 +76,7 @@ class SongListFragment :
|
|||
listener = this@SongListFragment
|
||||
}
|
||||
|
||||
collectImmediately(homeModel.songsList, ::updateSongs)
|
||||
collectImmediately(homeModel.songList, ::updateSongs)
|
||||
collectImmediately(listModel.selected, ::updateSelection)
|
||||
collectImmediately(
|
||||
playbackModel.song, playbackModel.parent, playbackModel.isPlaying, ::updatePlayback)
|
||||
|
@ -94,11 +92,11 @@ class SongListFragment :
|
|||
}
|
||||
|
||||
override fun getPopup(pos: Int): String? {
|
||||
val song = homeModel.songsList.value[pos]
|
||||
val song = homeModel.songList.value[pos]
|
||||
// Change how we display the popup depending on the current sort mode.
|
||||
// Note: We don't use the more correct individual artist name here, as sorts are largely
|
||||
// based off the names of the parent objects and not the child objects.
|
||||
return when (homeModel.getSortForTab(MusicType.SONGS).mode) {
|
||||
return when (homeModel.songSort.mode) {
|
||||
// Name -> Use name
|
||||
is Sort.Mode.ByName -> song.name.thumb
|
||||
|
||||
|
@ -140,12 +138,12 @@ class SongListFragment :
|
|||
playbackModel.play(item, homeModel.playWith)
|
||||
}
|
||||
|
||||
override fun onOpenMenu(item: Song, anchor: View) {
|
||||
override fun onOpenMenu(item: Song) {
|
||||
listModel.openMenu(R.menu.item_song, item, homeModel.playWith)
|
||||
}
|
||||
|
||||
private fun updateSongs(songs: List<Song>) {
|
||||
songAdapter.update(songs, homeModel.songsInstructions.consume())
|
||||
songAdapter.update(songs, homeModel.songInstructions.consume())
|
||||
}
|
||||
|
||||
private fun updateSelection(selection: List<Music>) {
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* Copyright (c) 2023 Auxio Project
|
||||
* AlbumSortDialog.kt is part of Auxio.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.oxycblt.auxio.home.sort
|
||||
|
||||
import androidx.fragment.app.activityViewModels
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import org.oxycblt.auxio.home.HomeViewModel
|
||||
import org.oxycblt.auxio.list.Sort
|
||||
import org.oxycblt.auxio.list.sort.SortDialog
|
||||
|
||||
/**
|
||||
* A [SortDialog] that controls the [Sort] of [HomeViewModel.albumList].
|
||||
*
|
||||
* @author Alexander Capehart (OxygenCobalt)
|
||||
*/
|
||||
@AndroidEntryPoint
|
||||
class AlbumSortDialog : SortDialog() {
|
||||
private val homeModel: HomeViewModel by activityViewModels()
|
||||
|
||||
override fun getInitialSort() = homeModel.albumSort
|
||||
|
||||
override fun applyChosenSort(sort: Sort) {
|
||||
homeModel.applyAlbumSort(sort)
|
||||
}
|
||||
|
||||
override fun getModeChoices() =
|
||||
listOf(
|
||||
Sort.Mode.ByName,
|
||||
Sort.Mode.ByArtist,
|
||||
Sort.Mode.ByDate,
|
||||
Sort.Mode.ByDuration,
|
||||
Sort.Mode.ByCount,
|
||||
Sort.Mode.ByDateAdded)
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Copyright (c) 2023 Auxio Project
|
||||
* ArtistSortDialog.kt is part of Auxio.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.oxycblt.auxio.home.sort
|
||||
|
||||
import androidx.fragment.app.activityViewModels
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import org.oxycblt.auxio.home.HomeViewModel
|
||||
import org.oxycblt.auxio.list.Sort
|
||||
import org.oxycblt.auxio.list.sort.SortDialog
|
||||
|
||||
/**
|
||||
* A [SortDialog] that controls the [Sort] of [HomeViewModel.artistList].
|
||||
*
|
||||
* @author Alexander Capehart (OxygenCobalt)
|
||||
*/
|
||||
@AndroidEntryPoint
|
||||
class ArtistSortDialog : SortDialog() {
|
||||
private val homeModel: HomeViewModel by activityViewModels()
|
||||
|
||||
override fun getInitialSort() = homeModel.artistSort
|
||||
|
||||
override fun applyChosenSort(sort: Sort) {
|
||||
homeModel.applyArtistSort(sort)
|
||||
}
|
||||
|
||||
override fun getModeChoices() =
|
||||
listOf(Sort.Mode.ByName, Sort.Mode.ByDuration, Sort.Mode.ByCount)
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Copyright (c) 2023 Auxio Project
|
||||
* GenreSortDialog.kt is part of Auxio.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.oxycblt.auxio.home.sort
|
||||
|
||||
import androidx.fragment.app.activityViewModels
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import org.oxycblt.auxio.home.HomeViewModel
|
||||
import org.oxycblt.auxio.list.Sort
|
||||
import org.oxycblt.auxio.list.sort.SortDialog
|
||||
|
||||
/**
|
||||
* A [SortDialog] that controls the [Sort] of [HomeViewModel.genreList].
|
||||
*
|
||||
* @author Alexander Capehart (OxygenCobalt)
|
||||
*/
|
||||
@AndroidEntryPoint
|
||||
class GenreSortDialog : SortDialog() {
|
||||
private val homeModel: HomeViewModel by activityViewModels()
|
||||
|
||||
override fun getInitialSort() = homeModel.genreSort
|
||||
|
||||
override fun applyChosenSort(sort: Sort) {
|
||||
homeModel.applyGenreSort(sort)
|
||||
}
|
||||
|
||||
override fun getModeChoices() =
|
||||
listOf(Sort.Mode.ByName, Sort.Mode.ByDuration, Sort.Mode.ByCount)
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Copyright (c) 2023 Auxio Project
|
||||
* PlaylistSortDialog.kt is part of Auxio.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.oxycblt.auxio.home.sort
|
||||
|
||||
import androidx.fragment.app.activityViewModels
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import org.oxycblt.auxio.home.HomeViewModel
|
||||
import org.oxycblt.auxio.list.Sort
|
||||
import org.oxycblt.auxio.list.sort.SortDialog
|
||||
|
||||
/**
|
||||
* A [SortDialog] that controls the [Sort] of [HomeViewModel.playlistList].
|
||||
*
|
||||
* @author Alexander Capehart (OxygenCobalt)
|
||||
*/
|
||||
@AndroidEntryPoint
|
||||
class PlaylistSortDialog : SortDialog() {
|
||||
private val homeModel: HomeViewModel by activityViewModels()
|
||||
|
||||
override fun getInitialSort() = homeModel.playlistSort
|
||||
|
||||
override fun applyChosenSort(sort: Sort) {
|
||||
homeModel.applyPlaylistSort(sort)
|
||||
}
|
||||
|
||||
override fun getModeChoices() =
|
||||
listOf(Sort.Mode.ByName, Sort.Mode.ByDuration, Sort.Mode.ByCount)
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* Copyright (c) 2023 Auxio Project
|
||||
* SongSortDialog.kt is part of Auxio.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.oxycblt.auxio.home.sort
|
||||
|
||||
import androidx.fragment.app.activityViewModels
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import org.oxycblt.auxio.home.HomeViewModel
|
||||
import org.oxycblt.auxio.list.Sort
|
||||
import org.oxycblt.auxio.list.sort.SortDialog
|
||||
|
||||
/**
|
||||
* A [SortDialog] that controls the [Sort] of [HomeViewModel.songList].
|
||||
*
|
||||
* @author Alexander Capehart (OxygenCobalt)
|
||||
*/
|
||||
@AndroidEntryPoint
|
||||
class SongSortDialog : SortDialog() {
|
||||
private val homeModel: HomeViewModel by activityViewModels()
|
||||
|
||||
override fun getInitialSort() = homeModel.songSort
|
||||
|
||||
override fun applyChosenSort(sort: Sort) {
|
||||
homeModel.applySongSort(sort)
|
||||
}
|
||||
|
||||
override fun getModeChoices() =
|
||||
listOf(
|
||||
Sort.Mode.ByName,
|
||||
Sort.Mode.ByArtist,
|
||||
Sort.Mode.ByAlbum,
|
||||
Sort.Mode.ByDate,
|
||||
Sort.Mode.ByDuration,
|
||||
Sort.Mode.ByDateAdded)
|
||||
}
|
|
@ -115,9 +115,8 @@ interface SelectableListListener<in T> : ClickableListListener<T> {
|
|||
* Called when an item in the list requests that a menu related to it should be opened.
|
||||
*
|
||||
* @param item The [T] item to open a menu for.
|
||||
* @param anchor The [View] to anchor the menu to.
|
||||
*/
|
||||
fun onOpenMenu(item: T, anchor: View)
|
||||
fun onOpenMenu(item: T)
|
||||
|
||||
/**
|
||||
* Called when an item in the list requests that it be selected.
|
||||
|
@ -148,6 +147,6 @@ interface SelectableListListener<in T> : ClickableListListener<T> {
|
|||
true
|
||||
}
|
||||
// Map the menu button to the menu opening listener.
|
||||
menuButton.setOnClickListener { onOpenMenu(item, it) }
|
||||
menuButton.setOnClickListener { onOpenMenu(item) }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,8 +18,6 @@
|
|||
|
||||
package org.oxycblt.auxio.list
|
||||
|
||||
import androidx.annotation.IdRes
|
||||
import java.lang.IllegalStateException
|
||||
import kotlin.math.max
|
||||
import org.oxycblt.auxio.IntegerTable
|
||||
import org.oxycblt.auxio.R
|
||||
|
@ -164,8 +162,6 @@ data class Sort(val mode: Mode, val direction: Direction) {
|
|||
sealed interface Mode {
|
||||
/** The integer representation of this sort mode. */
|
||||
val intCode: Int
|
||||
/** The item ID of this sort mode in menu resources. */
|
||||
val itemId: Int
|
||||
/** The string resource of the human-readable name of this sort mode. */
|
||||
val stringRes: Int
|
||||
|
||||
|
@ -223,9 +219,6 @@ data class Sort(val mode: Mode, val direction: Direction) {
|
|||
override val intCode: Int
|
||||
get() = IntegerTable.SORT_BY_NAME
|
||||
|
||||
override val itemId: Int
|
||||
get() = R.id.option_sort_name
|
||||
|
||||
override val stringRes: Int
|
||||
get() = R.string.lbl_name
|
||||
|
||||
|
@ -254,9 +247,6 @@ data class Sort(val mode: Mode, val direction: Direction) {
|
|||
override val intCode: Int
|
||||
get() = IntegerTable.SORT_BY_ALBUM
|
||||
|
||||
override val itemId: Int
|
||||
get() = R.id.option_sort_album
|
||||
|
||||
override val stringRes: Int
|
||||
get() = R.string.lbl_album
|
||||
|
||||
|
@ -277,9 +267,6 @@ data class Sort(val mode: Mode, val direction: Direction) {
|
|||
override val intCode: Int
|
||||
get() = IntegerTable.SORT_BY_ARTIST
|
||||
|
||||
override val itemId: Int
|
||||
get() = R.id.option_sort_artist
|
||||
|
||||
override val stringRes: Int
|
||||
get() = R.string.lbl_artist
|
||||
|
||||
|
@ -309,9 +296,6 @@ data class Sort(val mode: Mode, val direction: Direction) {
|
|||
override val intCode: Int
|
||||
get() = IntegerTable.SORT_BY_YEAR
|
||||
|
||||
override val itemId: Int
|
||||
get() = R.id.option_sort_year
|
||||
|
||||
override val stringRes: Int
|
||||
get() = R.string.lbl_date
|
||||
|
||||
|
@ -334,9 +318,6 @@ data class Sort(val mode: Mode, val direction: Direction) {
|
|||
override val intCode: Int
|
||||
get() = IntegerTable.SORT_BY_DURATION
|
||||
|
||||
override val itemId: Int
|
||||
get() = R.id.option_sort_duration
|
||||
|
||||
override val stringRes: Int
|
||||
get() = R.string.lbl_duration
|
||||
|
||||
|
@ -372,9 +353,6 @@ data class Sort(val mode: Mode, val direction: Direction) {
|
|||
override val intCode: Int
|
||||
get() = IntegerTable.SORT_BY_COUNT
|
||||
|
||||
override val itemId: Int
|
||||
get() = R.id.option_sort_count
|
||||
|
||||
override val stringRes: Int
|
||||
get() = R.string.lbl_song_count
|
||||
|
||||
|
@ -406,9 +384,6 @@ data class Sort(val mode: Mode, val direction: Direction) {
|
|||
override val intCode: Int
|
||||
get() = IntegerTable.SORT_BY_DISC
|
||||
|
||||
override val itemId: Int
|
||||
get() = throw IllegalStateException()
|
||||
|
||||
override val stringRes: Int
|
||||
get() = R.string.lbl_disc
|
||||
|
||||
|
@ -428,9 +403,6 @@ data class Sort(val mode: Mode, val direction: Direction) {
|
|||
override val intCode: Int
|
||||
get() = IntegerTable.SORT_BY_TRACK
|
||||
|
||||
override val itemId: Int
|
||||
get() = throw IllegalStateException()
|
||||
|
||||
override val stringRes: Int
|
||||
get() = R.string.lbl_track
|
||||
|
||||
|
@ -451,9 +423,6 @@ data class Sort(val mode: Mode, val direction: Direction) {
|
|||
override val intCode: Int
|
||||
get() = IntegerTable.SORT_BY_DATE_ADDED
|
||||
|
||||
override val itemId: Int
|
||||
get() = R.id.option_sort_date_added
|
||||
|
||||
override val stringRes: Int
|
||||
get() = R.string.lbl_date_added
|
||||
|
||||
|
@ -488,27 +457,6 @@ data class Sort(val mode: Mode, val direction: Direction) {
|
|||
ByDateAdded.intCode -> ByDateAdded
|
||||
else -> null
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a menu item ID into a [Mode].
|
||||
*
|
||||
* @param itemId The menu resource ID to convert
|
||||
* @return A [Mode] corresponding to the given ID, or null if the ID is invalid.
|
||||
* @see itemId
|
||||
*/
|
||||
fun fromItemId(@IdRes itemId: Int) =
|
||||
when (itemId) {
|
||||
ByName.itemId -> ByName
|
||||
ByAlbum.itemId -> ByAlbum
|
||||
ByArtist.itemId -> ByArtist
|
||||
ByDate.itemId -> ByDate
|
||||
ByDuration.itemId -> ByDuration
|
||||
ByCount.itemId -> ByCount
|
||||
ByDisc.itemId -> ByDisc
|
||||
ByTrack.itemId -> ByTrack
|
||||
ByDateAdded.itemId -> ByDateAdded
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -182,7 +182,7 @@ class SearchFragment : ListFragment<Music, FragmentSearchBinding>() {
|
|||
}
|
||||
}
|
||||
|
||||
override fun onOpenMenu(item: Music, anchor: View) {
|
||||
override fun onOpenMenu(item: Music) {
|
||||
when (item) {
|
||||
is Song -> listModel.openMenu(R.menu.item_song, item, searchModel.playWith)
|
||||
is Album -> listModel.openMenu(R.menu.item_album, item)
|
||||
|
|
|
@ -9,46 +9,10 @@
|
|||
app:showAsAction="ifRoom" />
|
||||
|
||||
<item
|
||||
android:id="@+id/submenu_sorting"
|
||||
android:id="@+id/action_sort"
|
||||
android:icon="@drawable/ic_sort_24"
|
||||
android:title="@string/lbl_sort"
|
||||
app:showAsAction="ifRoom">
|
||||
<menu>
|
||||
<group android:checkableBehavior="single"
|
||||
android:id="@+id/sort_modes">
|
||||
<item
|
||||
android:id="@+id/option_sort_name"
|
||||
android:title="@string/lbl_name" />
|
||||
<item
|
||||
android:id="@+id/option_sort_artist"
|
||||
android:title="@string/lbl_artist" />
|
||||
<item
|
||||
android:id="@+id/option_sort_album"
|
||||
android:title="@string/lbl_album" />
|
||||
<item
|
||||
android:id="@+id/option_sort_year"
|
||||
android:title="@string/lbl_date" />
|
||||
<item
|
||||
android:id="@+id/option_sort_duration"
|
||||
android:title="@string/lbl_duration" />
|
||||
<item
|
||||
android:id="@+id/option_sort_count"
|
||||
android:title="@string/lbl_song_count" />
|
||||
<item
|
||||
android:id="@+id/option_sort_date_added"
|
||||
android:title="@string/lbl_date_added" />
|
||||
</group>
|
||||
<group android:checkableBehavior="single"
|
||||
android:id="@+id/sort_direction">
|
||||
<item
|
||||
android:id="@+id/option_sort_asc"
|
||||
android:title="@string/lbl_sort_asc" />
|
||||
<item
|
||||
android:id="@+id/option_sort_dec"
|
||||
android:title="@string/lbl_sort_dsc" />
|
||||
</group>
|
||||
</menu>
|
||||
</item>
|
||||
app:showAsAction="ifRoom" />
|
||||
|
||||
<item
|
||||
android:id="@+id/action_settings"
|
||||
|
|
|
@ -12,6 +12,21 @@
|
|||
<action
|
||||
android:id="@+id/search"
|
||||
app:destination="@id/search_fragment" />
|
||||
<action
|
||||
android:id="@+id/sort_songs"
|
||||
app:destination="@+id/song_sort_dialog" />
|
||||
<action
|
||||
android:id="@+id/sort_albums"
|
||||
app:destination="@+id/album_sort_dialog" />
|
||||
<action
|
||||
android:id="@+id/sort_artists"
|
||||
app:destination="@+id/artist_sort_dialog" />
|
||||
<action
|
||||
android:id="@+id/sort_genres"
|
||||
app:destination="@+id/genre_sort_dialog" />
|
||||
<action
|
||||
android:id="@+id/sort_playlists"
|
||||
app:destination="@+id/playlist_sort_dialog" />
|
||||
<action
|
||||
android:id="@+id/show_song"
|
||||
app:destination="@id/song_detail_dialog" />
|
||||
|
@ -65,6 +80,36 @@
|
|||
app:destination="@id/play_from_genre_dialog" />
|
||||
</fragment>
|
||||
|
||||
<dialog
|
||||
android:id="@+id/song_sort_dialog"
|
||||
android:name="org.oxycblt.auxio.home.sort.SongSortDialog"
|
||||
android:label="song_sort_dialog"
|
||||
tools:layout="@layout/dialog_sort" />
|
||||
|
||||
<dialog
|
||||
android:id="@+id/album_sort_dialog"
|
||||
android:name="org.oxycblt.auxio.home.sort.AlbumSortDialog"
|
||||
android:label="song_sort_dialog"
|
||||
tools:layout="@layout/dialog_sort" />
|
||||
|
||||
<dialog
|
||||
android:id="@+id/artist_sort_dialog"
|
||||
android:name="org.oxycblt.auxio.home.sort.ArtistSortDialog"
|
||||
android:label="song_sort_dialog"
|
||||
tools:layout="@layout/dialog_sort" />
|
||||
|
||||
<dialog
|
||||
android:id="@+id/genre_sort_dialog"
|
||||
android:name="org.oxycblt.auxio.home.sort.GenreSortDialog"
|
||||
android:label="song_sort_dialog"
|
||||
tools:layout="@layout/dialog_sort" />
|
||||
|
||||
<dialog
|
||||
android:id="@+id/playlist_sort_dialog"
|
||||
android:name="org.oxycblt.auxio.home.sort.PlaylistSortDialog"
|
||||
android:label="song_sort_dialog"
|
||||
tools:layout="@layout/dialog_sort" />
|
||||
|
||||
<dialog
|
||||
android:id="@+id/song_detail_dialog"
|
||||
android:name="org.oxycblt.auxio.detail.SongDetailDialog"
|
||||
|
|
Loading…
Reference in a new issue