diff --git a/core/subsonic-api/src/main/kotlin/org/moire/ultrasonic/api/subsonic/models/Album.kt b/core/subsonic-api/src/main/kotlin/org/moire/ultrasonic/api/subsonic/models/Album.kt index 5dacd51b..801634c3 100644 --- a/core/subsonic-api/src/main/kotlin/org/moire/ultrasonic/api/subsonic/models/Album.kt +++ b/core/subsonic-api/src/main/kotlin/org/moire/ultrasonic/api/subsonic/models/Album.kt @@ -5,14 +5,19 @@ import java.util.Calendar data class Album( val id: String = "", + val parent: String = "", + val album: String = "", + val title: String = "", val name: String = "", + val discNumber: Int = 0, val coverArt: String = "", + val songCount: Int = 0, + val created: Calendar? = null, val artist: String = "", val artistId: String = "", - val songCount: Int = 0, val duration: Int = 0, - val created: Calendar? = null, val year: Int = 0, val genre: String = "", - @JsonProperty("song") val songList: List = emptyList() + @JsonProperty("song") val songList: List = emptyList(), + @JsonProperty("starred") val starredDate: String = "" ) diff --git a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/domain/APIAlbumConverter.kt b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/domain/APIAlbumConverter.kt index efcebe2e..0dac2654 100644 --- a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/domain/APIAlbumConverter.kt +++ b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/domain/APIAlbumConverter.kt @@ -16,7 +16,8 @@ fun Album.toDomainEntity(): MusicDirectory.Entry = MusicDirectory.Entry( duration = this@toDomainEntity.duration, created = this@toDomainEntity.created?.time, year = this@toDomainEntity.year, - genre = this@toDomainEntity.genre + genre = this@toDomainEntity.genre, + starred = this@toDomainEntity.starredDate.isNotEmpty() ) fun Album.toMusicDirectoryDomainEntity(): MusicDirectory = MusicDirectory().apply { diff --git a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/AlbumListFragment.kt b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/AlbumListFragment.kt index 97285d68..9cd0a050 100644 --- a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/AlbumListFragment.kt +++ b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/AlbumListFragment.kt @@ -63,7 +63,8 @@ class AlbumListFragment : GenericListFragment onItemClick(entry) }, { menuItem, entry -> onContextMenuItemSelected(menuItem, entry) }, imageLoaderProvider.getImageLoader(), - onMusicFolderUpdate + onMusicFolderUpdate, + requireContext() ) } diff --git a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/AlbumRowAdapter.kt b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/AlbumRowAdapter.kt index 239fb237..c9dcbabe 100644 --- a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/AlbumRowAdapter.kt +++ b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/AlbumRowAdapter.kt @@ -7,15 +7,22 @@ package org.moire.ultrasonic.fragment +import android.content.Context +import android.graphics.drawable.Drawable import android.view.MenuItem import android.view.View import android.widget.ImageView import android.widget.LinearLayout import android.widget.TextView import androidx.recyclerview.widget.RecyclerView +import java.lang.Exception import org.moire.ultrasonic.R import org.moire.ultrasonic.domain.MusicDirectory import org.moire.ultrasonic.imageloader.ImageLoader +import org.moire.ultrasonic.service.MusicServiceFactory.getMusicService +import org.moire.ultrasonic.util.Settings.shouldUseId3Tags +import org.moire.ultrasonic.util.Util +import timber.log.Timber /** * Creates a Row in a RecyclerView which contains the details of an Album @@ -25,13 +32,19 @@ class AlbumRowAdapter( onItemClick: (MusicDirectory.Entry) -> Unit, onContextMenuClick: (MenuItem, MusicDirectory.Entry) -> Boolean, private val imageLoader: ImageLoader, - onMusicFolderUpdate: (String?) -> Unit + onMusicFolderUpdate: (String?) -> Unit, + context: Context, ) : GenericRowAdapter( onItemClick, onContextMenuClick, onMusicFolderUpdate ) { + private val starDrawable: Drawable = + Util.getDrawableFromAttribute(context, R.attr.star_full) + private val starHollowDrawable: Drawable = + Util.getDrawableFromAttribute(context, R.attr.star_hollow) + override var itemList = albumList // Set our layout files @@ -53,6 +66,8 @@ class AlbumRowAdapter( holder.details.setOnClickListener { onItemClick(entry) } holder.details.setOnLongClickListener { view -> createPopupMenu(view, listPosition) } holder.coverArtId = entry.coverArt + holder.star.setImageDrawable(if (entry.starred) starDrawable else starHollowDrawable) + holder.star.setOnClickListener { onStarClick(entry, holder.star) } imageLoader.loadImage( holder.coverArt, entry, @@ -78,6 +93,7 @@ class AlbumRowAdapter( var artist: TextView = view.findViewById(R.id.album_artist) var details: LinearLayout = view.findViewById(R.id.row_album_details) var coverArt: ImageView = view.findViewById(R.id.album_coverart) + var star: ImageView = view.findViewById(R.id.album_star) var coverArtId: String? = null } @@ -87,4 +103,33 @@ class AlbumRowAdapter( override fun newViewHolder(view: View): RecyclerView.ViewHolder { return ViewHolder(view) } + + /** + * Handles the star / unstar action for an album + */ + private fun onStarClick(entry: MusicDirectory.Entry, star: ImageView) { + entry.starred = !entry.starred + star.setImageDrawable(if (entry.starred) starDrawable else starHollowDrawable) + val musicService = getMusicService() + Thread { + val useId3 = shouldUseId3Tags + try { + if (entry.starred) { + musicService.star( + if (!useId3) entry.id else null, + if (useId3) entry.id else null, + null + ) + } else { + musicService.unstar( + if (!useId3) entry.id else null, + if (useId3) entry.id else null, + null + ) + } + } catch (all: Exception) { + Timber.e(all) + } + }.start() + } } diff --git a/ultrasonic/src/main/res/layout/album_list_item.xml b/ultrasonic/src/main/res/layout/album_list_item.xml index 7959aa3d..5e66c129 100644 --- a/ultrasonic/src/main/res/layout/album_list_item.xml +++ b/ultrasonic/src/main/res/layout/album_list_item.xml @@ -36,14 +36,14 @@ a:paddingLeft="3dip" a:paddingRight="3dip" a:textAppearance="?android:attr/textAppearanceMedium" - app:layout_constraintEnd_toStartOf="@+id/guideline2" + app:layout_constraintEnd_toStartOf="@+id/album_star" app:layout_constraintLeft_toRightOf="@+id/album_coverart" app:layout_constraintStart_toEndOf="@+id/album_coverart" app:layout_constraintTop_toTopOf="parent"> - - - - + tools:src="@drawable/ic_star_hollow_dark" />