music: show months in UI
If a song/album date has a month value, show it in the UI. This hopefully improves the date experience for more well-tagged libraries. Due to date limitations however, it is limited to Android O onwards for now.
This commit is contained in:
parent
f4d25f81cc
commit
daf1cf8590
28 changed files with 77 additions and 37 deletions
|
@ -22,6 +22,7 @@
|
|||
- Reshuffling the queue will no longer drop any songs you have added/removed
|
||||
- Allowed light/dark theme to be customized on Android 12+
|
||||
- All information now scrolls in the playback view
|
||||
- A month is now shown for song/album dates when available (Android O+ only)
|
||||
|
||||
#### What's Fixed
|
||||
- Fixed issue where the scroll popup would not display correctly in landscape mode [#230]
|
||||
|
|
|
@ -120,7 +120,7 @@ private class AlbumDetailViewHolder private constructor(private val binding: Ite
|
|||
|
||||
binding.detailInfo.apply {
|
||||
val date =
|
||||
item.date?.resolveYear(context)
|
||||
item.date?.resolveDate(context)
|
||||
?: context.getString(R.string.def_date)
|
||||
|
||||
val songCount = context.getPlural(R.plurals.fmt_song_count, item.songs.size)
|
||||
|
|
|
@ -159,7 +159,7 @@ private class ArtistAlbumViewHolder private constructor(private val binding: Ite
|
|||
binding.parentImage.bind(item)
|
||||
binding.parentName.text = item.resolveName(binding.context)
|
||||
binding.parentInfo.text =
|
||||
item.date?.resolveYear(binding.context)
|
||||
item.date?.resolveDate(binding.context)
|
||||
?: binding.context.getString(R.string.def_date)
|
||||
|
||||
// binding.parentMenu.setOnClickListener { listener.onOpenMenu(item, it) }
|
||||
|
|
|
@ -70,7 +70,7 @@ class AlbumListFragment : HomeListFragment<Album>() {
|
|||
is Sort.Mode.ByArtist -> album.artists[0].collationKey?.run { sourceString.first().uppercase() }
|
||||
|
||||
// Year -> Use Full Year
|
||||
is Sort.Mode.ByDate -> album.date?.resolveYear(requireContext())
|
||||
is Sort.Mode.ByDate -> album.date?.resolveDate(requireContext())
|
||||
|
||||
// Duration -> Use formatted duration
|
||||
is Sort.Mode.ByDuration -> album.durationMs.formatDurationMs(false)
|
||||
|
|
|
@ -86,7 +86,7 @@ class SongListFragment : HomeListFragment<Song>() {
|
|||
is Sort.Mode.ByAlbum -> song.album.collationKey?.run { sourceString.first().uppercase() }
|
||||
|
||||
// Year -> Use Full Year
|
||||
is Sort.Mode.ByDate -> song.album.date?.resolveYear(requireContext())
|
||||
is Sort.Mode.ByDate -> song.album.date?.resolveDate(requireContext())
|
||||
|
||||
// Duration -> Use formatted duration
|
||||
is Sort.Mode.ByDuration -> song.durationMs.formatDurationMs(false)
|
||||
|
|
|
@ -18,10 +18,21 @@
|
|||
package org.oxycblt.auxio.music
|
||||
|
||||
import android.content.Context
|
||||
import android.os.Build
|
||||
import android.text.format.DateUtils
|
||||
import androidx.annotation.RequiresApi
|
||||
import org.oxycblt.auxio.BuildConfig
|
||||
import org.oxycblt.auxio.R
|
||||
import org.oxycblt.auxio.playback.secsToMs
|
||||
import org.oxycblt.auxio.util.inRangeOrNull
|
||||
import org.oxycblt.auxio.util.logD
|
||||
import org.oxycblt.auxio.util.logE
|
||||
import org.oxycblt.auxio.util.nonZeroOrNull
|
||||
import java.time.ZoneId
|
||||
import java.time.format.DateTimeFormatter
|
||||
import java.time.temporal.TemporalQueries
|
||||
import java.util.Formatter
|
||||
import java.util.Locale
|
||||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
|
||||
|
@ -60,10 +71,7 @@ class Date private constructor(private val tokens: List<Int>) : Comparable<Date>
|
|||
}
|
||||
}
|
||||
|
||||
val year = tokens[0]
|
||||
|
||||
/** Resolve the year field in a way suitable for the UI. */
|
||||
fun resolveYear(context: Context) = context.getString(R.string.fmt_number, year)
|
||||
private val year = tokens[0]
|
||||
|
||||
private val month = tokens.getOrNull(1)
|
||||
|
||||
|
@ -75,6 +83,37 @@ class Date private constructor(private val tokens: List<Int>) : Comparable<Date>
|
|||
|
||||
private val second = tokens.getOrNull(5)
|
||||
|
||||
fun resolveDate(context: Context): String {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
return try {
|
||||
resolveFullDate(context).also { logD(it) }
|
||||
} catch (e: Exception) {
|
||||
logE("Failed to format a full date")
|
||||
logE(e.stackTraceToString())
|
||||
return resolveYear(context)
|
||||
}
|
||||
} else {
|
||||
return resolveYear(context)
|
||||
}
|
||||
}
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.O)
|
||||
private fun resolveFullDate(context: Context) =
|
||||
if( month != null ) {
|
||||
val temporal = DateTimeFormatter.ISO_DATE.parse(
|
||||
"$year-$month-${day ?: 1}",
|
||||
TemporalQueries.localDate()
|
||||
)
|
||||
|
||||
temporal.atStartOfDay(ZoneId.systemDefault())
|
||||
.format(DateTimeFormatter.ofPattern("MMM yyyy", Locale.getDefault()))
|
||||
} else {
|
||||
resolveYear(context)
|
||||
}
|
||||
|
||||
/** Resolve the year field in a way suitable for the UI. */
|
||||
private fun resolveYear(context: Context) = context.getString(R.string.fmt_number, year)
|
||||
|
||||
override fun hashCode() = tokens.hashCode()
|
||||
|
||||
override fun equals(other: Any?) = other is Date && tokens == other.tokens
|
||||
|
@ -103,20 +142,20 @@ class Date private constructor(private val tokens: List<Int>) : Comparable<Date>
|
|||
|
||||
private fun StringBuilder.appendDate(): StringBuilder {
|
||||
append(year.toFixedString(4))
|
||||
append("-${(month ?: return this).toFixedString(2)}")
|
||||
append("-${(day ?: return this).toFixedString(2)}")
|
||||
append("T${(hour ?: return this).toFixedString(2)}")
|
||||
append(":${(minute ?: return this.append('Z')).toFixedString(2)}")
|
||||
append(":${(second ?: return this.append('Z')).toFixedString(2)}")
|
||||
append("-${(month ?: 1).toFixedString(2)}")
|
||||
append("-${(day ?: 1).toFixedString(2)}")
|
||||
append("T${(hour ?: 0).toFixedString(2)}")
|
||||
append(":${(minute ?: 0).toFixedString(2)}")
|
||||
append(":${(second ?: 0).toFixedString(2)}")
|
||||
return this.append('Z')
|
||||
}
|
||||
|
||||
private fun Int.toFixedString(len: Int) = toString().padStart(len, '0')
|
||||
private fun Int.toFixedString(len: Int) = toString().padStart(len, '0').substring(0 until len)
|
||||
|
||||
companion object {
|
||||
private val ISO8601_REGEX =
|
||||
Regex(
|
||||
"""^(\d{4,})([-.](\d{2})([-.](\d{2})([T ](\d{2})([:.](\d{2})([:.](\d{2}))?)?)?)?)?$"""
|
||||
"""^(\d{4,})([-.](\d{2})([-.](\d{2})([T ](\d{2})([:.](\d{2})([:.](\d{2})(Z)?)?)?)?)?)?$"""
|
||||
)
|
||||
|
||||
fun from(year: Int) = fromTokens(listOf(year))
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
android:title="@string/lbl_album" />
|
||||
<item
|
||||
android:id="@+id/option_sort_year"
|
||||
android:title="@string/lbl_sort_year" />
|
||||
android:title="@string/lbl_sort_date" />
|
||||
<item
|
||||
android:id="@+id/option_sort_duration"
|
||||
android:title="@string/lbl_sort_duration" />
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
android:title="@string/lbl_album" />
|
||||
<item
|
||||
android:id="@+id/option_sort_year"
|
||||
android:title="@string/lbl_sort_year" />
|
||||
android:title="@string/lbl_sort_date" />
|
||||
<item
|
||||
android:id="@+id/option_sort_duration"
|
||||
android:title="@string/lbl_sort_duration" />
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
android:title="@string/lbl_album" />
|
||||
<item
|
||||
android:id="@+id/option_sort_year"
|
||||
android:title="@string/lbl_sort_year" />
|
||||
android:title="@string/lbl_sort_date" />
|
||||
<item
|
||||
android:id="@+id/option_sort_duration"
|
||||
android:title="@string/lbl_sort_duration" />
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
<string name="lbl_sort_name">اسم</string>
|
||||
<string name="lbl_artist">فنان</string>
|
||||
<string name="lbl_album">البوم</string>
|
||||
<string name="lbl_sort_year">سنة</string>
|
||||
<string name="lbl_sort_date">سنة</string>
|
||||
<string name="lbl_sort_asc">تصاعدي</string>
|
||||
<string name="lbl_playback">يعمل الآن</string>
|
||||
<string name="lbl_play">تشغيل</string>
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
<string name="lbl_sort_name">Název</string>
|
||||
<string name="lbl_artist">Umělec</string>
|
||||
<string name="lbl_album">Album</string>
|
||||
<string name="lbl_sort_year">Rok</string>
|
||||
<string name="lbl_sort_date">Rok</string>
|
||||
<string name="lbl_sort_duration">Trvání</string>
|
||||
<string name="lbl_sort_count">Počet skladeb</string>
|
||||
<string name="lbl_sort_disc">Disk</string>
|
||||
|
|
|
@ -120,7 +120,7 @@
|
|||
<string name="lng_playback">Musikwiedergabe anzeigen und kontrollieren</string>
|
||||
<string name="lbl_artist">Künstler</string>
|
||||
<string name="lbl_album">Album</string>
|
||||
<string name="lbl_sort_year">Jahr</string>
|
||||
<string name="lbl_sort_date">Jahr</string>
|
||||
<string name="set_black_mode">Schwarzes Farbschema</string>
|
||||
<string name="set_black_mode_desc">Ein rein schwarzes dunkles Farbschema verwenden</string>
|
||||
<string name="set_repeat_pause">Pause bei Wiederholung</string>
|
||||
|
|
|
@ -74,7 +74,7 @@
|
|||
<string name="fmt_disc_no">Δίσκος %d</string>
|
||||
<string name="fmt_lib_album_count">Album που φορτώθηκαν: %d</string>
|
||||
<string name="fmt_lib_artist_count">Καλλιτέχνες που φορτώθηκαν: %d</string>
|
||||
<string name="lbl_sort_year">Έτος</string>
|
||||
<string name="lbl_sort_date">Έτος</string>
|
||||
<string name="lbl_sort_disc">Δίσκος</string>
|
||||
<string name="err_no_music">Δεν βρέθηκε καθόλου μουσική</string>
|
||||
<string name="err_index_failed">Η φόρτωση μουσικής απέτυχε</string>
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
<string name="lbl_sort_name">Nombre</string>
|
||||
<string name="lbl_artist">Artista</string>
|
||||
<string name="lbl_album">Álbum</string>
|
||||
<string name="lbl_sort_year">Año</string>
|
||||
<string name="lbl_sort_date">Año</string>
|
||||
<string name="lbl_sort_asc">Ascendente</string>
|
||||
<string name="lbl_playback">En reproducción</string>
|
||||
<string name="lbl_play">Reproducir</string>
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
<string name="lbl_compilations">Mga Compilation</string>
|
||||
<string name="lbl_sort">Ayusin</string>
|
||||
<string name="lbl_sort_name">Pangalan</string>
|
||||
<string name="lbl_sort_year">Taon</string>
|
||||
<string name="lbl_sort_date">Taon</string>
|
||||
<string name="lbl_sort_duration">Tagal</string>
|
||||
<string name="lbl_sort_count">Bilang ng kanta</string>
|
||||
<string name="lbl_compilation">Compilation</string>
|
||||
|
|
|
@ -99,7 +99,7 @@
|
|||
<string name="lbl_sort_name">Nom</string>
|
||||
<string name="lbl_artist">Artiste</string>
|
||||
<string name="lbl_album">Album</string>
|
||||
<string name="lbl_sort_year">Année</string>
|
||||
<string name="lbl_sort_date">Année</string>
|
||||
<string name="lbl_sort_duration">Durée</string>
|
||||
<string name="lbl_sort_count">Nombre de chansons</string>
|
||||
<string name="lbl_sort_disc">Disque</string>
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
<string name="lbl_genres">Žanrovi</string>
|
||||
<string name="lbl_sort">Sortiraj</string>
|
||||
<string name="lbl_sort_name">Naziv</string>
|
||||
<string name="lbl_sort_year">Godina</string>
|
||||
<string name="lbl_sort_date">Godina</string>
|
||||
<string name="lbl_sort_duration">Trajanje</string>
|
||||
<string name="lbl_sort_count">Broj pjesama</string>
|
||||
<string name="lbl_sort_disc">Disk</string>
|
||||
|
|
|
@ -77,7 +77,7 @@
|
|||
<string name="info_app_desc">Pemutar musik yang simpel dan rasional untuk android.</string>
|
||||
<string name="lbl_indexer">Pemuatan Musik</string>
|
||||
<string name="lng_playback">Lihat dan kontrol pemutaran musik</string>
|
||||
<string name="lbl_sort_year">Tahun</string>
|
||||
<string name="lbl_sort_date">Tahun</string>
|
||||
<string name="lbl_sort_duration">Durasi</string>
|
||||
<string name="lbl_sort_disc">Disk</string>
|
||||
<string name="lbl_song_detail">Lihat properti</string>
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
<string name="lbl_sort_name">Nome</string>
|
||||
<string name="lbl_artist">Artista</string>
|
||||
<string name="lbl_album">Disco</string>
|
||||
<string name="lbl_sort_year">Anno</string>
|
||||
<string name="lbl_sort_date">Anno</string>
|
||||
<string name="lbl_sort_asc">Ascendente</string>
|
||||
<string name="lbl_playback">Ora in riproduzione</string>
|
||||
<string name="lbl_play">Riproduci</string>
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
<string name="lbl_sort_name">제목</string>
|
||||
<string name="lbl_artist">아티스트</string>
|
||||
<string name="lbl_album">앨범</string>
|
||||
<string name="lbl_sort_year">연도</string>
|
||||
<string name="lbl_sort_date">연도</string>
|
||||
<string name="lbl_sort_duration">길이</string>
|
||||
<string name="lbl_sort_count">곡 수</string>
|
||||
<string name="lbl_sort_disc">디스크</string>
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<string name="lbl_filter_all">Visos</string>
|
||||
<string name="lbl_sort">Rūšiuoti</string>
|
||||
<string name="lbl_sort_name">Pavadinimas</string>
|
||||
<string name="lbl_sort_year">Metai</string>
|
||||
<string name="lbl_sort_date">Metai</string>
|
||||
<string name="lbl_sort_duration">Trukmė</string>
|
||||
<string name="lbl_sort_count">Dainų skaičius</string>
|
||||
<string name="lbl_sort_disc">Diskas</string>
|
||||
|
|
|
@ -121,7 +121,7 @@
|
|||
<string name="lbl_artist">Artiest</string>
|
||||
<string name="lbl_cancel">@android:string/cancel</string>
|
||||
<string name="set_lib_tabs">Bibliotheek tabbladen</string>
|
||||
<string name="lbl_sort_year">Jaar</string>
|
||||
<string name="lbl_sort_date">Jaar</string>
|
||||
<string name="lbl_relative_path">Ouderpad</string>
|
||||
<string name="lbl_props">Lied eigenschappen</string>
|
||||
<string name="lbl_file_name">Bestandsnaam</string>
|
||||
|
|
|
@ -119,7 +119,7 @@
|
|||
<string name="clr_deep_purple">Ciemny fiolet</string>
|
||||
<string name="fmt_db_neg">-%.1f dB</string>
|
||||
<string name="lbl_sort_name">Nazwa</string>
|
||||
<string name="lbl_sort_year">Rok</string>
|
||||
<string name="lbl_sort_date">Rok</string>
|
||||
<string name="lbl_single">Singiel</string>
|
||||
<string name="lbl_singles">Single</string>
|
||||
<string name="lbl_sort_duration">Czas trwania</string>
|
||||
|
|
|
@ -97,7 +97,7 @@
|
|||
<string name="err_no_perms">O Auxio precisa de permissão para ler sua biblioteca de músicas</string>
|
||||
<string name="info_app_desc">Um leitor de música simples e racional para android.</string>
|
||||
<string name="lng_indexing">Carregando sua biblioteca de músicas…</string>
|
||||
<string name="lbl_sort_year">Ano</string>
|
||||
<string name="lbl_sort_date">Ano</string>
|
||||
<string name="lbl_sort_duration">Duração</string>
|
||||
<string name="lbl_sort_count">Contagem de músicas</string>
|
||||
<string name="lbl_sort_disc">Disco</string>
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
<string name="lbl_sort_name">Название</string>
|
||||
<string name="lbl_artist">Исполнитель</string>
|
||||
<string name="lbl_album">Альбом</string>
|
||||
<string name="lbl_sort_year">Год</string>
|
||||
<string name="lbl_sort_date">Год</string>
|
||||
<string name="lbl_sort_asc">По возрастанию</string>
|
||||
<string name="lbl_playback">Сейчас играет</string>
|
||||
<string name="lbl_play">Играть</string>
|
||||
|
|
|
@ -78,7 +78,7 @@
|
|||
<string name="lbl_sort_name">İsim</string>
|
||||
<string name="lbl_artist">Sanatçı</string>
|
||||
<string name="lbl_album">Albüm</string>
|
||||
<string name="lbl_sort_year">Yıl</string>
|
||||
<string name="lbl_sort_date">Yıl</string>
|
||||
<string name="lbl_sort_duration">Süre</string>
|
||||
<string name="lbl_state_saved">Durum kaydedildi</string>
|
||||
<string name="lng_author">OxygenCobalt tarafından geliştirildi</string>
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
<string name="lbl_sort_name">名称</string>
|
||||
<string name="lbl_artist">艺术家</string>
|
||||
<string name="lbl_album">专辑</string>
|
||||
<string name="lbl_sort_year">年份</string>
|
||||
<string name="lbl_sort_date">年份</string>
|
||||
<string name="lbl_sort_asc">首字符(正序)</string>
|
||||
<string name="lbl_playback">正在播放</string>
|
||||
<string name="lbl_play">播放</string>
|
||||
|
|
|
@ -85,7 +85,7 @@
|
|||
|
||||
<string name="lbl_sort">Sort</string>
|
||||
<string name="lbl_sort_name">Name</string>
|
||||
<string name="lbl_sort_year">Year</string>
|
||||
<string name="lbl_sort_date">Date</string>
|
||||
<string name="lbl_sort_duration">Duration</string>
|
||||
<string name="lbl_sort_count">Song count</string>
|
||||
<string name="lbl_sort_disc">Disc</string>
|
||||
|
|
Loading…
Reference in a new issue