all: remove databinding

Remove databinding entirely.

Databinding was a terrible idea for Auxio. I rarely leveraged it, and
when I did, it produced messy code and bloated build times. Dumpster it
for just viewbinding, which is good. This reduces building times by
nearly 2/3, and generally makes the codebase more coherent and usable.
This commit is contained in:
OxygenCobalt 2022-03-23 10:53:47 -06:00
parent 95057ec357
commit d79592e029
No known key found for this signature in database
GPG key ID: 37DBE3621FE9AD47
61 changed files with 861 additions and 1307 deletions

View file

@ -17,7 +17,7 @@ android {
targetSdkVersion 32 targetSdkVersion 32
buildFeatures { buildFeatures {
dataBinding true viewBinding true
} }
} }

View file

@ -26,8 +26,6 @@ import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.app.AppCompatDelegate import androidx.appcompat.app.AppCompatDelegate
import androidx.core.view.updatePadding import androidx.core.view.updatePadding
import androidx.databinding.DataBindingUtil
import androidx.viewbinding.ViewBinding
import org.oxycblt.auxio.databinding.ActivityMainBinding import org.oxycblt.auxio.databinding.ActivityMainBinding
import org.oxycblt.auxio.playback.PlaybackViewModel import org.oxycblt.auxio.playback.PlaybackViewModel
import org.oxycblt.auxio.playback.system.PlaybackService import org.oxycblt.auxio.playback.system.PlaybackService
@ -54,10 +52,9 @@ class MainActivity : AppCompatActivity() {
setupTheme() setupTheme()
val binding = val binding = ActivityMainBinding.inflate(layoutInflater)
DataBindingUtil.setContentView<ActivityMainBinding>(this, R.layout.activity_main) setContentView(binding.root)
applyEdgeToEdgeWindow(binding.root)
applyEdgeToEdgeWindow(binding)
logD("Activity created") logD("Activity created")
} }
@ -114,7 +111,7 @@ class MainActivity : AppCompatActivity() {
} }
} }
private fun applyEdgeToEdgeWindow(binding: ViewBinding) { private fun applyEdgeToEdgeWindow(contentView: View) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
logD("Doing R+ edge-to-edge") logD("Doing R+ edge-to-edge")
@ -124,7 +121,7 @@ class MainActivity : AppCompatActivity() {
// the R+ SDK decides to make you specify the insets yourself with a barely // the R+ SDK decides to make you specify the insets yourself with a barely
// documented API that isn't even mentioned in any of the edge-to-edge // documented API that isn't even mentioned in any of the edge-to-edge
// tutorials. Thanks android, very cool! // tutorials. Thanks android, very cool!
binding.root.setOnApplyWindowInsetsListener { _, insets -> contentView.setOnApplyWindowInsetsListener { view, insets ->
WindowInsets.Builder() WindowInsets.Builder()
.setInsets( .setInsets(
WindowInsets.Type.systemBars(), WindowInsets.Type.systemBars(),
@ -133,27 +130,25 @@ class MainActivity : AppCompatActivity() {
WindowInsets.Type.systemGestures(), WindowInsets.Type.systemGestures(),
insets.getInsetsIgnoringVisibility(WindowInsets.Type.systemGestures())) insets.getInsetsIgnoringVisibility(WindowInsets.Type.systemGestures()))
.build() .build()
.applyLeftRightInsets(binding) .applyLeftRightInsets(view)
} }
} else { } else {
// Do old edge-to-edge otherwise. // Do old edge-to-edge otherwise.
logD("Doing legacy edge-to-edge") logD("Doing legacy edge-to-edge")
@Suppress("DEPRECATION") @Suppress("DEPRECATION")
binding.root.apply { contentView.apply {
systemUiVisibility = systemUiVisibility =
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_LAYOUT_STABLE View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_LAYOUT_STABLE
setOnApplyWindowInsetsListener { _, insets -> insets.applyLeftRightInsets(binding) } setOnApplyWindowInsetsListener { view, insets -> insets.applyLeftRightInsets(view) }
} }
} }
} }
private fun WindowInsets.applyLeftRightInsets(binding: ViewBinding): WindowInsets { private fun WindowInsets.applyLeftRightInsets(contentView: View): WindowInsets {
val bars = systemBarInsetsCompat val bars = systemBarInsetsCompat
contentView.updatePadding(left = bars.left, right = bars.right)
binding.root.updatePadding(left = bars.left, right = bars.right)
return replaceSystemBarInsetsCompat(0, bars.top, 0, bars.bottom) return replaceSystemBarInsetsCompat(0, bars.top, 0, bars.bottom)
} }

View file

@ -23,7 +23,6 @@ import android.widget.ImageView
import androidx.annotation.DrawableRes import androidx.annotation.DrawableRes
import androidx.annotation.StringRes import androidx.annotation.StringRes
import androidx.core.graphics.drawable.toBitmap import androidx.core.graphics.drawable.toBitmap
import androidx.databinding.BindingAdapter
import coil.dispose import coil.dispose
import coil.imageLoader import coil.imageLoader
import coil.load import coil.load
@ -39,28 +38,25 @@ import org.oxycblt.auxio.music.Song
// --- BINDING ADAPTERS --- // --- BINDING ADAPTERS ---
/** Bind the album cover for a [song]. */ /** Bind the album cover for a [song]. */
@BindingAdapter("albumArt") fun ImageView.applyAlbumCover(song: Song?) =
fun ImageView.bindAlbumCover(song: Song?) =
load(song, R.drawable.ic_album, R.string.desc_album_cover) load(song, R.drawable.ic_album, R.string.desc_album_cover)
/** Bind the album cover for an [album]. */ /** Bind the album cover for an [album]. */
@BindingAdapter("albumArt") fun ImageView.applyAlbumCover(album: Album?) =
fun ImageView.bindAlbumCover(album: Album?) =
load(album, R.drawable.ic_album, R.string.desc_album_cover) load(album, R.drawable.ic_album, R.string.desc_album_cover)
/** Bind the image for an [artist] */ /** Bind the image for an [artist] */
@BindingAdapter("artistImage") fun ImageView.applyArtistImage(artist: Artist?) =
fun ImageView.bindArtistImage(artist: Artist?) =
load(artist, R.drawable.ic_artist, R.string.desc_artist_image) load(artist, R.drawable.ic_artist, R.string.desc_artist_image)
/** Bind the image for a [genre] */ /** Bind the image for a [genre] */
@BindingAdapter("genreImage") fun ImageView.applyGenreImage(genre: Genre?) =
fun ImageView.bindGenreImage(genre: Genre?) =
load(genre, R.drawable.ic_genre, R.string.desc_genre_image) load(genre, R.drawable.ic_genre, R.string.desc_genre_image)
fun <T : Music> ImageView.load(music: T?, @DrawableRes error: Int, @StringRes desc: Int) { fun <T : Music> ImageView.load(music: T?, @DrawableRes error: Int, @StringRes desc: Int) {
contentDescription = context.getString(desc, music?.resolvedName) contentDescription = context.getString(desc, music?.resolvedName)
dispose() dispose()
scaleType = ImageView.ScaleType.FIT_CENTER
load(music) { load(music) {
error(error) error(error)
transformations(SquareFrameTransform.INSTANCE) transformations(SquareFrameTransform.INSTANCE)

View file

@ -24,7 +24,7 @@ import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import org.oxycblt.auxio.IntegerTable import org.oxycblt.auxio.IntegerTable
import org.oxycblt.auxio.R import org.oxycblt.auxio.R
import org.oxycblt.auxio.coil.bindAlbumCover import org.oxycblt.auxio.coil.applyAlbumCover
import org.oxycblt.auxio.databinding.ItemAlbumSongBinding import org.oxycblt.auxio.databinding.ItemAlbumSongBinding
import org.oxycblt.auxio.databinding.ItemDetailBinding import org.oxycblt.auxio.databinding.ItemDetailBinding
import org.oxycblt.auxio.detail.DetailViewModel import org.oxycblt.auxio.detail.DetailViewModel
@ -32,12 +32,14 @@ import org.oxycblt.auxio.music.ActionHeader
import org.oxycblt.auxio.music.Album import org.oxycblt.auxio.music.Album
import org.oxycblt.auxio.music.Item import org.oxycblt.auxio.music.Item
import org.oxycblt.auxio.music.Song import org.oxycblt.auxio.music.Song
import org.oxycblt.auxio.music.toDuration
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
import org.oxycblt.auxio.ui.DiffCallback import org.oxycblt.auxio.ui.DiffCallback
import org.oxycblt.auxio.util.getPluralSafe import org.oxycblt.auxio.util.getPluralSafe
import org.oxycblt.auxio.util.inflater import org.oxycblt.auxio.util.inflater
import org.oxycblt.auxio.util.textSafe
/** /**
* An adapter for displaying the details and [Song]s of an [Album] * An adapter for displaying the details and [Song]s of an [Album]
@ -127,14 +129,14 @@ class AlbumDetailAdapter(
override fun onBind(data: Album) { override fun onBind(data: Album) {
binding.detailCover.apply { binding.detailCover.apply {
bindAlbumCover(data) applyAlbumCover(data)
contentDescription = context.getString(R.string.desc_album_cover, data.resolvedName) contentDescription = context.getString(R.string.desc_album_cover, data.resolvedName)
} }
binding.detailName.text = data.resolvedName binding.detailName.textSafe = data.resolvedName
binding.detailSubhead.apply { binding.detailSubhead.apply {
text = data.artist.resolvedName textSafe = data.artist.resolvedName
setOnClickListener { detailModel.navToItem(data.artist) } setOnClickListener { detailModel.navToItem(data.artist) }
} }
@ -157,14 +159,25 @@ class AlbumDetailAdapter(
private val binding: ItemAlbumSongBinding, private val binding: ItemAlbumSongBinding,
) : BaseViewHolder<Song>(binding, doOnClick, doOnLongClick), Highlightable { ) : BaseViewHolder<Song>(binding, doOnClick, doOnLongClick), Highlightable {
override fun onBind(data: Song) { override fun onBind(data: Song) {
binding.song = data // Hide the track number view if the song does not have a track.
binding.songName.requestLayout() if (data.track != null) {
binding.songTrack.apply {
textSafe = context.getString(R.string.fmt_number, data.track)
isInvisible = false
}
// Hide the track number view if the track is zero, as generally a track number of binding.songTrackPlaceholder.isInvisible = true
// zero implies that the song does not have a track number. } else {
val usePlaceholder = data.track == null binding.songTrack.apply {
binding.songTrack.isInvisible = usePlaceholder textSafe = ""
binding.songTrackPlaceholder.isInvisible = !usePlaceholder isInvisible = true
}
binding.songTrackPlaceholder.isInvisible = false
}
binding.songName.textSafe = data.resolvedName
binding.songDuration.textSafe = data.seconds.toDuration(false)
} }
override fun setHighlighted(isHighlighted: Boolean) { override fun setHighlighted(isHighlighted: Boolean) {

View file

@ -23,23 +23,26 @@ import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import org.oxycblt.auxio.IntegerTable import org.oxycblt.auxio.IntegerTable
import org.oxycblt.auxio.R import org.oxycblt.auxio.R
import org.oxycblt.auxio.coil.bindArtistImage import org.oxycblt.auxio.coil.applyAlbumCover
import org.oxycblt.auxio.databinding.ItemArtistAlbumBinding import org.oxycblt.auxio.coil.applyArtistImage
import org.oxycblt.auxio.databinding.ItemArtistSongBinding
import org.oxycblt.auxio.databinding.ItemDetailBinding import org.oxycblt.auxio.databinding.ItemDetailBinding
import org.oxycblt.auxio.databinding.ItemParentBinding
import org.oxycblt.auxio.databinding.ItemSongBinding
import org.oxycblt.auxio.music.ActionHeader import org.oxycblt.auxio.music.ActionHeader
import org.oxycblt.auxio.music.Album import org.oxycblt.auxio.music.Album
import org.oxycblt.auxio.music.Artist import org.oxycblt.auxio.music.Artist
import org.oxycblt.auxio.music.Header import org.oxycblt.auxio.music.Header
import org.oxycblt.auxio.music.Item import org.oxycblt.auxio.music.Item
import org.oxycblt.auxio.music.Song import org.oxycblt.auxio.music.Song
import org.oxycblt.auxio.music.bindArtistInfo
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
import org.oxycblt.auxio.ui.DiffCallback import org.oxycblt.auxio.ui.DiffCallback
import org.oxycblt.auxio.ui.HeaderViewHolder import org.oxycblt.auxio.ui.HeaderViewHolder
import org.oxycblt.auxio.util.context
import org.oxycblt.auxio.util.getPluralSafe
import org.oxycblt.auxio.util.inflater import org.oxycblt.auxio.util.inflater
import org.oxycblt.auxio.util.textSafe
/** /**
* An adapter for displaying the [Album]s and [Song]s of an artist. * An adapter for displaying the [Album]s and [Song]s of an artist.
@ -73,9 +76,9 @@ class ArtistDetailAdapter(
IntegerTable.ITEM_TYPE_ARTIST_DETAIL -> IntegerTable.ITEM_TYPE_ARTIST_DETAIL ->
ArtistDetailViewHolder(ItemDetailBinding.inflate(parent.context.inflater)) ArtistDetailViewHolder(ItemDetailBinding.inflate(parent.context.inflater))
IntegerTable.ITEM_TYPE_ARTIST_ALBUM -> IntegerTable.ITEM_TYPE_ARTIST_ALBUM ->
ArtistAlbumViewHolder(ItemArtistAlbumBinding.inflate(parent.context.inflater)) ArtistAlbumViewHolder(ItemParentBinding.inflate(parent.context.inflater))
IntegerTable.ITEM_TYPE_ARTIST_SONG -> IntegerTable.ITEM_TYPE_ARTIST_SONG ->
ArtistSongViewHolder(ItemArtistSongBinding.inflate(parent.context.inflater)) ArtistSongViewHolder(ItemSongBinding.inflate(parent.context.inflater))
IntegerTable.ITEM_TYPE_HEADER -> HeaderViewHolder.from(parent.context) IntegerTable.ITEM_TYPE_HEADER -> HeaderViewHolder.from(parent.context)
IntegerTable.ITEM_TYPE_ACTION_HEADER -> ActionHeaderViewHolder.from(parent.context) IntegerTable.ITEM_TYPE_ACTION_HEADER -> ActionHeaderViewHolder.from(parent.context)
else -> error("Invalid ViewHolder item type $viewType") else -> error("Invalid ViewHolder item type $viewType")
@ -173,16 +176,16 @@ class ArtistDetailAdapter(
val context = binding.root.context val context = binding.root.context
binding.detailCover.apply { binding.detailCover.apply {
bindArtistImage(data) applyArtistImage(data)
contentDescription = contentDescription =
context.getString(R.string.desc_artist_image, data.resolvedName) context.getString(R.string.desc_artist_image, data.resolvedName)
} }
binding.detailName.text = data.resolvedName binding.detailName.textSafe = data.resolvedName
// Get the genre that corresponds to the most songs in this artist, which would be // Get the genre that corresponds to the most songs in this artist, which would be
// the most "Prominent" genre. // the most "Prominent" genre.
binding.detailSubhead.text = binding.detailSubhead.textSafe =
data.songs data.songs
.groupBy { it.genre.resolvedName } .groupBy { it.genre.resolvedName }
.entries .entries
@ -190,7 +193,11 @@ class ArtistDetailAdapter(
?.key ?.key
?: context.getString(R.string.def_genre) ?: context.getString(R.string.def_genre)
binding.detailInfo.bindArtistInfo(data) binding.detailInfo.textSafe =
binding.context.getString(
R.string.fmt_two,
binding.context.getPluralSafe(R.plurals.fmt_album_count, data.albums.size),
binding.context.getPluralSafe(R.plurals.fmt_song_count, data.songs.size))
binding.detailPlayButton.setOnClickListener { playbackModel.playArtist(data, false) } binding.detailPlayButton.setOnClickListener { playbackModel.playArtist(data, false) }
@ -199,24 +206,26 @@ class ArtistDetailAdapter(
} }
inner class ArtistAlbumViewHolder( inner class ArtistAlbumViewHolder(
private val binding: ItemArtistAlbumBinding, private val binding: ItemParentBinding,
) : BaseViewHolder<Album>(binding, doOnClick, doOnLongClick), Highlightable { ) : BaseViewHolder<Album>(binding, doOnClick, doOnLongClick), Highlightable {
override fun onBind(data: Album) { override fun onBind(data: Album) {
binding.album = data binding.parentImage.applyAlbumCover(data)
binding.albumName.requestLayout() binding.parentName.textSafe = data.resolvedName
binding.parentInfo.textSafe = binding.context.getString(R.string.fmt_number, data.year)
} }
override fun setHighlighted(isHighlighted: Boolean) { override fun setHighlighted(isHighlighted: Boolean) {
binding.albumName.isActivated = isHighlighted binding.parentName.isActivated = isHighlighted
} }
} }
inner class ArtistSongViewHolder( inner class ArtistSongViewHolder(
private val binding: ItemArtistSongBinding, private val binding: ItemSongBinding,
) : BaseViewHolder<Song>(binding, doOnSongClick, doOnLongClick), Highlightable { ) : BaseViewHolder<Song>(binding, doOnSongClick, doOnLongClick), Highlightable {
override fun onBind(data: Song) { override fun onBind(data: Song) {
binding.song = data binding.songAlbumCover.applyAlbumCover(data)
binding.songName.requestLayout() binding.songName.textSafe = data.resolvedName
binding.songInfo.textSafe = data.resolvedAlbumName
} }
override fun setHighlighted(isHighlighted: Boolean) { override fun setHighlighted(isHighlighted: Boolean) {

View file

@ -23,19 +23,22 @@ import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import org.oxycblt.auxio.IntegerTable import org.oxycblt.auxio.IntegerTable
import org.oxycblt.auxio.R import org.oxycblt.auxio.R
import org.oxycblt.auxio.coil.bindGenreImage import org.oxycblt.auxio.coil.applyAlbumCover
import org.oxycblt.auxio.coil.applyGenreImage
import org.oxycblt.auxio.databinding.ItemDetailBinding import org.oxycblt.auxio.databinding.ItemDetailBinding
import org.oxycblt.auxio.databinding.ItemGenreSongBinding import org.oxycblt.auxio.databinding.ItemSongBinding
import org.oxycblt.auxio.music.ActionHeader import org.oxycblt.auxio.music.ActionHeader
import org.oxycblt.auxio.music.Genre import org.oxycblt.auxio.music.Genre
import org.oxycblt.auxio.music.Item import org.oxycblt.auxio.music.Item
import org.oxycblt.auxio.music.Song import org.oxycblt.auxio.music.Song
import org.oxycblt.auxio.music.bindGenreInfo
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
import org.oxycblt.auxio.ui.DiffCallback import org.oxycblt.auxio.ui.DiffCallback
import org.oxycblt.auxio.util.context
import org.oxycblt.auxio.util.getPluralSafe
import org.oxycblt.auxio.util.inflater import org.oxycblt.auxio.util.inflater
import org.oxycblt.auxio.util.textSafe
/** /**
* An adapter for displaying the [Song]s of a genre. * An adapter for displaying the [Song]s of a genre.
@ -64,9 +67,7 @@ class GenreDetailAdapter(
GenreDetailViewHolder(ItemDetailBinding.inflate(parent.context.inflater)) GenreDetailViewHolder(ItemDetailBinding.inflate(parent.context.inflater))
IntegerTable.ITEM_TYPE_ACTION_HEADER -> ActionHeaderViewHolder.from(parent.context) IntegerTable.ITEM_TYPE_ACTION_HEADER -> ActionHeaderViewHolder.from(parent.context)
IntegerTable.ITEM_TYPE_GENRE_SONG -> IntegerTable.ITEM_TYPE_GENRE_SONG ->
GenreSongViewHolder( GenreSongViewHolder(ItemSongBinding.inflate(parent.context.inflater))
ItemGenreSongBinding.inflate(parent.context.inflater),
)
else -> error("Bad ViewHolder item type $viewType") else -> error("Bad ViewHolder item type $viewType")
} }
} }
@ -127,13 +128,14 @@ class GenreDetailAdapter(
val context = binding.root.context val context = binding.root.context
binding.detailCover.apply { binding.detailCover.apply {
bindGenreImage(data) applyGenreImage(data)
contentDescription = context.getString(R.string.desc_genre_image, data.resolvedName) contentDescription = context.getString(R.string.desc_genre_image, data.resolvedName)
} }
binding.detailName.text = data.resolvedName binding.detailName.textSafe = data.resolvedName
binding.detailSubhead.bindGenreInfo(data) binding.detailSubhead.textSafe =
binding.detailInfo.text = data.totalDuration binding.context.getPluralSafe(R.plurals.fmt_song_count, data.songs.size)
binding.detailInfo.textSafe = data.totalDuration
binding.detailPlayButton.setOnClickListener { playbackModel.playGenre(data, false) } binding.detailPlayButton.setOnClickListener { playbackModel.playGenre(data, false) }
@ -141,14 +143,16 @@ class GenreDetailAdapter(
} }
} }
inner class GenreSongViewHolder( /** The Shared ViewHolder for a [Song]. Instantiation should be done with [from]. */
private val binding: ItemGenreSongBinding, inner class GenreSongViewHolder
constructor(
private val binding: ItemSongBinding,
) : BaseViewHolder<Song>(binding, doOnClick, doOnLongClick), Highlightable { ) : BaseViewHolder<Song>(binding, doOnClick, doOnLongClick), Highlightable {
override fun onBind(data: Song) {
binding.song = data
binding.songName.requestLayout() override fun onBind(data: Song) {
binding.songInfo.requestLayout() binding.songAlbumCover.applyAlbumCover(data)
binding.songName.textSafe = data.resolvedName
binding.songInfo.textSafe = data.resolvedArtistName
} }
override fun setHighlighted(isHighlighted: Boolean) { override fun setHighlighted(isHighlighted: Boolean) {

View file

@ -186,6 +186,8 @@ constructor(context: Context, attrs: AttributeSet? = null, @AttrRes defStyleAttr
// --- RECYCLERVIEW EVENT MANAGEMENT --- // --- RECYCLERVIEW EVENT MANAGEMENT ---
private fun onPreDraw() { private fun onPreDraw() {
// FIXME: Make the way we lay out views less of a hacky mess. Perhaps consider
// overlaying views or turning this into a ViewGroup.
updateScrollbarState() updateScrollbarState()
thumbView.layoutDirection = layoutDirection thumbView.layoutDirection = layoutDirection

View file

@ -18,12 +18,7 @@
package org.oxycblt.auxio.music package org.oxycblt.auxio.music
import android.text.format.DateUtils import android.text.format.DateUtils
import android.widget.TextView
import androidx.databinding.BindingAdapter
import org.oxycblt.auxio.R
import org.oxycblt.auxio.util.getPluralSafe
import org.oxycblt.auxio.util.logD import org.oxycblt.auxio.util.logD
import org.oxycblt.auxio.util.logW
// --- EXTENSION FUNCTIONS --- // --- EXTENSION FUNCTIONS ---
@ -47,53 +42,3 @@ fun Long.toDuration(isElapsed: Boolean): String {
return durationString return durationString
} }
// --- BINDING ADAPTERS ---
@BindingAdapter("songInfo")
fun TextView.bindSongInfo(song: Song?) {
if (song == null) {
logW("Song was null, not applying info")
return
}
text = context.getString(R.string.fmt_two, song.resolvedArtistName, song.resolvedAlbumName)
}
@BindingAdapter("albumInfo")
fun TextView.bindAlbumInfo(album: Album?) {
if (album == null) {
logW("Album was null, not applying info")
return
}
text =
context.getString(
R.string.fmt_two,
album.resolvedArtistName,
context.getPluralSafe(R.plurals.fmt_song_count, album.songs.size))
}
@BindingAdapter("artistInfo")
fun TextView.bindArtistInfo(artist: Artist?) {
if (artist == null) {
logW("Artist was null, not applying info")
return
}
text =
context.getString(
R.string.fmt_two,
context.getPluralSafe(R.plurals.fmt_album_count, artist.albums.size),
context.getPluralSafe(R.plurals.fmt_song_count, artist.songs.size))
}
@BindingAdapter("genreInfo")
fun TextView.bindGenreInfo(genre: Genre?) {
if (genre == null) {
logW("Genre was null, not applying info")
return
}
text = context.getPluralSafe(R.plurals.fmt_song_count, genre.songs.size)
}

View file

@ -22,6 +22,7 @@ import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import org.oxycblt.auxio.databinding.ItemExcludedDirBinding import org.oxycblt.auxio.databinding.ItemExcludedDirBinding
import org.oxycblt.auxio.util.inflater import org.oxycblt.auxio.util.inflater
import org.oxycblt.auxio.util.textSafe
/** /**
* Adapter that shows the excluded directories and their "Clear" button. * Adapter that shows the excluded directories and their "Clear" button.
@ -56,8 +57,7 @@ class ExcludedEntryAdapter(private val onClear: (String) -> Unit) :
} }
fun bind(path: String) { fun bind(path: String) {
binding.excludedPath.text = path binding.excludedPath.textSafe = path
binding.excludedPath.requestLayout()
binding.excludedClear.setOnClickListener { onClear(path) } binding.excludedClear.setOnClickListener { onClear(path) }
} }
} }

View file

@ -25,14 +25,14 @@ import androidx.core.view.updatePadding
import androidx.fragment.app.activityViewModels import androidx.fragment.app.activityViewModels
import com.google.android.material.color.MaterialColors import com.google.android.material.color.MaterialColors
import org.oxycblt.auxio.R import org.oxycblt.auxio.R
import org.oxycblt.auxio.coil.bindAlbumCover import org.oxycblt.auxio.coil.applyAlbumCover
import org.oxycblt.auxio.databinding.FragmentPlaybackBarBinding import org.oxycblt.auxio.databinding.FragmentPlaybackBarBinding
import org.oxycblt.auxio.detail.DetailViewModel import org.oxycblt.auxio.detail.DetailViewModel
import org.oxycblt.auxio.music.bindSongInfo
import org.oxycblt.auxio.ui.BottomSheetLayout import org.oxycblt.auxio.ui.BottomSheetLayout
import org.oxycblt.auxio.ui.ViewBindingFragment import org.oxycblt.auxio.ui.ViewBindingFragment
import org.oxycblt.auxio.util.getAttrColorSafe import org.oxycblt.auxio.util.getAttrColorSafe
import org.oxycblt.auxio.util.systemBarInsetsCompat import org.oxycblt.auxio.util.systemBarInsetsCompat
import org.oxycblt.auxio.util.textSafe
class PlaybackBarFragment : ViewBindingFragment<FragmentPlaybackBarBinding>() { class PlaybackBarFragment : ViewBindingFragment<FragmentPlaybackBarBinding>() {
private val playbackModel: PlaybackViewModel by activityViewModels() private val playbackModel: PlaybackViewModel by activityViewModels()
@ -99,9 +99,10 @@ class PlaybackBarFragment : ViewBindingFragment<FragmentPlaybackBarBinding>() {
playbackModel.song.observe(viewLifecycleOwner) { song -> playbackModel.song.observe(viewLifecycleOwner) { song ->
if (song != null) { if (song != null) {
binding.playbackCover.bindAlbumCover(song) binding.playbackCover.applyAlbumCover(song)
binding.playbackSong.text = song.resolvedName binding.playbackSong.textSafe = song.resolvedName
binding.playbackInfo.bindSongInfo(song) binding.playbackInfo.textSafe =
getString(R.string.fmt_two, song.resolvedArtistName, song.resolvedAlbumName)
binding.playbackProgressBar.max = song.seconds.toInt() binding.playbackProgressBar.max = song.seconds.toInt()
} }
} }

View file

@ -29,7 +29,7 @@ import com.google.android.material.slider.Slider
import kotlin.math.max import kotlin.math.max
import org.oxycblt.auxio.MainFragmentDirections import org.oxycblt.auxio.MainFragmentDirections
import org.oxycblt.auxio.R import org.oxycblt.auxio.R
import org.oxycblt.auxio.coil.bindAlbumCover import org.oxycblt.auxio.coil.applyAlbumCover
import org.oxycblt.auxio.databinding.FragmentPlaybackPanelBinding import org.oxycblt.auxio.databinding.FragmentPlaybackPanelBinding
import org.oxycblt.auxio.detail.DetailViewModel import org.oxycblt.auxio.detail.DetailViewModel
import org.oxycblt.auxio.music.MusicParent import org.oxycblt.auxio.music.MusicParent
@ -42,6 +42,7 @@ import org.oxycblt.auxio.util.getAttrColorSafe
import org.oxycblt.auxio.util.logD import org.oxycblt.auxio.util.logD
import org.oxycblt.auxio.util.stateList import org.oxycblt.auxio.util.stateList
import org.oxycblt.auxio.util.systemBarInsetsCompat import org.oxycblt.auxio.util.systemBarInsetsCompat
import org.oxycblt.auxio.util.textSafe
/** /**
* A [Fragment] that displays more information about the song, along with more media controls. * A [Fragment] that displays more information about the song, along with more media controls.
@ -166,7 +167,7 @@ class PlaybackPanelFragment :
override fun onValueChange(slider: Slider, value: Float, fromUser: Boolean) { override fun onValueChange(slider: Slider, value: Float, fromUser: Boolean) {
if (fromUser) { if (fromUser) {
requireBinding().playbackPosition.text = value.toLong().toDuration(true) requireBinding().playbackPosition.textSafe = value.toLong().toDuration(true)
} }
} }
@ -174,14 +175,14 @@ class PlaybackPanelFragment :
if (song == null) return if (song == null) return
val binding = requireBinding() val binding = requireBinding()
binding.playbackCover.bindAlbumCover(song) binding.playbackCover.applyAlbumCover(song)
binding.playbackSong.text = song.resolvedName binding.playbackSong.textSafe = song.resolvedName
binding.playbackArtist.text = song.resolvedArtistName binding.playbackArtist.textSafe = song.resolvedArtistName
binding.playbackAlbum.text = song.resolvedAlbumName binding.playbackAlbum.textSafe = song.resolvedAlbumName
// Normally if a song had a duration // Normally if a song had a duration
val seconds = song.seconds val seconds = song.seconds
binding.playbackDuration.text = seconds.toDuration(false) binding.playbackDuration.textSafe = seconds.toDuration(false)
binding.playbackSeekBar.apply { binding.playbackSeekBar.apply {
valueTo = max(seconds, 1L).toFloat() valueTo = max(seconds, 1L).toFloat()
isEnabled = seconds > 0L isEnabled = seconds > 0L
@ -199,7 +200,7 @@ class PlaybackPanelFragment :
val binding = requireBinding() val binding = requireBinding()
if (!binding.playbackPosition.isActivated) { if (!binding.playbackPosition.isActivated) {
binding.playbackSeekBar.value = position.toFloat() binding.playbackSeekBar.value = position.toFloat()
binding.playbackPosition.text = position.toDuration(true) binding.playbackPosition.textSafe = position.toDuration(true)
} }
} }

View file

@ -65,6 +65,7 @@ class PlaybackViewModel : ViewModel(), PlaybackStateManager.Callback {
private val mMode = MutableLiveData(PlaybackMode.ALL_SONGS) private val mMode = MutableLiveData(PlaybackMode.ALL_SONGS)
// Other // Other
// TODO: Move URI management to PlaybackService (more capable of taking commands)
private var mIntentUri: Uri? = null private var mIntentUri: Uri? = null
/** The current song. */ /** The current song. */

View file

@ -28,6 +28,7 @@ import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.shape.MaterialShapeDrawable import com.google.android.material.shape.MaterialShapeDrawable
import org.oxycblt.auxio.IntegerTable import org.oxycblt.auxio.IntegerTable
import org.oxycblt.auxio.coil.applyAlbumCover
import org.oxycblt.auxio.databinding.ItemQueueSongBinding import org.oxycblt.auxio.databinding.ItemQueueSongBinding
import org.oxycblt.auxio.music.ActionHeader import org.oxycblt.auxio.music.ActionHeader
import org.oxycblt.auxio.music.Header import org.oxycblt.auxio.music.Header
@ -41,6 +42,7 @@ import org.oxycblt.auxio.util.disableDropShadowCompat
import org.oxycblt.auxio.util.inflater import org.oxycblt.auxio.util.inflater
import org.oxycblt.auxio.util.logE import org.oxycblt.auxio.util.logE
import org.oxycblt.auxio.util.stateList import org.oxycblt.auxio.util.stateList
import org.oxycblt.auxio.util.textSafe
/** /**
* The single adapter for both the Next Queue and the User Queue. * The single adapter for both the Next Queue and the User Queue.
@ -125,7 +127,9 @@ class QueueAdapter(private val touchHelper: ItemTouchHelper) :
@SuppressLint("ClickableViewAccessibility") @SuppressLint("ClickableViewAccessibility")
override fun onBind(data: Song) { override fun onBind(data: Song) {
binding.song = data binding.songAlbumCover.applyAlbumCover(data)
binding.songName.textSafe = data.resolvedName
binding.songInfo.textSafe = data.resolvedArtistName
binding.background.isInvisible = true binding.background.isInvisible = true

View file

@ -36,6 +36,7 @@ import org.oxycblt.auxio.ui.ViewBindingFragment
import org.oxycblt.auxio.util.logD import org.oxycblt.auxio.util.logD
import org.oxycblt.auxio.util.showToast import org.oxycblt.auxio.util.showToast
import org.oxycblt.auxio.util.systemBarInsetsCompat import org.oxycblt.auxio.util.systemBarInsetsCompat
import org.oxycblt.auxio.util.textSafe
/** /**
* A [BottomSheetDialogFragment] that shows Auxio's about screen. * A [BottomSheetDialogFragment] that shows Auxio's about screen.
@ -54,13 +55,13 @@ class AboutFragment : ViewBindingFragment<FragmentAboutBinding>() {
binding.aboutToolbar.setNavigationOnClickListener { findNavController().navigateUp() } binding.aboutToolbar.setNavigationOnClickListener { findNavController().navigateUp() }
binding.aboutVersion.text = BuildConfig.VERSION_NAME binding.aboutVersion.textSafe = BuildConfig.VERSION_NAME
binding.aboutCode.setOnClickListener { openLinkInBrowser(LINK_CODEBASE) } binding.aboutCode.setOnClickListener { openLinkInBrowser(LINK_CODEBASE) }
binding.aboutFaq.setOnClickListener { openLinkInBrowser(LINK_FAQ) } binding.aboutFaq.setOnClickListener { openLinkInBrowser(LINK_FAQ) }
binding.aboutLicenses.setOnClickListener { openLinkInBrowser(LINK_LICENSES) } binding.aboutLicenses.setOnClickListener { openLinkInBrowser(LINK_LICENSES) }
homeModel.songs.observe(viewLifecycleOwner) { songs -> homeModel.songs.observe(viewLifecycleOwner) { songs ->
binding.aboutSongCount.text = getString(R.string.fmt_songs_loaded, songs.size) binding.aboutSongCount.textSafe = getString(R.string.fmt_songs_loaded, songs.size)
} }
} }

View file

@ -249,11 +249,11 @@ constructor(context: Context, attrs: AttributeSet? = null, defStyle: Int = 0) :
barView = getChildAt(1) // Child 2 is assumed to be the bar used when collapsed barView = getChildAt(1) // Child 2 is assumed to be the bar used when collapsed
panelView = getChildAt(2) // Child 3 is assumed to be the panel used when expanded panelView = getChildAt(2) // Child 3 is assumed to be the panel used when expanded
// We actually move the bar and panel views into a container so that they have consistent
// behavior when be manipulate layouts later.
removeView(barView) removeView(barView)
removeView(panelView) removeView(panelView)
// We actually move the bar and panel views into a container so that they have consistent
// behavior when be manipulate layouts later.
containerView.apply { containerView.apply {
addView( addView(
barView, barView,

View file

@ -20,13 +20,15 @@ package org.oxycblt.auxio.ui
import android.content.Context import android.content.Context
import android.view.View import android.view.View
import androidx.appcompat.widget.TooltipCompat import androidx.appcompat.widget.TooltipCompat
import androidx.databinding.ViewDataBinding
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import androidx.viewbinding.ViewBinding
import org.oxycblt.auxio.R
import org.oxycblt.auxio.coil.applyAlbumCover
import org.oxycblt.auxio.coil.applyArtistImage
import org.oxycblt.auxio.coil.applyGenreImage
import org.oxycblt.auxio.databinding.ItemActionHeaderBinding import org.oxycblt.auxio.databinding.ItemActionHeaderBinding
import org.oxycblt.auxio.databinding.ItemAlbumBinding
import org.oxycblt.auxio.databinding.ItemArtistBinding
import org.oxycblt.auxio.databinding.ItemGenreBinding
import org.oxycblt.auxio.databinding.ItemHeaderBinding import org.oxycblt.auxio.databinding.ItemHeaderBinding
import org.oxycblt.auxio.databinding.ItemParentBinding
import org.oxycblt.auxio.databinding.ItemSongBinding import org.oxycblt.auxio.databinding.ItemSongBinding
import org.oxycblt.auxio.music.ActionHeader import org.oxycblt.auxio.music.ActionHeader
import org.oxycblt.auxio.music.Album import org.oxycblt.auxio.music.Album
@ -35,7 +37,10 @@ import org.oxycblt.auxio.music.Genre
import org.oxycblt.auxio.music.Header import org.oxycblt.auxio.music.Header
import org.oxycblt.auxio.music.Item import org.oxycblt.auxio.music.Item
import org.oxycblt.auxio.music.Song import org.oxycblt.auxio.music.Song
import org.oxycblt.auxio.util.context
import org.oxycblt.auxio.util.getPluralSafe
import org.oxycblt.auxio.util.inflater import org.oxycblt.auxio.util.inflater
import org.oxycblt.auxio.util.textSafe
/** /**
* A [RecyclerView.ViewHolder] that streamlines a lot of the common things across all viewholders. * A [RecyclerView.ViewHolder] that streamlines a lot of the common things across all viewholders.
@ -46,7 +51,7 @@ import org.oxycblt.auxio.util.inflater
* @author OxygenCobalt * @author OxygenCobalt
*/ */
abstract class BaseViewHolder<T : Item>( abstract class BaseViewHolder<T : Item>(
private val binding: ViewDataBinding, private val binding: ViewBinding,
private val doOnClick: ((data: T) -> Unit)? = null, private val doOnClick: ((data: T) -> Unit)? = null,
private val doOnLongClick: ((view: View, data: T) -> Unit)? = null private val doOnLongClick: ((view: View, data: T) -> Unit)? = null
) : RecyclerView.ViewHolder(binding.root) { ) : RecyclerView.ViewHolder(binding.root) {
@ -73,8 +78,6 @@ abstract class BaseViewHolder<T : Item>(
} }
onBind(data) onBind(data)
binding.executePendingBindings()
} }
/** /**
@ -93,10 +96,9 @@ private constructor(
) : BaseViewHolder<Song>(binding, doOnClick, doOnLongClick) { ) : BaseViewHolder<Song>(binding, doOnClick, doOnLongClick) {
override fun onBind(data: Song) { override fun onBind(data: Song) {
binding.song = data binding.songAlbumCover.applyAlbumCover(data)
binding.songName.textSafe = data.resolvedName
binding.songName.requestLayout() binding.songInfo.textSafe = data.resolvedArtistName
binding.songInfo.requestLayout()
} }
companion object { companion object {
@ -115,14 +117,19 @@ private constructor(
/** The Shared ViewHolder for a [Album]. Instantiation should be done with [from]. */ /** The Shared ViewHolder for a [Album]. Instantiation should be done with [from]. */
class AlbumViewHolder class AlbumViewHolder
private constructor( private constructor(
private val binding: ItemAlbumBinding, private val binding: ItemParentBinding,
doOnClick: (data: Album) -> Unit, doOnClick: (data: Album) -> Unit,
doOnLongClick: (view: View, data: Album) -> Unit doOnLongClick: (view: View, data: Album) -> Unit
) : BaseViewHolder<Album>(binding, doOnClick, doOnLongClick) { ) : BaseViewHolder<Album>(binding, doOnClick, doOnLongClick) {
override fun onBind(data: Album) { override fun onBind(data: Album) {
binding.album = data binding.parentImage.applyAlbumCover(data)
binding.albumName.requestLayout() binding.parentName.textSafe = data.resolvedName
binding.parentInfo.textSafe =
binding.context.getString(
R.string.fmt_two,
data.resolvedArtistName,
binding.context.getPluralSafe(R.plurals.fmt_song_count, data.songs.size))
} }
companion object { companion object {
@ -133,7 +140,7 @@ private constructor(
doOnLongClick: (view: View, data: Album) -> Unit doOnLongClick: (view: View, data: Album) -> Unit
): AlbumViewHolder { ): AlbumViewHolder {
return AlbumViewHolder( return AlbumViewHolder(
ItemAlbumBinding.inflate(context.inflater), doOnClick, doOnLongClick) ItemParentBinding.inflate(context.inflater), doOnClick, doOnLongClick)
} }
} }
} }
@ -141,14 +148,19 @@ private constructor(
/** The Shared ViewHolder for a [Artist]. Instantiation should be done with [from]. */ /** The Shared ViewHolder for a [Artist]. Instantiation should be done with [from]. */
class ArtistViewHolder class ArtistViewHolder
private constructor( private constructor(
private val binding: ItemArtistBinding, private val binding: ItemParentBinding,
doOnClick: (Artist) -> Unit, doOnClick: (Artist) -> Unit,
doOnLongClick: (view: View, data: Artist) -> Unit doOnLongClick: (view: View, data: Artist) -> Unit
) : BaseViewHolder<Artist>(binding, doOnClick, doOnLongClick) { ) : BaseViewHolder<Artist>(binding, doOnClick, doOnLongClick) {
override fun onBind(data: Artist) { override fun onBind(data: Artist) {
binding.artist = data binding.parentImage.applyArtistImage(data)
binding.artistName.requestLayout() binding.parentName.textSafe = data.resolvedName
binding.parentInfo.textSafe =
binding.context.getString(
R.string.fmt_two,
binding.context.getPluralSafe(R.plurals.fmt_album_count, data.albums.size),
binding.context.getPluralSafe(R.plurals.fmt_song_count, data.songs.size))
} }
companion object { companion object {
@ -159,7 +171,7 @@ private constructor(
doOnLongClick: (view: View, data: Artist) -> Unit doOnLongClick: (view: View, data: Artist) -> Unit
): ArtistViewHolder { ): ArtistViewHolder {
return ArtistViewHolder( return ArtistViewHolder(
ItemArtistBinding.inflate(context.inflater), doOnClick, doOnLongClick) ItemParentBinding.inflate(context.inflater), doOnClick, doOnLongClick)
} }
} }
} }
@ -167,14 +179,16 @@ private constructor(
/** The Shared ViewHolder for a [Genre]. Instantiation should be done with [from]. */ /** The Shared ViewHolder for a [Genre]. Instantiation should be done with [from]. */
class GenreViewHolder class GenreViewHolder
private constructor( private constructor(
private val binding: ItemGenreBinding, private val binding: ItemParentBinding,
doOnClick: (Genre) -> Unit, doOnClick: (Genre) -> Unit,
doOnLongClick: (view: View, data: Genre) -> Unit doOnLongClick: (view: View, data: Genre) -> Unit
) : BaseViewHolder<Genre>(binding, doOnClick, doOnLongClick) { ) : BaseViewHolder<Genre>(binding, doOnClick, doOnLongClick) {
override fun onBind(data: Genre) { override fun onBind(data: Genre) {
binding.genre = data binding.parentImage.applyGenreImage(data)
binding.genreName.requestLayout() binding.parentName.textSafe = data.resolvedName
binding.parentInfo.textSafe =
binding.context.getPluralSafe(R.plurals.fmt_song_count, data.songs.size)
} }
companion object { companion object {
@ -185,7 +199,7 @@ private constructor(
doOnLongClick: (view: View, data: Genre) -> Unit doOnLongClick: (view: View, data: Genre) -> Unit
): GenreViewHolder { ): GenreViewHolder {
return GenreViewHolder( return GenreViewHolder(
ItemGenreBinding.inflate(context.inflater), doOnClick, doOnLongClick) ItemParentBinding.inflate(context.inflater), doOnClick, doOnLongClick)
} }
} }
} }
@ -195,7 +209,7 @@ class HeaderViewHolder private constructor(private val binding: ItemHeaderBindin
BaseViewHolder<Header>(binding) { BaseViewHolder<Header>(binding) {
override fun onBind(data: Header) { override fun onBind(data: Header) {
binding.header = data binding.title.textSafe = binding.context.getString(data.string)
} }
companion object { companion object {
@ -211,13 +225,11 @@ class ActionHeaderViewHolder private constructor(private val binding: ItemAction
BaseViewHolder<ActionHeader>(binding) { BaseViewHolder<ActionHeader>(binding) {
override fun onBind(data: ActionHeader) { override fun onBind(data: ActionHeader) {
binding.header = data binding.headerTitle.textSafe = binding.context.getString(data.string)
binding.executePendingBindings()
binding.headerButton.apply { binding.headerButton.apply {
setImageResource(data.icon)
contentDescription = context.getString(data.desc)
TooltipCompat.setTooltipText(this, contentDescription) TooltipCompat.setTooltipText(this, contentDescription)
setOnClickListener(data.onClick) setOnClickListener(data.onClick)
} }
} }

View file

@ -17,6 +17,7 @@
package org.oxycblt.auxio.util package org.oxycblt.auxio.util
import android.content.Context
import android.content.res.ColorStateList import android.content.res.ColorStateList
import android.graphics.Insets import android.graphics.Insets
import android.graphics.Rect import android.graphics.Rect
@ -24,44 +25,14 @@ import android.graphics.drawable.Drawable
import android.os.Build import android.os.Build
import android.view.View import android.view.View
import android.view.WindowInsets import android.view.WindowInsets
import android.widget.TextView
import androidx.annotation.ColorRes import androidx.annotation.ColorRes
import androidx.core.graphics.drawable.DrawableCompat import androidx.core.graphics.drawable.DrawableCompat
import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import androidx.viewbinding.ViewBinding
import org.oxycblt.auxio.R import org.oxycblt.auxio.R
/** Converts this color to a single-color [ColorStateList]. */
val @receiver:ColorRes Int.stateList
get() = ColorStateList.valueOf(this)
/**
* Apply the recommended spans for a [RecyclerView].
*
* @param shouldBeFullWidth Optional callback for determining whether an item should be full-width,
* regardless of spans
*/
fun RecyclerView.applySpans(shouldBeFullWidth: ((Int) -> Boolean)? = null) {
val spans = resources.getInteger(R.integer.recycler_spans)
if (spans > 1) {
val mgr = GridLayoutManager(context, spans)
if (shouldBeFullWidth != null) {
mgr.spanSizeLookup =
object : GridLayoutManager.SpanSizeLookup() {
override fun getSpanSize(position: Int): Int {
return if (shouldBeFullWidth(position)) spans else 1
}
}
}
layoutManager = mgr
}
}
/** Returns whether a recyclerview can scroll. */
fun RecyclerView.canScroll(): Boolean = computeVerticalScrollRange() > height
/** /**
* Disables drop shadows on a view programmatically in a version-compatible manner. This only works * Disables drop shadows on a view programmatically in a version-compatible manner. This only works
* on Android 9 and above. Below that version, shadows will remain visible. * on Android 9 and above. Below that version, shadows will remain visible.
@ -113,9 +84,52 @@ private fun isUnderImpl(
val View.isRtl: Boolean val View.isRtl: Boolean
get() = layoutDirection == View.LAYOUT_DIRECTION_RTL get() = layoutDirection == View.LAYOUT_DIRECTION_RTL
val Drawable.isRtl: Boolean val Drawable.isRtl: Boolean
get() = DrawableCompat.getLayoutDirection(this) == View.LAYOUT_DIRECTION_RTL get() = DrawableCompat.getLayoutDirection(this) == View.LAYOUT_DIRECTION_RTL
val ViewBinding.context: Context
get() = root.context
var TextView.textSafe
get() = text
set(value) {
text = value
requestLayout()
}
/**
* Apply the recommended spans for a [RecyclerView].
*
* @param shouldBeFullWidth Optional callback for determining whether an item should be full-width,
* regardless of spans
*/
fun RecyclerView.applySpans(shouldBeFullWidth: ((Int) -> Boolean)? = null) {
val spans = resources.getInteger(R.integer.recycler_spans)
if (spans > 1) {
val mgr = GridLayoutManager(context, spans)
if (shouldBeFullWidth != null) {
mgr.spanSizeLookup =
object : GridLayoutManager.SpanSizeLookup() {
override fun getSpanSize(position: Int): Int {
return if (shouldBeFullWidth(position)) spans else 1
}
}
}
layoutManager = mgr
}
}
/** Returns whether a recyclerview can scroll. */
fun RecyclerView.canScroll(): Boolean = computeVerticalScrollRange() > height
/** Converts this color to a single-color [ColorStateList]. */
val @receiver:ColorRes Int.stateList
get() = ColorStateList.valueOf(this)
/** /**
* Resolve system bar insets in a version-aware manner. This can be used to apply padding to a view * Resolve system bar insets in a version-aware manner. This can be used to apply padding to a view
* that properly follows all the frustrating changes that were made between 8-11. * that properly follows all the frustrating changes that were made between 8-11.

View file

@ -1,11 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android" <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"> xmlns:tools="http://schemas.android.com/tools"
<!-- This layout is re-used across all detail fragments. Do not add databinding. -->
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:padding="@dimen/spacing_medium"> android:padding="@dimen/spacing_medium">
@ -75,4 +71,3 @@
app:layout_constraintStart_toEndOf="@+id/detail_play_button" app:layout_constraintStart_toEndOf="@+id/detail_play_button"
app:layout_constraintTop_toTopOf="@+id/detail_play_button" /> app:layout_constraintTop_toTopOf="@+id/detail_play_button" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

View file

@ -1,10 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android" <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
tools:context=".playback.PlaybackPanelFragment">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/playback_layout" android:id="@+id/playback_layout"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent">
@ -85,11 +82,11 @@
android:id="@+id/playback_seek_bar" android:id="@+id/playback_seek_bar"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/spacing_medium"
android:valueFrom="0" android:valueFrom="0"
android:valueTo="1" android:valueTo="1"
app:haloRadius="@dimen/slider_halo_radius" app:haloRadius="@dimen/slider_halo_radius"
app:labelBehavior="gone" app:labelBehavior="gone"
android:layout_marginBottom="@dimen/spacing_medium"
app:labelStyle="@style/TextAppearance.Auxio.BodySmall" app:labelStyle="@style/TextAppearance.Auxio.BodySmall"
app:layout_constraintBottom_toTopOf="@+id/playback_play_pause" app:layout_constraintBottom_toTopOf="@+id/playback_play_pause"
app:layout_constraintEnd_toEndOf="@+id/playback_song_container" app:layout_constraintEnd_toEndOf="@+id/playback_song_container"
@ -101,8 +98,8 @@
android:id="@+id/playback_position" android:id="@+id/playback_position"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="@dimen/spacing_small_inv"
android:layout_marginStart="@dimen/spacing_medium" android:layout_marginStart="@dimen/spacing_medium"
android:layout_marginTop="@dimen/spacing_small_inv"
android:textAppearance="@style/TextAppearance.Auxio.BodyMedium" android:textAppearance="@style/TextAppearance.Auxio.BodyMedium"
android:textColor="@color/sel_accented_secondary" android:textColor="@color/sel_accented_secondary"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
@ -125,10 +122,10 @@
android:id="@+id/playback_loop" android:id="@+id/playback_loop"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="@dimen/spacing_medium"
android:contentDescription="@string/desc_change_loop" android:contentDescription="@string/desc_change_loop"
android:src="@drawable/ic_loop" android:src="@drawable/ic_loop"
app:hasIndicator="true" app:hasIndicator="true"
android:layout_marginStart="@dimen/spacing_medium"
app:layout_constraintBottom_toBottomOf="@+id/playback_skip_prev" app:layout_constraintBottom_toBottomOf="@+id/playback_skip_prev"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/playback_skip_prev" /> app:layout_constraintTop_toTopOf="@+id/playback_skip_prev" />
@ -149,12 +146,12 @@
style="@style/Widget.Auxio.FloatingActionButton.PlayPause" style="@style/Widget.Auxio.FloatingActionButton.PlayPause"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/spacing_medium"
android:contentDescription="@string/desc_play_pause" android:contentDescription="@string/desc_play_pause"
android:src="@drawable/sel_playing_state" android:src="@drawable/sel_playing_state"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="@+id/playback_seek_bar" app:layout_constraintEnd_toEndOf="@+id/playback_seek_bar"
app:layout_constraintStart_toStartOf="@+id/playback_seek_bar" app:layout_constraintStart_toStartOf="@+id/playback_seek_bar"
android:layout_marginBottom="@dimen/spacing_medium"
tools:src="@drawable/ic_play" /> tools:src="@drawable/ic_play" />
<org.oxycblt.auxio.playback.PlaybackButton <org.oxycblt.auxio.playback.PlaybackButton
@ -172,14 +169,13 @@
android:id="@+id/playback_shuffle" android:id="@+id/playback_shuffle"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginEnd="@dimen/spacing_medium"
android:contentDescription="@string/desc_shuffle" android:contentDescription="@string/desc_shuffle"
android:src="@drawable/ic_shuffle" android:src="@drawable/ic_shuffle"
android:layout_marginEnd="@dimen/spacing_medium"
app:hasIndicator="true" app:hasIndicator="true"
app:layout_constraintBottom_toBottomOf="@+id/playback_skip_next" app:layout_constraintBottom_toBottomOf="@+id/playback_skip_next"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@+id/playback_skip_next" app:layout_constraintTop_toTopOf="@+id/playback_skip_next"
app:tint="@color/sel_accented" /> app:tint="@color/sel_accented" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

View file

@ -1,11 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android" <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"> xmlns:tools="http://schemas.android.com/tools"
<!-- This layout is re-used across all detail fragments. Do not add databinding. -->
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:padding="@dimen/spacing_medium"> android:padding="@dimen/spacing_medium">
@ -88,4 +84,3 @@
app:layout_constraintTop_toTopOf="@+id/detail_play_button" /> app:layout_constraintTop_toTopOf="@+id/detail_play_button" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

View file

@ -1,10 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android" <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
tools:context=".playback.PlaybackPanelFragment">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/playback_layout" android:id="@+id/playback_layout"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent">
@ -181,4 +178,3 @@
app:tint="@color/sel_accented" /> app:tint="@color/sel_accented" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

View file

@ -1,10 +1,8 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
tools:context=".playback.PlaybackPanelFragment">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/playback_layout" android:id="@+id/playback_layout"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent">
@ -168,6 +166,4 @@
app:layout_constraintTop_toTopOf="@+id/playback_skip_next" app:layout_constraintTop_toTopOf="@+id/playback_skip_next"
app:tint="@color/sel_accented" /> app:tint="@color/sel_accented" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

View file

@ -1,13 +1,10 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<!-- This layout is re-used across all detail fragments. Do not add databinding. --> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:padding="@dimen/spacing_medium"> android:padding="@dimen/spacing_medium">
<org.oxycblt.auxio.coil.RoundableImageView <org.oxycblt.auxio.coil.RoundableImageView
@ -92,4 +89,3 @@
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

View file

@ -1,10 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android" <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
tools:context=".playback.PlaybackBarView">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
tools:parentTag="androidx.constraintlayout.widget.ConstraintLayout"> tools:parentTag="androidx.constraintlayout.widget.ConstraintLayout">
@ -96,4 +93,3 @@
tools:progress="70" /> tools:progress="70" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

View file

@ -1,11 +1,9 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android" <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:padding="@dimen/spacing_medium"> android:padding="@dimen/spacing_medium">
<org.oxycblt.auxio.coil.RoundableImageView <org.oxycblt.auxio.coil.RoundableImageView
@ -86,4 +84,3 @@
app:layout_constraintTop_toTopOf="@+id/detail_play_button" /> app:layout_constraintTop_toTopOf="@+id/detail_play_button" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

View file

@ -1,11 +1,8 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
tools:context=".playback.PlaybackPanelFragment">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/playback_layout" android:id="@+id/playback_layout"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent">
@ -184,4 +181,3 @@
app:tint="@color/sel_accented" /> app:tint="@color/sel_accented" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

View file

@ -1,10 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android" <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
tools:context=".playback.PlaybackBarView">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
tools:parentTag="androidx.constraintlayout.widget.ConstraintLayout"> tools:parentTag="androidx.constraintlayout.widget.ConstraintLayout">
@ -95,4 +92,3 @@
tools:progress="70" /> tools:progress="70" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

View file

@ -1,10 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android" <androidx.fragment.app.FragmentContainerView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
tools:context=".MainActivity">
<androidx.fragment.app.FragmentContainerView
android:id="@+id/nav_host" android:id="@+id/nav_host"
android:name="androidx.navigation.fragment.NavHostFragment" android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent" android:layout_width="match_parent"
@ -12,4 +9,3 @@
app:defaultNavHost="true" app:defaultNavHost="true"
app:navGraph="@navigation/nav_main" app:navGraph="@navigation/nav_main"
tools:layout="@layout/fragment_main" /> tools:layout="@layout/fragment_main" />
</layout>

View file

@ -1,9 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android" <androidx.recyclerview.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"> xmlns:tools="http://schemas.android.com/tools"
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/accent_recycler" android:id="@+id/accent_recycler"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
@ -17,5 +15,3 @@
app:layout_constraintTop_toBottomOf="@+id/accent_header" app:layout_constraintTop_toBottomOf="@+id/accent_header"
tools:itemCount="18" tools:itemCount="18"
tools:listitem="@layout/item_accent" /> tools:listitem="@layout/item_accent" />
</layout>

View file

@ -1,14 +1,13 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"> xmlns:tools="http://schemas.android.com/tools"
<LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical" android:orientation="vertical"
android:paddingTop="@dimen/spacing_small"> android:paddingTop="@dimen/spacing_small">
<androidx.recyclerview.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
android:id="@+id/excluded_recycler" android:id="@+id/excluded_recycler"
android:layout_width="match_parent" android:layout_width="match_parent"
@ -30,5 +29,4 @@
android:textAppearance="@style/TextAppearance.Auxio.TitleMidLarge" android:textAppearance="@style/TextAppearance.Auxio.TitleMidLarge"
android:textColor="?android:attr/textColorSecondary" /> android:textColor="?android:attr/textColorSecondary" />
</LinearLayout> </LinearLayout>
</layout>

View file

@ -1,9 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android" <androidx.recyclerview.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"> xmlns:tools="http://schemas.android.com/tools"
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/tab_recycler" android:id="@+id/tab_recycler"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
@ -14,5 +12,3 @@
app:layout_constraintTop_toBottomOf="@+id/accent_header" app:layout_constraintTop_toBottomOf="@+id/accent_header"
tools:itemCount="5" tools:itemCount="5"
tools:listitem="@layout/item_tab" /> tools:listitem="@layout/item_tab" />
</layout>

View file

@ -1,14 +1,12 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android" <org.oxycblt.auxio.ui.EdgeCoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
tools:context=".settings.AboutFragment">
<org.oxycblt.auxio.ui.EdgeCoordinatorLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:background="?attr/colorSurface" android:background="?attr/colorSurface"
android:orientation="vertical"> android:orientation="vertical"
tools:context=".settings.AboutFragment">
<org.oxycblt.auxio.ui.EdgeAppBarLayout <org.oxycblt.auxio.ui.EdgeAppBarLayout
android:id="@+id/about_appbar" android:id="@+id/about_appbar"
@ -158,11 +156,11 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
app:drawableStartCompat="@drawable/ic_album" app:drawableStartCompat="@drawable/ic_album"
app:drawableTint="?attr/colorControlNormal"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/about_licenses" app:layout_constraintTop_toBottomOf="@+id/about_licenses"
tools:text="Songs Loaded: 1616" tools:text="Songs Loaded: 1616" />
app:drawableTint="?attr/colorControlNormal" />
<TextView <TextView
android:id="@+id/about_author" android:id="@+id/about_author"
@ -170,8 +168,8 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@string/lbl_author" android:text="@string/lbl_author"
app:drawableTint="?attr/colorControlNormal"
app:drawableStartCompat="@drawable/ic_artist" app:drawableStartCompat="@drawable/ic_artist"
app:drawableTint="?attr/colorControlNormal"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/about_song_count" /> app:layout_constraintTop_toBottomOf="@+id/about_song_count" />
@ -179,5 +177,4 @@
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.card.MaterialCardView> </com.google.android.material.card.MaterialCardView>
</androidx.core.widget.NestedScrollView> </androidx.core.widget.NestedScrollView>
</org.oxycblt.auxio.ui.EdgeCoordinatorLayout> </org.oxycblt.auxio.ui.EdgeCoordinatorLayout>
</layout>

View file

@ -1,10 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android" <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
tools:context=".detail.DetailFragment">
<FrameLayout
android:id="@+id/bar_layout" android:id="@+id/bar_layout"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent">
@ -34,5 +31,4 @@
tools:listitem="@layout/item_detail" /> tools:listitem="@layout/item_detail" />
</org.oxycblt.auxio.ui.EdgeCoordinatorLayout> </org.oxycblt.auxio.ui.EdgeCoordinatorLayout>
</FrameLayout> </FrameLayout>
</layout>

View file

@ -1,10 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android" <org.oxycblt.auxio.ui.EdgeCoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
tools:context=".home.HomeFragment">
<org.oxycblt.auxio.ui.EdgeCoordinatorLayout
android:id="@+id/main_layout" android:id="@+id/main_layout"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent">
@ -59,4 +56,3 @@
</org.oxycblt.auxio.home.EdgeFabContainer> </org.oxycblt.auxio.home.EdgeFabContainer>
</org.oxycblt.auxio.ui.EdgeCoordinatorLayout> </org.oxycblt.auxio.ui.EdgeCoordinatorLayout>
</layout>

View file

@ -1,9 +1,8 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<org.oxycblt.auxio.home.fastscroll.FastScrollRecyclerView <org.oxycblt.auxio.home.fastscroll.FastScrollRecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/home_recycler" android:id="@+id/home_recycler"
style="@style/Widget.Auxio.RecyclerView.WithAdaptiveFab" style="@style/Widget.Auxio.RecyclerView.WithAdaptiveFab"
android:layout_width="match_parent" android:layout_width="match_parent"
@ -11,4 +10,3 @@
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior" app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior"
tools:listitem="@layout/item_artist" /> tools:listitem="@layout/item_artist" />
</layout>

View file

@ -1,10 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android" <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
tools:context=".MainFragment">
<FrameLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent">
@ -63,5 +60,3 @@
</FrameLayout> </FrameLayout>
</FrameLayout> </FrameLayout>
</layout>

View file

@ -1,10 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android" <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
tools:context=".playback.PlaybackBarView">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
tools:parentTag="androidx.constraintlayout.widget.ConstraintLayout"> tools:parentTag="androidx.constraintlayout.widget.ConstraintLayout">
@ -68,4 +65,3 @@
tools:progress="70" /> tools:progress="70" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

View file

@ -1,10 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android" <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
tools:context=".playback.PlaybackPanelFragment">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/playback_layout" android:id="@+id/playback_layout"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent">
@ -170,4 +167,3 @@
app:tint="@color/sel_accented" /> app:tint="@color/sel_accented" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

View file

@ -1,10 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android" <org.oxycblt.auxio.ui.EdgeCoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
tools:context=".playback.queue.QueueFragment">
<org.oxycblt.auxio.ui.EdgeCoordinatorLayout
android:id="@+id/queue_coordinator" android:id="@+id/queue_coordinator"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
@ -36,4 +33,3 @@
tools:listitem="@layout/item_queue_song" /> tools:listitem="@layout/item_queue_song" />
</org.oxycblt.auxio.ui.EdgeCoordinatorLayout> </org.oxycblt.auxio.ui.EdgeCoordinatorLayout>
</layout>

View file

@ -1,9 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android" <org.oxycblt.auxio.ui.EdgeCoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"> xmlns:tools="http://schemas.android.com/tools"
<org.oxycblt.auxio.ui.EdgeCoordinatorLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent">
@ -55,4 +53,3 @@
tools:listitem="@layout/item_song" /> tools:listitem="@layout/item_song" />
</org.oxycblt.auxio.ui.EdgeCoordinatorLayout> </org.oxycblt.auxio.ui.EdgeCoordinatorLayout>
</layout>

View file

@ -1,10 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context=".settings.SettingsFragment">
<org.oxycblt.auxio.ui.EdgeCoordinatorLayout <org.oxycblt.auxio.ui.EdgeCoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/settings_coordinator" android:id="@+id/settings_coordinator"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
@ -33,4 +30,3 @@
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior" /> app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior" />
</org.oxycblt.auxio.ui.EdgeCoordinatorLayout> </org.oxycblt.auxio.ui.EdgeCoordinatorLayout>
</layout>

View file

@ -1,9 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android" <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
tools:context=".settings.pref.AccentAdapter.ViewHolder">
<FrameLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:paddingTop="@dimen/spacing_small" android:paddingTop="@dimen/spacing_small"
@ -22,5 +19,4 @@
tools:backgroundTint="?attr/colorPrimary" tools:backgroundTint="?attr/colorPrimary"
tools:ignore="ContentDescription, SpeakableTextPresentCheck" /> tools:ignore="ContentDescription, SpeakableTextPresentCheck" />
</FrameLayout> </FrameLayout>
</layout>

View file

@ -1,17 +1,8 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
tools:context=".ui.HeaderViewHolder">
<data>
<variable
name="header"
type="org.oxycblt.auxio.music.ActionHeader" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content"> android:layout_height="wrap_content">
@ -20,7 +11,6 @@
style="@style/Widget.Auxio.TextView.Header" style="@style/Widget.Auxio.TextView.Header"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@{context.getString(header.string)}"
app:layout_constraintBottom_toTopOf="@id/header_divider" app:layout_constraintBottom_toTopOf="@id/header_divider"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
@ -31,16 +21,15 @@
style="@style/Widget.AppCompat.Button.Borderless" style="@style/Widget.AppCompat.Button.Borderless"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:contentDescription="@{context.getString(header.desc)}"
android:minWidth="@dimen/size_btn_small" android:minWidth="@dimen/size_btn_small"
android:minHeight="@dimen/size_btn_small" android:minHeight="@dimen/size_btn_small"
android:background="@drawable/ui_unbounded_ripple" android:background="@drawable/ui_unbounded_ripple"
android:paddingStart="@dimen/spacing_medium" android:paddingStart="@dimen/spacing_medium"
android:paddingEnd="@dimen/spacing_medium" android:paddingEnd="@dimen/spacing_medium"
android:src="@{context.getDrawable(header.icon)}"
app:layout_constraintBottom_toTopOf="@id/header_divider" app:layout_constraintBottom_toTopOf="@id/header_divider"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
tools:ignore="ContentDescription"
tools:src="@drawable/ic_sort" /> tools:src="@drawable/ic_sort" />
<com.google.android.material.divider.MaterialDivider <com.google.android.material.divider.MaterialDivider
@ -50,4 +39,3 @@
app:layout_constraintBottom_toBottomOf="parent" /> app:layout_constraintBottom_toBottomOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

View file

@ -1,51 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context=".ui.AlbumViewHolder">
<data>
<variable
name="album"
type="org.oxycblt.auxio.music.Album" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout style="@style/Widget.Auxio.ItemLayout">
<org.oxycblt.auxio.coil.RoundableImageView
android:id="@+id/album_cover"
style="@style/Widget.Auxio.Image.Medium"
android:contentDescription="@{@string/desc_album_cover(album.resolvedName)}"
app:albumArt="@{album}"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:src="@drawable/ic_album" />
<TextView
android:id="@+id/album_name"
style="@style/Widget.Auxio.TextView.Item.Primary"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="@{album.rawName}"
app:layout_constraintBottom_toTopOf="@+id/album_info"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/album_cover"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_chainStyle="packed"
tools:text="Album Name" />
<TextView
android:id="@+id/album_info"
style="@style/Widget.Auxio.TextView.Item.Secondary"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:albumInfo="@{album}"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/album_cover"
app:layout_constraintTop_toBottomOf="@+id/album_name"
tools:text="Artist / 10 Songs" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>

View file

@ -1,25 +1,18 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
tools:context=".detail.recycler.AlbumDetailAdapter.AlbumSongViewHolder"> style="@style/Widget.Auxio.ItemLayout">
<data>
<variable
name="song"
type="org.oxycblt.auxio.music.Song" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout style="@style/Widget.Auxio.ItemLayout">
<ImageView <ImageView
android:id="@+id/song_track_placeholder" android:id="@+id/song_track_placeholder"
style="@style/Widget.Auxio.Image.Small"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:contentDescription="@string/def_track" android:contentDescription="@string/def_track"
android:src="@drawable/ic_song" android:src="@drawable/ic_song"
android:visibility="gone" android:visibility="invisible"
app:tint="@color/sel_accented" app:tint="@color/sel_accented"
app:layout_constraintBottom_toBottomOf="@+id/song_track" app:layout_constraintBottom_toBottomOf="@+id/song_track"
app:layout_constraintEnd_toEndOf="@+id/song_track" app:layout_constraintEnd_toEndOf="@+id/song_track"
@ -31,33 +24,30 @@
android:id="@+id/song_track" android:id="@+id/song_track"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:contentDescription="@{@string/desc_track_number(song.track)}"
android:gravity="center" android:gravity="center"
android:maxLines="1" android:maxLines="1"
android:minWidth="@dimen/size_track_number" android:minWidth="@dimen/size_track_number"
android:text="@{@string/fmt_track(song.track)}"
android:textAlignment="center" android:textAlignment="center"
android:textAppearance="@style/TextAppearance.Auxio.BodyLarge" android:textAppearance="@style/TextAppearance.Auxio.BodyLarge"
android:textColor="@color/sel_accented_secondary" android:textColor="@color/sel_accented_secondary"
android:textSize="@dimen/text_size_ext_title_mid_larger" android:textSize="@dimen/text_size_ext_title_mid_large"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/song_name" app:layout_constraintEnd_toStartOf="@+id/song_name"
app:layout_constraintHorizontal_bias="0.5" app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
tools:text="1" /> tools:text="16" />
<TextView <TextView
android:id="@+id/song_name" android:id="@+id/song_name"
style="@style/Widget.Auxio.TextView.Item.Primary" style="@style/Widget.Auxio.TextView.Item.Primary"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@{song.resolvedName}"
android:textColor="@color/sel_accented_primary" android:textColor="@color/sel_accented_primary"
app:layout_constraintBottom_toTopOf="@+id/song_duration" app:layout_constraintBottom_toTopOf="@+id/song_duration"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/song_track" app:layout_constraintStart_toEndOf="@+id/song_track"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="@+id/song_track"
app:layout_constraintVertical_chainStyle="packed" app:layout_constraintVertical_chainStyle="packed"
tools:text="Song Name" /> tools:text="Song Name" />
@ -66,13 +56,11 @@
style="@style/Widget.Auxio.TextView.Item.Secondary" style="@style/Widget.Auxio.TextView.Item.Secondary"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@{song.formattedDuration}"
android:textColor="?android:attr/textColorSecondary" android:textColor="?android:attr/textColorSecondary"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="@+id/song_track"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/song_track" app:layout_constraintStart_toEndOf="@+id/song_track"
app:layout_constraintTop_toBottomOf="@+id/song_name" app:layout_constraintTop_toBottomOf="@+id/song_name"
tools:text="16:16" /> tools:text="16:16" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

View file

@ -1,23 +1,13 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
tools:context=".ui.ArtistViewHolder"> xmlns:app="http://schemas.android.com/apk/res-auto"
style="@style/Widget.Auxio.ItemLayout">
<data>
<variable
name="artist"
type="org.oxycblt.auxio.music.Artist" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout style="@style/Widget.Auxio.ItemLayout">
<org.oxycblt.auxio.coil.RoundableImageView <org.oxycblt.auxio.coil.RoundableImageView
android:id="@+id/artist_image" android:id="@+id/artist_image"
style="@style/Widget.Auxio.Image.Medium" style="@style/Widget.Auxio.Image.Medium"
android:contentDescription="@{@string/desc_artist_image(artist.resolvedName)}"
app:artistImage="@{artist}"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
@ -28,8 +18,7 @@
style="@style/Widget.Auxio.TextView.Item.Primary" style="@style/Widget.Auxio.TextView.Item.Primary"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@{artist.resolvedName}" app:layout_constraintBottom_toTopOf="@+id/artist_info"
app:layout_constraintBottom_toTopOf="@+id/artist_details"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/artist_image" app:layout_constraintStart_toEndOf="@+id/artist_image"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
@ -37,11 +26,10 @@
tools:text="Artist Name" /> tools:text="Artist Name" />
<TextView <TextView
android:id="@+id/artist_details" android:id="@+id/artist_info"
style="@style/Widget.Auxio.TextView.Item.Secondary" style="@style/Widget.Auxio.TextView.Item.Secondary"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
app:artistInfo="@{artist}"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/artist_image" app:layout_constraintStart_toEndOf="@+id/artist_image"
@ -49,4 +37,3 @@
tools:text="2 Albums, 20 Songs" /> tools:text="2 Albums, 20 Songs" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

View file

@ -1,52 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context=".detail.recycler.ArtistDetailAdapter.ArtistAlbumViewHolder">
<data>
<variable
name="album"
type="org.oxycblt.auxio.music.Album" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout style="@style/Widget.Auxio.ItemLayout">
<org.oxycblt.auxio.coil.RoundableImageView
android:id="@+id/album_cover"
style="@style/Widget.Auxio.Image.Medium"
android:contentDescription="@{@string/desc_album_cover(album.resolvedName)}"
app:albumArt="@{album}"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:src="@drawable/ic_album" />
<TextView
android:id="@+id/album_name"
style="@style/Widget.Auxio.TextView.Item.Primary"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="@{album.resolvedName}"
android:textColor="@color/sel_accented_primary"
app:layout_constraintBottom_toTopOf="@+id/album_year"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/album_cover"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_chainStyle="packed"
tools:text="Album Name" />
<TextView
android:id="@+id/album_year"
style="@style/Widget.Auxio.TextView.Item.Secondary"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="@{album.year != 0 ? String.valueOf(album.year) : @string/def_date}"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/album_cover"
app:layout_constraintTop_toBottomOf="@+id/album_name"
tools:text="2020" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>

View file

@ -1,69 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context=".ui.SongViewHolder">
<data>
<variable
name="song"
type="org.oxycblt.auxio.music.Song" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout style="@style/Widget.Auxio.ItemLayout">
<org.oxycblt.auxio.coil.RoundableImageView
android:id="@+id/album_cover"
style="@style/Widget.Auxio.Image.Small"
android:contentDescription="@{@string/desc_album_cover(song.resolvedName)}"
app:albumArt="@{song}"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:src="@drawable/ic_album" />
<TextView
android:id="@+id/song_name"
style="@style/Widget.Auxio.TextView.Item.Primary"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="@dimen/spacing_medium"
android:text="@{song.resolvedName}"
android:textColor="@color/sel_accented_primary"
app:layout_constraintBottom_toTopOf="@+id/song_info"
app:layout_constraintEnd_toStartOf="@+id/song_duration"
app:layout_constraintStart_toEndOf="@+id/album_cover"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_chainStyle="packed"
tools:text="Song Name" />
<TextView
android:id="@+id/song_info"
style="@style/Widget.Auxio.TextView.Item.Secondary"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="@dimen/spacing_medium"
android:text="@{song.resolvedAlbumName}"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/song_duration"
app:layout_constraintStart_toEndOf="@+id/album_cover"
app:layout_constraintTop_toBottomOf="@+id/song_name"
tools:text="Album" />
<TextView
android:id="@+id/song_duration"
style="@style/Widget.Auxio.TextView.Item.Tertiary"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="none"
android:gravity="end"
android:text="@{song.formattedDuration}"
android:textAlignment="viewEnd"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="16:16" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>

View file

@ -1,11 +1,8 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"> xmlns:tools="http://schemas.android.com/tools"
<!-- This layout is re-used across all detail fragments. Do not add databinding. -->
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:padding="@dimen/spacing_medium"> android:padding="@dimen/spacing_medium">
@ -75,4 +72,3 @@
app:layout_constraintStart_toEndOf="@+id/detail_play_button" app:layout_constraintStart_toEndOf="@+id/detail_play_button"
app:layout_constraintTop_toTopOf="@+id/detail_play_button" /> app:layout_constraintTop_toTopOf="@+id/detail_play_button" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

View file

@ -1,14 +1,13 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<androidx.constraintlayout.widget.ConstraintLayout <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
style="@style/Widget.Auxio.ItemLayout"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:clickable="false" android:clickable="false"
android:focusable="false" android:focusable="false"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
style="@style/Widget.Auxio.ItemLayout"
android:padding="0dp"> android:padding="0dp">
<TextView <TextView
@ -42,4 +41,3 @@
app:tint="?attr/colorControlNormal" /> app:tint="?attr/colorControlNormal" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

View file

@ -1,52 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context=".ui.GenreViewHolder">
<data>
<variable
name="genre"
type="org.oxycblt.auxio.music.Genre" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout style="@style/Widget.Auxio.ItemLayout">
<org.oxycblt.auxio.coil.RoundableImageView
android:id="@+id/genre_image"
style="@style/Widget.Auxio.Image.Medium"
android:contentDescription="@{@string/desc_genre_image(genre.resolvedName)}"
app:genreImage="@{genre}"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:src="@drawable/ic_genre" />
<TextView
android:id="@+id/genre_name"
style="@style/Widget.Auxio.TextView.Item.Primary"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="@{genre.resolvedName}"
app:layout_constraintBottom_toTopOf="@+id/genre_count"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/genre_image"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_chainStyle="packed"
tools:text="Genre Name" />
<TextView
android:id="@+id/genre_count"
style="@style/Widget.Auxio.TextView.Item.Secondary"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:genreInfo="@{genre}"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/genre_image"
app:layout_constraintTop_toBottomOf="@+id/genre_name"
tools:text="40 Songs" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>

View file

@ -1,69 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context=".detail.recycler.GenreDetailAdapter.GenreSongViewHolder">
<data>
<variable
name="song"
type="org.oxycblt.auxio.music.Song" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout style="@style/Widget.Auxio.ItemLayout">
<org.oxycblt.auxio.coil.RoundableImageView
android:id="@+id/album_cover"
style="@style/Widget.Auxio.Image.Small"
android:contentDescription="@{@string/desc_album_cover(song.resolvedName)}"
app:albumArt="@{song}"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:src="@drawable/ic_album" />
<TextView
android:id="@+id/song_name"
style="@style/Widget.Auxio.TextView.Item.Primary"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="@dimen/spacing_medium"
android:text="@{song.resolvedName}"
android:textColor="@color/sel_accented_primary"
app:layout_constraintBottom_toTopOf="@+id/song_info"
app:layout_constraintEnd_toStartOf="@+id/song_duration"
app:layout_constraintStart_toEndOf="@+id/album_cover"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_chainStyle="packed"
tools:text="Song Name" />
<TextView
android:id="@+id/song_info"
style="@style/Widget.Auxio.TextView.Item.Secondary"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="@dimen/spacing_medium"
app:songInfo="@{song}"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/song_duration"
app:layout_constraintStart_toEndOf="@+id/album_cover"
app:layout_constraintTop_toBottomOf="@+id/song_name"
tools:text="Artist / Album" />
<TextView
android:id="@+id/song_duration"
style="@style/Widget.Auxio.TextView.Item.Tertiary"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="none"
android:gravity="end"
android:text="@{song.formattedDuration}"
android:textAlignment="viewEnd"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="16:16" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>

View file

@ -1,17 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android" <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
tools:context=".ui.HeaderViewHolder">
<data>
<variable
name="header"
type="org.oxycblt.auxio.music.Header" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content"> android:layout_height="wrap_content">
@ -20,7 +10,6 @@
style="@style/Widget.Auxio.TextView.Header" style="@style/Widget.Auxio.TextView.Header"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@{context.getString(header.string)}"
app:layout_constraintBottom_toTopOf="@id/header_divider" app:layout_constraintBottom_toTopOf="@id/header_divider"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
@ -33,4 +22,3 @@
app:layout_constraintBottom_toBottomOf="parent" /> app:layout_constraintBottom_toBottomOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

View file

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
style="@style/Widget.Auxio.ItemLayout">
<org.oxycblt.auxio.coil.RoundableImageView
android:id="@+id/parent_image"
style="@style/Widget.Auxio.Image.Medium"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:src="@drawable/ic_artist" />
<TextView
android:id="@+id/parent_name"
style="@style/Widget.Auxio.TextView.Item.Primary"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:textColor="@color/sel_accented_primary"
app:layout_constraintBottom_toTopOf="@+id/parent_info"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/parent_image"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_chainStyle="packed"
tools:text="Artist" />
<TextView
android:id="@+id/parent_info"
style="@style/Widget.Auxio.TextView.Item.Secondary"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/parent_image"
app:layout_constraintTop_toBottomOf="@+id/parent_name"
tools:text="Info" />
</androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -1,17 +1,8 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android" <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
tools:context=".playback.queue.QueueAdapter.QueueSongViewHolder">
<data>
<variable
name="song"
type="org.oxycblt.auxio.music.Song" />
</data>
<FrameLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:background="?attr/colorSurface"> android:background="?attr/colorSurface">
@ -39,11 +30,9 @@
android:background="?attr/colorSurface"> android:background="?attr/colorSurface">
<org.oxycblt.auxio.coil.RoundableImageView <org.oxycblt.auxio.coil.RoundableImageView
android:id="@+id/album_cover" android:id="@+id/song_album_cover"
style="@style/Widget.Auxio.Image.Small" style="@style/Widget.Auxio.Image.Small"
android:layout_margin="@dimen/spacing_medium" android:layout_margin="@dimen/spacing_medium"
android:contentDescription="@{@string/desc_album_cover(song.resolvedName)}"
app:albumArt="@{song}"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
@ -55,10 +44,9 @@
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginEnd="@dimen/spacing_medium" android:layout_marginEnd="@dimen/spacing_medium"
android:text="@{song.resolvedName}"
app:layout_constraintBottom_toTopOf="@+id/song_info" app:layout_constraintBottom_toTopOf="@+id/song_info"
app:layout_constraintEnd_toStartOf="@+id/song_drag_handle" app:layout_constraintEnd_toStartOf="@+id/song_drag_handle"
app:layout_constraintStart_toEndOf="@+id/album_cover" app:layout_constraintStart_toEndOf="@+id/song_album_cover"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_chainStyle="packed" app:layout_constraintVertical_chainStyle="packed"
tools:text="Song Name" /> tools:text="Song Name" />
@ -69,10 +57,9 @@
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginEnd="@dimen/spacing_medium" android:layout_marginEnd="@dimen/spacing_medium"
app:songInfo="@{song}"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/song_drag_handle" app:layout_constraintEnd_toStartOf="@+id/song_drag_handle"
app:layout_constraintStart_toEndOf="@+id/album_cover" app:layout_constraintStart_toEndOf="@+id/song_album_cover"
app:layout_constraintTop_toBottomOf="@+id/song_name" app:layout_constraintTop_toBottomOf="@+id/song_name"
tools:text="Artist / Album" /> tools:text="Artist / Album" />
@ -89,10 +76,9 @@
android:paddingEnd="@dimen/spacing_medium" android:paddingEnd="@dimen/spacing_medium"
android:scaleType="center" android:scaleType="center"
android:src="@drawable/ic_handle" android:src="@drawable/ic_handle"
app:layout_constraintBottom_toBottomOf="@+id/album_cover" app:layout_constraintBottom_toBottomOf="@+id/song_album_cover"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@+id/album_cover" /> app:layout_constraintTop_toTopOf="@+id/song_album_cover" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
</FrameLayout> </FrameLayout>
</layout>

View file

@ -1,23 +1,12 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android" <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
tools:context=".ui.SongViewHolder"> xmlns:app="http://schemas.android.com/apk/res-auto"
style="@style/Widget.Auxio.ItemLayout">
<data>
<variable
name="song"
type="org.oxycblt.auxio.music.Song" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout style="@style/Widget.Auxio.ItemLayout">
<org.oxycblt.auxio.coil.RoundableImageView <org.oxycblt.auxio.coil.RoundableImageView
android:id="@+id/album_cover" android:id="@+id/song_album_cover"
style="@style/Widget.Auxio.Image.Small" style="@style/Widget.Auxio.Image.Small"
android:contentDescription="@{@string/desc_album_cover(song.resolvedName)}"
app:albumArt="@{song}"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
@ -28,25 +17,23 @@
style="@style/Widget.Auxio.TextView.Item.Primary" style="@style/Widget.Auxio.TextView.Item.Primary"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@{song.resolvedName}" android:textColor="@color/sel_accented_primary"
app:layout_constraintBottom_toTopOf="@+id/song_info" app:layout_constraintBottom_toTopOf="@+id/song_info"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/album_cover" app:layout_constraintStart_toEndOf="@+id/song_album_cover"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_chainStyle="packed" app:layout_constraintVertical_chainStyle="packed"
tools:text="Song Name" /> tools:text="Song" />
<TextView <TextView
android:id="@+id/song_info" android:id="@+id/song_info"
style="@style/Widget.Auxio.TextView.Item.Secondary" style="@style/Widget.Auxio.TextView.Item.Secondary"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
app:songInfo="@{song}"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/album_cover" app:layout_constraintStart_toEndOf="@+id/song_album_cover"
app:layout_constraintTop_toBottomOf="@+id/song_name" app:layout_constraintTop_toBottomOf="@+id/song_name"
tools:text="Artist / Album" /> tools:text="Info" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

View file

@ -1,12 +1,11 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<androidx.constraintlayout.widget.ConstraintLayout <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
style="@style/Widget.Auxio.ItemLayout"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
style="@style/Widget.Auxio.ItemLayout"
android:padding="0dp"> android:padding="0dp">
<com.google.android.material.checkbox.MaterialCheckBox <com.google.android.material.checkbox.MaterialCheckBox
@ -47,4 +46,3 @@
app:layout_constraintTop_toTopOf="@+id/tab_icon" /> app:layout_constraintTop_toTopOf="@+id/tab_icon" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

View file

@ -1,9 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android" <merge xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"> xmlns:tools="http://schemas.android.com/tools"
<merge
tools:layout_height="wrap_content" tools:layout_height="wrap_content"
tools:layout_width="match_parent" tools:layout_width="match_parent"
tools:parentTag="androidx.constraintlayout.widget.ConstraintLayout"> tools:parentTag="androidx.constraintlayout.widget.ConstraintLayout">
@ -50,4 +48,3 @@
tools:text="16:16" /> tools:text="16:16" />
</merge> </merge>
</layout>

View file

@ -26,7 +26,6 @@
<dimen name="text_size_ext_label_larger">16sp</dimen> <dimen name="text_size_ext_label_larger">16sp</dimen>
<dimen name="text_size_ext_title_mid_large">18sp</dimen> <dimen name="text_size_ext_title_mid_large">18sp</dimen>
<dimen name="text_size_ext_title_mid_larger">20sp</dimen>
<!-- Misc --> <!-- Misc -->
<dimen name="elevation_small">2dp</dimen> <dimen name="elevation_small">2dp</dimen>

View file

@ -6,5 +6,5 @@
<!-- Format Namespace | Value formatting/plurals --> <!-- Format Namespace | Value formatting/plurals -->
<string name="fmt_two" translatable="false">%1$s • %2$s</string> <string name="fmt_two" translatable="false">%1$s • %2$s</string>
<string name="fmt_three" translatable="false">%1$s • %2$s • %3$s</string> <string name="fmt_three" translatable="false">%1$s • %2$s • %3$s</string>
<string name="fmt_track" translatable="false">%d</string> <string name="fmt_number" translatable="false">%d</string>
</resources> </resources>

View file

@ -44,16 +44,16 @@ should be added as a new `Fragment` implementation and added to one of the two n
- `nav_main`: Navigation *from* `MainFragment` - `nav_main`: Navigation *from* `MainFragment`
- `nav_explore`: Navigation *in* `MainFragment` - `nav_explore`: Navigation *in* `MainFragment`
Fragments themselves are organized in order of lifecycle. So the first override would be `onCreate`, followed by Fragments themselves are based off a super class called `ViewBindingFragment` that takes a view-binding and then
`onCreateView`, and so on. `onCreateView` is where all view instantiation and configuration takes place, and leverages it within the fragment lifecycle.
is separated into three phases:
- Create variables [Bindings, Adapters, etc] - Create variables [Bindings, Adapters, etc]
- Set up the UI - Set up the UI
- Set up ViewModel instances and LiveData observers - Set up ViewModel instances and LiveData observers
`findViewById` is to **only** be used when interfacing with non-Auxio views. Otherwise, view-binding should be `findViewById` is to **only** be used when interfacing with non-Auxio views. Otherwise, view-binding should be
used in all cases. Avoid usages of databinding outside of the `onCreateView` step unless absolutely necessary. used in all cases. Code that involves retrieving the binding should be isolated into its own function, with
the binding being obtained by calling `requireBinding`.
At times it may be more appropriate to use a `View` instead of a full blown fragment. This is okay as long as At times it may be more appropriate to use a `View` instead of a full blown fragment. This is okay as long as
view-binding is still used. view-binding is still used.
@ -62,11 +62,6 @@ When creating a ViewHolder for a `RecyclerView`, one should use `BaseViewHolder`
and automate some code shared across all ViewHolders. The only exceptions to this case are for ViewHolders that and automate some code shared across all ViewHolders. The only exceptions to this case are for ViewHolders that
correspond to non-`BaseModel` data, in which a normal ViewHolder can be used instead. correspond to non-`BaseModel` data, in which a normal ViewHolder can be used instead.
Data is often bound using Binding Adapters, which are XML attributes assigned in layout files that can automatically
display data, usually written as `app:bindingAdapterName="@{data}"`. Its recommended to use these instead of applying
the attributes directly unless absolutely necessary. Usually it's okay to apply data programmatically if you begin
to duplicate layouts simply because they apply to different data objects, such as the detail UIs.
#### Object communication #### Object communication
Auxio's codebase is mostly centered around 4 different types of code that communicates with each-other. Auxio's codebase is mostly centered around 4 different types of code that communicates with each-other.