Add Artist item
Add the Artist item and switch LibraryFragment over to it.
This commit is contained in:
parent
139cf3c089
commit
7a2c779fe2
15 changed files with 172 additions and 29 deletions
|
|
@ -10,7 +10,7 @@ import androidx.fragment.app.Fragment
|
|||
import androidx.lifecycle.ViewModelProvider
|
||||
import org.oxycblt.auxio.R
|
||||
import org.oxycblt.auxio.databinding.FragmentLibraryBinding
|
||||
import org.oxycblt.auxio.recycler.adapters.AlbumAdapter
|
||||
import org.oxycblt.auxio.recycler.adapters.ArtistAdapter
|
||||
import org.oxycblt.auxio.recycler.applyDivider
|
||||
import org.oxycblt.auxio.recycler.viewholders.ClickListener
|
||||
|
||||
|
|
@ -29,10 +29,10 @@ class LibraryFragment : Fragment() {
|
|||
inflater, R.layout.fragment_library, container, false
|
||||
)
|
||||
|
||||
binding.libraryRecycler.adapter = AlbumAdapter(
|
||||
libraryModel.albums.value!!,
|
||||
ClickListener { album ->
|
||||
Log.d(this::class.simpleName, album.title)
|
||||
binding.libraryRecycler.adapter = ArtistAdapter(
|
||||
libraryModel.artists.value!!,
|
||||
ClickListener { artist ->
|
||||
Log.d(this::class.simpleName, artist.name)
|
||||
}
|
||||
)
|
||||
binding.libraryRecycler.applyDivider()
|
||||
|
|
|
|||
|
|
@ -21,6 +21,8 @@ import org.oxycblt.auxio.music.processing.MusicLoaderResponse
|
|||
|
||||
class LoadingFragment : Fragment(R.layout.fragment_loading) {
|
||||
|
||||
// TODO: Phase out LoadingFragment
|
||||
|
||||
private val loadingModel: LoadingViewModel by lazy {
|
||||
ViewModelProvider(
|
||||
this,
|
||||
|
|
@ -108,6 +110,7 @@ class LoadingFragment : Fragment(R.layout.fragment_loading) {
|
|||
// Don't run this if the value is null, Which is what the value changes to after
|
||||
// this is run.
|
||||
repoResponse?.let { response ->
|
||||
binding.loadingBar.visibility = View.GONE
|
||||
|
||||
if (response == MusicLoaderResponse.DONE) {
|
||||
val inflater = TransitionInflater.from(requireContext())
|
||||
|
|
@ -119,7 +122,6 @@ class LoadingFragment : Fragment(R.layout.fragment_loading) {
|
|||
} else {
|
||||
// If the response wasn't a success, then show the specific error message
|
||||
// depending on which error response was given, along with a retry button
|
||||
binding.loadingBar.visibility = View.GONE
|
||||
binding.errorText.visibility = View.VISIBLE
|
||||
binding.statusIcon.visibility = View.VISIBLE
|
||||
binding.retryButton.visibility = View.VISIBLE
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import androidx.databinding.BindingAdapter
|
|||
import coil.load
|
||||
import org.oxycblt.auxio.R
|
||||
import org.oxycblt.auxio.music.models.Album
|
||||
import org.oxycblt.auxio.music.models.Artist
|
||||
import org.oxycblt.auxio.music.models.Song
|
||||
|
||||
private val ID3_GENRES = arrayOf(
|
||||
|
|
@ -83,12 +84,32 @@ fun ImageView.getCoverArt(any: Any) {
|
|||
}
|
||||
}
|
||||
|
||||
fun Int.toSongCount(): Int {
|
||||
return if (this < 2) {
|
||||
R.string.label_single_song
|
||||
} else {
|
||||
R.string.format_multi_song_count
|
||||
}
|
||||
}
|
||||
|
||||
fun Int.toAlbumCount(): Int {
|
||||
return if (this < 2) {
|
||||
R.string.label_single_album
|
||||
} else {
|
||||
R.string.format_album_count
|
||||
}
|
||||
}
|
||||
|
||||
// Format the amount of songs in an album
|
||||
@BindingAdapter("songCount")
|
||||
fun TextView.getAlbumSongs(album: Album) {
|
||||
text = if (album.numSongs < 2) {
|
||||
context.getString(R.string.label_single_song)
|
||||
} else {
|
||||
context.getString(R.string.format_multi_song_count, album.numSongs.toString())
|
||||
}
|
||||
text = context.getString(album.numSongs.toSongCount(), album.numSongs)
|
||||
}
|
||||
|
||||
@BindingAdapter("albumSongCount")
|
||||
fun TextView.getSongAlbumCount(artist: Artist) {
|
||||
val albums = context.getString(artist.numAlbums.toAlbumCount(), artist.numAlbums)
|
||||
val songs = context.getString(artist.numSongs.toSongCount(), artist.numSongs)
|
||||
|
||||
text = context.getString(R.string.format_combined_song_album, albums, songs)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,4 +8,5 @@ data class Artist(
|
|||
) {
|
||||
val albums = mutableListOf<Album>()
|
||||
var numAlbums = 0
|
||||
var numSongs = 0
|
||||
}
|
||||
|
|
|
|||
|
|
@ -80,6 +80,9 @@ class MusicSorter(
|
|||
}
|
||||
|
||||
artist.numAlbums = artist.albums.size
|
||||
artist.albums.forEach { album ->
|
||||
artist.numSongs += album.numSongs
|
||||
}
|
||||
|
||||
unknownAlbums.removeAll(artistAlbums)
|
||||
}
|
||||
|
|
@ -95,7 +98,10 @@ class MusicSorter(
|
|||
unknownArtist.albums.add(album)
|
||||
}
|
||||
|
||||
unknownArtist.numAlbums = albums.size
|
||||
unknownArtist.numAlbums = unknownArtist.albums.size
|
||||
unknownArtist.albums.forEach { album ->
|
||||
unknownArtist.numSongs += album.numSongs
|
||||
}
|
||||
|
||||
artists.add(unknownArtist)
|
||||
|
||||
|
|
|
|||
|
|
@ -29,10 +29,6 @@ class AlbumAdapter(
|
|||
override fun onBindViewHolder(holder: AlbumViewHolder, position: Int) {
|
||||
val album = data[position]
|
||||
|
||||
holder.itemView.setOnClickListener {
|
||||
listener.onClick(album)
|
||||
}
|
||||
|
||||
holder.bind(album)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,34 @@
|
|||
package org.oxycblt.auxio.recycler.adapters
|
||||
|
||||
import android.view.LayoutInflater
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import org.oxycblt.auxio.databinding.ArtistItemBinding
|
||||
import org.oxycblt.auxio.music.models.Artist
|
||||
import org.oxycblt.auxio.recycler.viewholders.ArtistViewHolder
|
||||
import org.oxycblt.auxio.recycler.viewholders.ClickListener
|
||||
|
||||
class ArtistAdapter(
|
||||
private val data: List<Artist>,
|
||||
private val listener: ClickListener<Artist>
|
||||
) : RecyclerView.Adapter<ArtistViewHolder>() {
|
||||
|
||||
override fun getItemCount(): Int = data.size
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ArtistViewHolder {
|
||||
val binding = ArtistItemBinding.inflate(LayoutInflater.from(parent.context))
|
||||
|
||||
// Force the item to *actually* be the screen width so ellipsizing can work.
|
||||
binding.root.layoutParams = RecyclerView.LayoutParams(
|
||||
RecyclerView.LayoutParams.MATCH_PARENT, RecyclerView.LayoutParams.WRAP_CONTENT
|
||||
)
|
||||
|
||||
return ArtistViewHolder(binding)
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: ArtistViewHolder, position: Int) {
|
||||
val album = data[position]
|
||||
|
||||
holder.bind(album)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
package org.oxycblt.auxio.recycler.viewholders
|
||||
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import org.oxycblt.auxio.databinding.ArtistItemBinding
|
||||
import org.oxycblt.auxio.music.models.Artist
|
||||
|
||||
// Generic ViewHolder for an album
|
||||
class ArtistViewHolder(
|
||||
private val binding: ArtistItemBinding
|
||||
) : RecyclerView.ViewHolder(binding.root) {
|
||||
|
||||
// Bind the view w/new data
|
||||
fun bind(artist: Artist) {
|
||||
binding.artist = artist
|
||||
|
||||
binding.artistName.requestLayout()
|
||||
|
||||
binding.executePendingBindings()
|
||||
}
|
||||
}
|
||||
|
|
@ -13,7 +13,6 @@
|
|||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:animateLayoutChanges="true"
|
||||
android:background="@drawable/ripple"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
|
|
@ -23,12 +22,12 @@
|
|||
android:id="@+id/cover"
|
||||
android:layout_width="@dimen/cover_size_normal"
|
||||
android:layout_height="@dimen/cover_size_normal"
|
||||
android:contentDescription="@{@string/description_cover_art + album.title}"
|
||||
app:coverArt="@{album}"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:src="@tools:sample/backgrounds/scenic" />
|
||||
tools:src="@tools:sample/backgrounds/scenic"
|
||||
tools:ignore="ContentDescription" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/album_name"
|
||||
|
|
|
|||
61
app/src/main/res/layout/artist_item.xml
Normal file
61
app/src/main/res/layout/artist_item.xml
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<data>
|
||||
|
||||
<variable
|
||||
name="artist"
|
||||
type="org.oxycblt.auxio.music.models.Artist" />
|
||||
</data>
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/ripple"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:padding="@dimen/padding_medium">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/artist_image"
|
||||
android:layout_width="@dimen/cover_size_normal"
|
||||
android:layout_height="@dimen/cover_size_normal"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:src="@tools:sample/backgrounds/scenic"
|
||||
tools:ignore="ContentDescription" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/artist_name"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/margin_medium"
|
||||
android:text="@{artist.name}"
|
||||
android:textAppearance="?android:attr/textAppearanceListItem"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
app:layout_constraintBottom_toTopOf="@+id/album_song_count"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/artist_image"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_chainStyle="packed"
|
||||
tools:text="Artist Name" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/album_song_count"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/margin_medium"
|
||||
android:textAppearance="?android:attr/textAppearanceListItemSecondary"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
app:albumSongCount="@{artist}"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/artist_image"
|
||||
app:layout_constraintTop_toBottomOf="@+id/artist_name"
|
||||
tools:text="2 Albums, 20 Songs" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</layout>
|
||||
|
|
@ -6,6 +6,7 @@
|
|||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:animateLayoutChanges="true"
|
||||
android:orientation="vertical">
|
||||
|
||||
<androidx.appcompat.widget.Toolbar
|
||||
|
|
@ -15,7 +16,8 @@
|
|||
android:background="?android:attr/windowBackground"
|
||||
android:elevation="@dimen/elevation_normal"
|
||||
app:titleTextAppearance="@style/TextAppearance.Toolbar.Bold"
|
||||
app:title="@string/title_library_fragment" />
|
||||
app:title="@string/title_library_fragment"
|
||||
tools:titleTextColor="@color/blue"/>
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/library_recycler"
|
||||
|
|
|
|||
|
|
@ -39,14 +39,14 @@
|
|||
android:indeterminateTint="?attr/colorPrimary"
|
||||
android:indeterminateTintMode="src_in"
|
||||
android:src="@drawable/ic_error"
|
||||
android:contentDescription="@string/description_error_icon"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toTopOf="@+id/error_text"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/loading_bar"
|
||||
app:srcCompat="@drawable/ic_error"
|
||||
tools:tint="@color/blue" />
|
||||
tools:tint="@color/blue"
|
||||
tools:ignore="ContentDescription" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/error_text"
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:animateLayoutChanges="true"
|
||||
android:orientation="vertical">
|
||||
|
||||
<androidx.appcompat.widget.Toolbar
|
||||
|
|
@ -16,7 +17,8 @@
|
|||
android:elevation="@dimen/elevation_normal"
|
||||
app:titleTextAppearance="@style/TextAppearance.Toolbar.Bold"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:title="@string/title_all_songs" />
|
||||
app:title="@string/title_all_songs"
|
||||
tools:titleTextColor="@color/blue"/>
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/song_recycler"
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@
|
|||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:animateLayoutChanges="true"
|
||||
android:background="@drawable/ripple"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
|
|
@ -23,12 +22,12 @@
|
|||
android:id="@+id/cover"
|
||||
android:layout_width="@dimen/cover_size_compact"
|
||||
android:layout_height="@dimen/cover_size_compact"
|
||||
android:contentDescription="@{@string/description_cover_art + song.album.title}"
|
||||
app:coverArt="@{song}"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:src="@tools:sample/backgrounds/scenic" />
|
||||
tools:src="@tools:sample/backgrounds/scenic"
|
||||
tools:ignore="ContentDescription" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/song_name"
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
<string name="label_retry">Retry</string>
|
||||
<string name="label_grant">Grant</string>
|
||||
<string name="label_single_song">1 Song</string>
|
||||
<string name="label_single_album">1 Album</string>
|
||||
|
||||
<string name="placeholder_unknown_genre">Unknown Genre</string>
|
||||
<string name="placeholder_unknown_artist">Unknown Artist</string>
|
||||
|
|
@ -19,7 +20,6 @@
|
|||
|
||||
<string name="format_multi_song_count">%s Songs</string>
|
||||
<string name="format_song_info">%s / %s</string>
|
||||
|
||||
<string name="description_cover_art">Cover art for </string>
|
||||
<string name="description_error_icon">Error Icon</string>
|
||||
<string name="format_album_count">%s Albums</string>
|
||||
<string name="format_combined_song_album">%s, %s</string>
|
||||
</resources>
|
||||
Loading…
Reference in a new issue