util: fix number issues

Fix issues where invalid durations and years would not be aliased to
readable values.
This commit is contained in:
OxygenCobalt 2022-01-08 08:59:11 -07:00
parent e099d1c38c
commit 13730c303c
No known key found for this signature in database
GPG key ID: 37DBE3621FE9AD47
8 changed files with 55 additions and 20 deletions

View file

@ -31,6 +31,7 @@ import org.oxycblt.auxio.music.ActionHeader
import org.oxycblt.auxio.music.Album import org.oxycblt.auxio.music.Album
import org.oxycblt.auxio.music.BaseModel import org.oxycblt.auxio.music.BaseModel
import org.oxycblt.auxio.music.Song import org.oxycblt.auxio.music.Song
import org.oxycblt.auxio.music.toDate
import org.oxycblt.auxio.playback.PlaybackViewModel import org.oxycblt.auxio.playback.PlaybackViewModel
import org.oxycblt.auxio.ui.ActionHeaderViewHolder import org.oxycblt.auxio.ui.ActionHeaderViewHolder
import org.oxycblt.auxio.ui.BaseViewHolder import org.oxycblt.auxio.ui.BaseViewHolder
@ -154,7 +155,7 @@ class AlbumDetailAdapter(
binding.detailInfo.text = binding.detailInfo.context.getString( binding.detailInfo.text = binding.detailInfo.context.getString(
R.string.fmt_three, R.string.fmt_three,
data.year.toString(), data.year.toDate(binding.detailInfo.context),
binding.detailInfo.context.getPlural( binding.detailInfo.context.getPlural(
R.plurals.fmt_song_count, R.plurals.fmt_song_count,
data.songs.size data.songs.size

View file

@ -26,6 +26,7 @@ import androidx.navigation.fragment.findNavController
import org.oxycblt.auxio.R import org.oxycblt.auxio.R
import org.oxycblt.auxio.home.HomeFragmentDirections import org.oxycblt.auxio.home.HomeFragmentDirections
import org.oxycblt.auxio.music.Album import org.oxycblt.auxio.music.Album
import org.oxycblt.auxio.music.toDate
import org.oxycblt.auxio.ui.AlbumViewHolder import org.oxycblt.auxio.ui.AlbumViewHolder
import org.oxycblt.auxio.ui.DisplayMode import org.oxycblt.auxio.ui.DisplayMode
import org.oxycblt.auxio.ui.Sort import org.oxycblt.auxio.ui.Sort
@ -73,7 +74,7 @@ class AlbumListFragment : HomeListFragment() {
.first().uppercase() .first().uppercase()
// Year -> Use Full Year // Year -> Use Full Year
is Sort.ByYear -> album.year.toString() is Sort.ByYear -> album.year.toDate(requireContext())
// Unsupported sort, error gracefully // Unsupported sort, error gracefully
else -> "" else -> ""

View file

@ -24,6 +24,7 @@ import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import org.oxycblt.auxio.R import org.oxycblt.auxio.R
import org.oxycblt.auxio.music.Song import org.oxycblt.auxio.music.Song
import org.oxycblt.auxio.music.toDate
import org.oxycblt.auxio.ui.DisplayMode import org.oxycblt.auxio.ui.DisplayMode
import org.oxycblt.auxio.ui.SongViewHolder import org.oxycblt.auxio.ui.SongViewHolder
import org.oxycblt.auxio.ui.Sort import org.oxycblt.auxio.ui.Sort
@ -74,7 +75,7 @@ class SongListFragment : HomeListFragment() {
.first().uppercase() .first().uppercase()
// Year -> Use Full Year // Year -> Use Full Year
is Sort.ByYear -> song.album.year.toString() is Sort.ByYear -> song.album.year.toDate(requireContext())
} }
} }

View file

@ -84,7 +84,7 @@ data class Song(
val album: Album get() = requireNotNull(mAlbum) val album: Album get() = requireNotNull(mAlbum)
val seconds: Long get() = duration / 1000 val seconds: Long get() = duration / 1000
val formattedDuration: String get() = (duration / 1000).toDuration() val formattedDuration: String get() = (duration / 1000).toDuration(false)
override val hash: Long get() { override val hash: Long get() {
var result = name.hashCode().toLong() var result = name.hashCode().toLong()
@ -129,7 +129,7 @@ data class Album(
val artist: Artist get() = requireNotNull(mArtist) val artist: Artist get() = requireNotNull(mArtist)
val totalDuration: String get() = val totalDuration: String get() =
songs.sumOf { it.seconds }.toDuration() songs.sumOf { it.seconds }.toDuration(false)
fun linkArtist(artist: Artist) { fun linkArtist(artist: Artist) {
mArtist = artist mArtist = artist
@ -190,7 +190,7 @@ data class Genre(
val songs: List<Song> get() = mSongs val songs: List<Song> get() = mSongs
val totalDuration: String get() = val totalDuration: String get() =
songs.sumOf { it.seconds }.toDuration() songs.sumOf { it.seconds }.toDuration(false)
fun linkSong(song: Song) { fun linkSong(song: Song) {
mSongs.add(song) mSongs.add(song)

View file

@ -19,6 +19,7 @@
package org.oxycblt.auxio.music package org.oxycblt.auxio.music
import android.content.ContentUris import android.content.ContentUris
import android.content.Context
import android.net.Uri import android.net.Uri
import android.provider.MediaStore import android.provider.MediaStore
import android.text.format.DateUtils import android.text.format.DateUtils
@ -109,8 +110,14 @@ fun Long.toAlbumArtURI(): Uri {
/** /**
* Convert a [Long] of seconds into a string duration. * Convert a [Long] of seconds into a string duration.
* @param isElapsed Whether this duration is represents elapsed time. If this is false, then
* --:-- will be returned if the second value is 0.
*/ */
fun Long.toDuration(): String { fun Long.toDuration(isElapsed: Boolean): String {
if (!isElapsed && this == 0L) {
return "--:--"
}
var durationString = DateUtils.formatElapsedTime(this) var durationString = DateUtils.formatElapsedTime(this)
// If the duration begins with a excess zero [e.g 01:42], then cut it off. // If the duration begins with a excess zero [e.g 01:42], then cut it off.
@ -121,6 +128,14 @@ fun Long.toDuration(): String {
return durationString return durationString
} }
fun Int.toDate(context: Context): String {
return if (this == 0) {
context.getString(R.string.def_date)
} else {
toString()
}
}
// --- BINDING ADAPTERS --- // --- BINDING ADAPTERS ---
/** /**

View file

@ -29,7 +29,6 @@ import org.oxycblt.auxio.databinding.ViewSeekBarBinding
import org.oxycblt.auxio.music.toDuration import org.oxycblt.auxio.music.toDuration
import org.oxycblt.auxio.util.inflater import org.oxycblt.auxio.util.inflater
import org.oxycblt.auxio.util.resolveAttr import org.oxycblt.auxio.util.resolveAttr
import kotlin.math.max
/** /**
* A custom view that bundles together a seekbar with a current duration and a total duration. * A custom view that bundles together a seekbar with a current duration and a total duration.
@ -63,13 +62,29 @@ class PlaybackSeekBar @JvmOverloads constructor(
// Don't update the progress while we are seeking, that will make the SeekBar jump around. // Don't update the progress while we are seeking, that will make the SeekBar jump around.
if (!isSeeking) { if (!isSeeking) {
binding.seekBar.value = seconds.toFloat() binding.seekBar.value = seconds.toFloat()
binding.playbackDurationCurrent.text = seconds.toDuration() binding.playbackDurationCurrent.text = seconds.toDuration(true)
} }
} }
fun setDuration(seconds: Long) { fun setDuration(seconds: Long) {
binding.seekBar.valueTo = max(seconds.toFloat(), 1f) if (seconds == 0L) {
binding.playbackSongDuration.text = seconds.toDuration() // One of two things occured:
// - Android couldn't get the total duration of the song
// - The duration of the song was so low as to be rounded to zero when converted
// to seconds.
// In either of these cases, the seekbar is more or less useless. Disable it.
binding.seekBar.apply {
valueTo = 1f
isEnabled = false
}
} else {
binding.seekBar.apply {
valueTo = seconds.toFloat()
isEnabled = true
}
}
binding.playbackSongDuration.text = seconds.toDuration(false)
} }
override fun onStartTrackingTouch(slider: Slider) { override fun onStartTrackingTouch(slider: Slider) {
@ -85,7 +100,7 @@ class PlaybackSeekBar @JvmOverloads constructor(
if (fromUser) { if (fromUser) {
// Don't actually seek yet when the user moves the progress bar, as to make our // Don't actually seek yet when the user moves the progress bar, as to make our
// player seek during every movement is both inefficient and weird. // player seek during every movement is both inefficient and weird.
binding.playbackDurationCurrent.text = value.toLong().toDuration() binding.playbackDurationCurrent.text = value.toLong().toDuration(true)
} }
} }
} }

View file

@ -333,14 +333,14 @@ class PlaybackViewModel : ViewModel(), PlaybackStateManager.Callback {
private fun restorePlaybackState() { private fun restorePlaybackState() {
logD("Attempting to restore playback state.") logD("Attempting to restore playback state.")
mSong.value = playbackManager.song onSongUpdate(playbackManager.song)
mPosition.value = playbackManager.position / 1000 onPositionUpdate(playbackManager.position)
mParent.value = playbackManager.parent onParentUpdate(playbackManager.parent)
mNextUp.value = playbackManager.queue onQueueUpdate(playbackManager.queue, playbackManager.index)
mMode.value = playbackManager.playbackMode onModeUpdate(playbackManager.playbackMode)
mIsPlaying.value = playbackManager.isPlaying onPlayingUpdate(playbackManager.isPlaying)
mIsShuffling.value = playbackManager.isShuffling onShuffleUpdate(playbackManager.isShuffling)
mLoopMode.value = playbackManager.loopMode onLoopUpdate(playbackManager.loopMode)
} }
// --- OVERRIDES --- // --- OVERRIDES ---

View file

@ -99,6 +99,8 @@ class PlaybackStateManager private constructor() {
val position: Long get() = mPosition val position: Long get() = mPosition
/** The current queue determined by [parent] and [playbackMode] */ /** The current queue determined by [parent] and [playbackMode] */
val queue: List<Song> get() = mQueue val queue: List<Song> get() = mQueue
/** The current position in the queue */
val index: Int get() = mIndex
/** The current [PlaybackMode] */ /** The current [PlaybackMode] */
val playbackMode: PlaybackMode get() = mPlaybackMode val playbackMode: PlaybackMode get() = mPlaybackMode
/** Whether playback is paused or not */ /** Whether playback is paused or not */