detail: default to "no disc" instead of "disc 1"
Default tracks without a disc to a group called "No disc" instead of disc 1. This should reduce confusion on the user end, as it will make improper taggings more apparent instead of simply degrading to a werid sort ordering. Resolves #405.
This commit is contained in:
parent
4210a8d247
commit
8939d341e6
3 changed files with 30 additions and 18 deletions
|
@ -30,6 +30,7 @@ import kotlinx.coroutines.flow.StateFlow
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.yield
|
import kotlinx.coroutines.yield
|
||||||
import org.oxycblt.auxio.R
|
import org.oxycblt.auxio.R
|
||||||
|
import org.oxycblt.auxio.detail.list.DiscHeader
|
||||||
import org.oxycblt.auxio.detail.list.EditHeader
|
import org.oxycblt.auxio.detail.list.EditHeader
|
||||||
import org.oxycblt.auxio.detail.list.SortHeader
|
import org.oxycblt.auxio.detail.list.SortHeader
|
||||||
import org.oxycblt.auxio.list.BasicHeader
|
import org.oxycblt.auxio.list.BasicHeader
|
||||||
|
@ -46,7 +47,6 @@ import org.oxycblt.auxio.music.MusicRepository
|
||||||
import org.oxycblt.auxio.music.MusicSettings
|
import org.oxycblt.auxio.music.MusicSettings
|
||||||
import org.oxycblt.auxio.music.Playlist
|
import org.oxycblt.auxio.music.Playlist
|
||||||
import org.oxycblt.auxio.music.Song
|
import org.oxycblt.auxio.music.Song
|
||||||
import org.oxycblt.auxio.music.info.Disc
|
|
||||||
import org.oxycblt.auxio.music.info.ReleaseType
|
import org.oxycblt.auxio.music.info.ReleaseType
|
||||||
import org.oxycblt.auxio.music.metadata.AudioProperties
|
import org.oxycblt.auxio.music.metadata.AudioProperties
|
||||||
import org.oxycblt.auxio.playback.PlaybackSettings
|
import org.oxycblt.auxio.playback.PlaybackSettings
|
||||||
|
@ -409,12 +409,11 @@ constructor(
|
||||||
// To create a good user experience regarding disc numbers, we group the album's
|
// To create a good user experience regarding disc numbers, we group the album's
|
||||||
// songs up by disc and then delimit the groups by a disc header.
|
// songs up by disc and then delimit the groups by a disc header.
|
||||||
val songs = albumSongSort.songs(album.songs)
|
val songs = albumSongSort.songs(album.songs)
|
||||||
// Songs without disc tags become part of Disc 1.
|
val byDisc = songs.groupBy { it.disc }
|
||||||
val byDisc = songs.groupBy { it.disc ?: Disc(1, null) }
|
|
||||||
if (byDisc.size > 1) {
|
if (byDisc.size > 1) {
|
||||||
logD("Album has more than one disc, interspersing headers")
|
logD("Album has more than one disc, interspersing headers")
|
||||||
for (entry in byDisc.entries) {
|
for (entry in byDisc.entries) {
|
||||||
list.add(entry.key)
|
list.add(DiscHeader(entry.key))
|
||||||
list.addAll(entry.value)
|
list.addAll(entry.value)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -49,14 +49,14 @@ class AlbumDetailListAdapter(private val listener: Listener<Song>) :
|
||||||
override fun getItemViewType(position: Int) =
|
override fun getItemViewType(position: Int) =
|
||||||
when (getItem(position)) {
|
when (getItem(position)) {
|
||||||
// Support sub-headers for each disc, and special album songs.
|
// Support sub-headers for each disc, and special album songs.
|
||||||
is Disc -> DiscViewHolder.VIEW_TYPE
|
is DiscHeader -> DiscHeaderViewHolder.VIEW_TYPE
|
||||||
is Song -> AlbumSongViewHolder.VIEW_TYPE
|
is Song -> AlbumSongViewHolder.VIEW_TYPE
|
||||||
else -> super.getItemViewType(position)
|
else -> super.getItemViewType(position)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) =
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) =
|
||||||
when (viewType) {
|
when (viewType) {
|
||||||
DiscViewHolder.VIEW_TYPE -> DiscViewHolder.from(parent)
|
DiscHeaderViewHolder.VIEW_TYPE -> DiscHeaderViewHolder.from(parent)
|
||||||
AlbumSongViewHolder.VIEW_TYPE -> AlbumSongViewHolder.from(parent)
|
AlbumSongViewHolder.VIEW_TYPE -> AlbumSongViewHolder.from(parent)
|
||||||
else -> super.onCreateViewHolder(parent, viewType)
|
else -> super.onCreateViewHolder(parent, viewType)
|
||||||
}
|
}
|
||||||
|
@ -64,7 +64,7 @@ class AlbumDetailListAdapter(private val listener: Listener<Song>) :
|
||||||
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
|
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
|
||||||
super.onBindViewHolder(holder, position)
|
super.onBindViewHolder(holder, position)
|
||||||
when (val item = getItem(position)) {
|
when (val item = getItem(position)) {
|
||||||
is Disc -> (holder as DiscViewHolder).bind(item)
|
is DiscHeader -> (holder as DiscHeaderViewHolder).bind(item)
|
||||||
is Song -> (holder as AlbumSongViewHolder).bind(item, listener)
|
is Song -> (holder as AlbumSongViewHolder).bind(item, listener)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -76,7 +76,7 @@ class AlbumDetailListAdapter(private val listener: Listener<Song>) :
|
||||||
override fun areContentsTheSame(oldItem: Item, newItem: Item) =
|
override fun areContentsTheSame(oldItem: Item, newItem: Item) =
|
||||||
when {
|
when {
|
||||||
oldItem is Disc && newItem is Disc ->
|
oldItem is Disc && newItem is Disc ->
|
||||||
DiscViewHolder.DIFF_CALLBACK.areContentsTheSame(oldItem, newItem)
|
DiscHeaderViewHolder.DIFF_CALLBACK.areContentsTheSame(oldItem, newItem)
|
||||||
oldItem is Song && newItem is Song ->
|
oldItem is Song && newItem is Song ->
|
||||||
AlbumSongViewHolder.DIFF_CALLBACK.areContentsTheSame(oldItem, newItem)
|
AlbumSongViewHolder.DIFF_CALLBACK.areContentsTheSame(oldItem, newItem)
|
||||||
|
|
||||||
|
@ -88,23 +88,35 @@ class AlbumDetailListAdapter(private val listener: Listener<Song>) :
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A [RecyclerView.ViewHolder] that displays a [Disc] to delimit different disc groups. Use [from]
|
* A wrapper around [Disc] signifying that a header should be shown for a disc group.
|
||||||
* to create an instance.
|
* @author Alexander Capehart (OxygenCobalt)
|
||||||
|
*/
|
||||||
|
data class DiscHeader(val inner: Disc?) : Item
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A [RecyclerView.ViewHolder] that displays a [DiscHeader] to delimit different disc groups. Use
|
||||||
|
* [from] to create an instance.
|
||||||
*
|
*
|
||||||
* @author Alexander Capehart (OxygenCobalt)
|
* @author Alexander Capehart (OxygenCobalt)
|
||||||
*/
|
*/
|
||||||
private class DiscViewHolder(private val binding: ItemDiscHeaderBinding) :
|
private class DiscHeaderViewHolder(private val binding: ItemDiscHeaderBinding) :
|
||||||
RecyclerView.ViewHolder(binding.root) {
|
RecyclerView.ViewHolder(binding.root) {
|
||||||
/**
|
/**
|
||||||
* Bind new data to this instance.
|
* Bind new data to this instance.
|
||||||
*
|
*
|
||||||
* @param disc The new [disc] to bind.
|
* @param discHeader The new [DiscHeader] to bind.
|
||||||
*/
|
*/
|
||||||
fun bind(disc: Disc) {
|
fun bind(discHeader: DiscHeader) {
|
||||||
|
val disc = discHeader.inner
|
||||||
|
if (disc != null) {
|
||||||
binding.discNumber.text = binding.context.getString(R.string.fmt_disc_no, disc.number)
|
binding.discNumber.text = binding.context.getString(R.string.fmt_disc_no, disc.number)
|
||||||
binding.discName.apply {
|
binding.discName.apply {
|
||||||
text = disc.name
|
text = disc.name
|
||||||
isGone = disc.name == null
|
isGone = text == null
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
binding.discNumber.text = binding.context.getString(R.string.def_disc)
|
||||||
|
binding.discName.isGone = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,7 +131,7 @@ private class DiscViewHolder(private val binding: ItemDiscHeaderBinding) :
|
||||||
* @return A new instance.
|
* @return A new instance.
|
||||||
*/
|
*/
|
||||||
fun from(parent: View) =
|
fun from(parent: View) =
|
||||||
DiscViewHolder(ItemDiscHeaderBinding.inflate(parent.context.inflater))
|
DiscHeaderViewHolder(ItemDiscHeaderBinding.inflate(parent.context.inflater))
|
||||||
|
|
||||||
/** A comparator that can be used with DiffUtil. */
|
/** A comparator that can be used with DiffUtil. */
|
||||||
val DIFF_CALLBACK =
|
val DIFF_CALLBACK =
|
||||||
|
|
|
@ -332,6 +332,7 @@
|
||||||
<string name="def_artist">Unknown artist</string>
|
<string name="def_artist">Unknown artist</string>
|
||||||
<string name="def_genre">Unknown genre</string>
|
<string name="def_genre">Unknown genre</string>
|
||||||
<string name="def_date">No date</string>
|
<string name="def_date">No date</string>
|
||||||
|
<string name="def_disc">No disc</string>
|
||||||
<string name="def_track">No track</string>
|
<string name="def_track">No track</string>
|
||||||
<string name="def_song_count">No songs</string>
|
<string name="def_song_count">No songs</string>
|
||||||
<string name="def_playback">No music playing</string>
|
<string name="def_playback">No music playing</string>
|
||||||
|
|
Loading…
Reference in a new issue