Artist thumbnail now fall back to album thumbnail

This commit is contained in:
Kelvin K
2025-11-25 00:40:38 +01:00
parent 949294952f
commit 5b40da109b
4 changed files with 65 additions and 5 deletions
@@ -14,6 +14,7 @@ import android.widget.ImageView
import android.widget.LinearLayout import android.widget.LinearLayout
import android.widget.TextView import android.widget.TextView
import androidx.appcompat.widget.AppCompatImageView import androidx.appcompat.widget.AppCompatImageView
import androidx.core.view.isVisible
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager import androidx.fragment.app.FragmentManager
import androidx.lifecycle.Lifecycle import androidx.lifecycle.Lifecycle
@@ -22,6 +23,7 @@ import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import androidx.viewpager2.adapter.FragmentStateAdapter import androidx.viewpager2.adapter.FragmentStateAdapter
import androidx.viewpager2.widget.ViewPager2 import androidx.viewpager2.widget.ViewPager2
import com.bumptech.glide.Glide
import com.futo.platformplayer.R import com.futo.platformplayer.R
import com.futo.platformplayer.UIDialogs import com.futo.platformplayer.UIDialogs
import com.futo.platformplayer.UISlideOverlays import com.futo.platformplayer.UISlideOverlays
@@ -359,7 +361,21 @@ class LibraryArtistFragment : MainFragment() {
(_viewPager.adapter as ArtistViewPagerAdapter).artist = channel (_viewPager.adapter as ArtistViewPagerAdapter).artist = channel
_viewPager.adapter!!.notifyDataSetChanged() _viewPager.adapter!!.notifyDataSetChanged();
val artistThumbnail = channel.getThumbnailOrAlbum();
if(artistThumbnail != null) {
_creatorThumbnail.isVisible = true;
_creatorThumbnail.setThumbnail(channel.getThumbnailOrAlbum(), true, true);
Glide.with(_imageBanner)
.load(artistThumbnail)
.into(_imageBanner);
}
else {
_creatorThumbnail.isVisible = false;
Glide.with(_imageBanner).clear(_imageBanner);
}
this.channel = channel this.channel = channel
} }
@@ -37,6 +37,8 @@ import java.io.File
import java.time.Instant import java.time.Instant
import java.time.OffsetDateTime import java.time.OffsetDateTime
import java.time.ZoneOffset import java.time.ZoneOffset
import java.util.concurrent.ConcurrentHashMap
import java.util.concurrent.ConcurrentMap
class StateLibrary { class StateLibrary {
@@ -488,6 +490,10 @@ class Artist {
return AdhocPager({ listOf() }, getTracksPager(idLong)); return AdhocPager({ listOf() }, getTracksPager(idLong));
} }
fun getThumbnailOrAlbum(): String? {
return thumbnail ?: tryGetArtistThumbnail(id.toLongOrNull());
}
companion object { companion object {
val ID_UNKNOWN = "UNKNOWN"; val ID_UNKNOWN = "UNKNOWN";
val PROJECTION: Array<String> = arrayOf(Artists._ID, val PROJECTION: Array<String> = arrayOf(Artists._ID,
@@ -495,6 +501,20 @@ class Artist {
Artists.NUMBER_OF_TRACKS, Artists.NUMBER_OF_TRACKS,
Artists.NUMBER_OF_ALBUMS); Artists.NUMBER_OF_ALBUMS);
val thumbnailCache = ConcurrentHashMap<Long, String>();
fun tryGetArtistThumbnail(artistId: Long?): String? {
if(artistId == null)
return null;
if(thumbnailCache.containsKey(artistId))
return thumbnailCache.get(artistId);
else {
val album = Album.getArtistAlbumWithThumbnail(artistId);
thumbnailCache.put(artistId, album?.thumbnail ?: "");
return album?.thumbnail;
}
}
fun fromCursor(cursor: Cursor): Artist { fun fromCursor(cursor: Cursor): Artist {
val id = cursor.getString(0); val id = cursor.getString(0);
val artist = cursor.getString(1); val artist = cursor.getString(1);
@@ -540,8 +560,11 @@ class Artist {
cursor.moveToFirst(); cursor.moveToFirst();
val list = mutableListOf<Artist>() val list = mutableListOf<Artist>()
while(!cursor.isAfterLast) { while(!cursor.isAfterLast) {
list.add(fromCursor(cursor)); val artist = fromCursor(cursor);
cursor.moveToNext(); cursor.moveToNext();
if(artist.name == "<unknown>")
continue; //TODO: Better way of detecting unknown?
list.add(artist);
} }
return@use list; return@use list;
} }
@@ -685,6 +708,26 @@ class Album {
return@use list; return@use list;
} }
} }
fun getArtistAlbumWithThumbnail(artistId: Long): Album? {
val resolver = StateApp.instance.contextOrNull?.contentResolver;
if(resolver == null) {
Logger.w(TAG, "Album contentResolver not found");
return null;
}
val cursor = resolver?.query(
MediaStore.Audio.Albums.EXTERNAL_CONTENT_URI, PROJECTION, "${MediaStore.Audio.Media.ARTIST_ID} = ?", arrayOf(artistId.toString()),
MediaStore.Audio.Albums.ALBUM + " ASC") ?: return null;
return cursor.use {
cursor.moveToFirst();
while(!cursor.isAfterLast) {
val album = fromCursor(cursor);
if(album.thumbnail != null)
return album
cursor.moveToNext();
}
return@use null;
}
}
} }
} }
@@ -37,9 +37,10 @@ class ArtistTileViewHolder(val _viewGroup: ViewGroup) : AnyAdapter.AnyViewHolder
override fun bind(artist: Artist) { override fun bind(artist: Artist) {
_artist = artist; _artist = artist;
_imageThumbnail?.let { _imageThumbnail?.let {
if (artist.thumbnail != null) val thumbnail = artist.getThumbnailOrAlbum();
if (thumbnail != null)
Glide.with(it) Glide.with(it)
.load(artist.thumbnail) .load(thumbnail)
.placeholder(R.drawable.ic_artist) .placeholder(R.drawable.ic_artist)
.into(it) .into(it)
else else
+1 -1
View File
@@ -60,7 +60,7 @@
<com.futo.platformplayer.views.others.CreatorThumbnail <com.futo.platformplayer.views.others.CreatorThumbnail
android:id="@+id/creator_thumbnail" android:id="@+id/creator_thumbnail"
android:background="@drawable/rounded_outline" android:background="@drawable/rounded_outline"
android:layout_width="1dp" android:layout_width="35dp"
android:layout_height="35dp" android:layout_height="35dp"
android:contentDescription="@string/cd_creator_thumbnail" android:contentDescription="@string/cd_creator_thumbnail"
android:layout_marginStart="8dp" android:layout_marginStart="8dp"