From e81c5aad316b7b2ec8e5e0f3a242f88ccb04ce74 Mon Sep 17 00:00:00 2001 From: chr56 Date: Thu, 6 Jun 2024 14:25:55 +0800 Subject: [PATCH 1/8] [layout] opt-out `emojiCompatEnabled` for TextView in list --- app/src/main/res/layout/item_grid.xml | 7 +++++-- .../main/res/layout/item_grid_card_horizontal.xml | 6 ++++-- app/src/main/res/layout/item_list.xml | 9 ++++++--- app/src/main/res/layout/item_list_3l.xml | 12 ++++++++---- app/src/main/res/layout/item_list_3l_extended.xml | 10 +++++++--- app/src/main/res/layout/item_list_3l_no_image.xml | 4 +++- app/src/main/res/layout/item_list_extended.xml | 5 ++++- app/src/main/res/layout/item_list_no_image.xml | 6 ++++-- app/src/main/res/layout/item_list_single_row.xml | 7 +++++-- 9 files changed, 46 insertions(+), 20 deletions(-) diff --git a/app/src/main/res/layout/item_grid.xml b/app/src/main/res/layout/item_grid.xml index 9b62c80e4..c08df4c7f 100644 --- a/app/src/main/res/layout/item_grid.xml +++ b/app/src/main/res/layout/item_grid.xml @@ -1,5 +1,6 @@ + android:textAppearance="@style/TextAppearance.AppCompat.Subhead" + app:emojiCompatEnabled="false" /> + android:textAppearance="@style/TextAppearance.AppCompat.Caption" + app:emojiCompatEnabled="false" /> diff --git a/app/src/main/res/layout/item_grid_card_horizontal.xml b/app/src/main/res/layout/item_grid_card_horizontal.xml index 8b561874c..823aa86d3 100644 --- a/app/src/main/res/layout/item_grid_card_horizontal.xml +++ b/app/src/main/res/layout/item_grid_card_horizontal.xml @@ -38,7 +38,8 @@ android:layout_height="wrap_content" android:singleLine="true" android:textAppearance="@style/TextAppearance.AppCompat.Subhead" - android:textSize="14sp" /> + android:textSize="14sp" + app:emojiCompatEnabled="false" /> + android:textSize="12sp" + app:emojiCompatEnabled="false" /> diff --git a/app/src/main/res/layout/item_list.xml b/app/src/main/res/layout/item_list.xml index 66ce022a6..3c9ac4ef3 100644 --- a/app/src/main/res/layout/item_list.xml +++ b/app/src/main/res/layout/item_list.xml @@ -52,7 +52,8 @@ android:minHeight="40dp" android:singleLine="true" android:textAppearance="@style/TextAppearance.AppCompat.Subhead" - android:visibility="gone" /> + android:visibility="gone" + app:emojiCompatEnabled="false" /> @@ -73,7 +74,8 @@ android:layout_height="wrap_content" android:fontFamily="sans-serif" android:singleLine="true" - android:textAppearance="@style/TextAppearance.AppCompat.Subhead" /> + android:textAppearance="@style/TextAppearance.AppCompat.Subhead" + app:emojiCompatEnabled="false" /> + android:textColor="?android:textColorSecondary" + app:emojiCompatEnabled="false" /> + android:visibility="gone" + app:emojiCompatEnabled="false" /> @@ -68,7 +69,8 @@ android:layout_height="wrap_content" android:fontFamily="sans-serif" android:singleLine="true" - android:textAppearance="@style/TextAppearance.AppCompat.Subhead" /> + android:textAppearance="@style/TextAppearance.AppCompat.Subhead" + app:emojiCompatEnabled="false" /> + android:textColor="?android:textColorSecondary" + app:emojiCompatEnabled="false" /> + android:textColor="?android:textColorSecondary" + app:emojiCompatEnabled="false" /> diff --git a/app/src/main/res/layout/item_list_3l_extended.xml b/app/src/main/res/layout/item_list_3l_extended.xml index 4fcd35e95..10d48e33d 100644 --- a/app/src/main/res/layout/item_list_3l_extended.xml +++ b/app/src/main/res/layout/item_list_3l_extended.xml @@ -49,7 +49,8 @@ android:minHeight="40dp" android:singleLine="true" android:textAppearance="@style/TextAppearance.AppCompat.Subhead" - android:visibility="gone" /> + android:visibility="gone" + app:emojiCompatEnabled="false" /> @@ -71,6 +72,7 @@ android:maxLines="3" android:singleLine="false" android:textAppearance="@style/TextAppearance.AppCompat.Subhead" + app:emojiCompatEnabled="false" tools:text="TITLE" /> + android:textColor="?android:textColorSecondary" + app:emojiCompatEnabled="false" /> + android:textColor="?android:textColorSecondary" + app:emojiCompatEnabled="false" /> + android:textColor="?android:textColorSecondary" + app:emojiCompatEnabled="false" /> + android:visibility="gone" + app:emojiCompatEnabled="false" /> @@ -71,6 +72,7 @@ android:maxLines="3" android:singleLine="false" android:textAppearance="@style/TextAppearance.AppCompat.Subhead" + app:emojiCompatEnabled="false" tools:text="TITLE" /> diff --git a/app/src/main/res/layout/item_list_no_image.xml b/app/src/main/res/layout/item_list_no_image.xml index a52be46da..33a3558d5 100644 --- a/app/src/main/res/layout/item_list_no_image.xml +++ b/app/src/main/res/layout/item_list_no_image.xml @@ -43,7 +43,8 @@ android:layout_height="wrap_content" android:fontFamily="sans-serif" android:singleLine="true" - android:textAppearance="@style/TextAppearance.AppCompat.Subhead" /> + android:textAppearance="@style/TextAppearance.AppCompat.Subhead" + app:emojiCompatEnabled="false" /> + android:textColor="?android:textColorSecondary" + app:emojiCompatEnabled="false" /> + android:visibility="gone" + app:emojiCompatEnabled="false" /> @@ -66,7 +68,8 @@ android:layout_weight="1" android:fontFamily="sans-serif" android:singleLine="true" - android:textAppearance="@style/TextAppearance.AppCompat.Subhead" /> + android:textAppearance="@style/TextAppearance.AppCompat.Subhead" + app:emojiCompatEnabled="false" /> Date: Thu, 6 Jun 2024 14:43:40 +0800 Subject: [PATCH 2/8] [model-strings] do not use plurals string for `songCountString` for better performance --- app/src/main/java/player/phonograph/model/Extensions.kt | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/player/phonograph/model/Extensions.kt b/app/src/main/java/player/phonograph/model/Extensions.kt index 3d13a7449..40e8aeabc 100644 --- a/app/src/main/java/player/phonograph/model/Extensions.kt +++ b/app/src/main/java/player/phonograph/model/Extensions.kt @@ -12,8 +12,11 @@ import player.phonograph.R fun Song.infoString(): String = buildInfoString(artistName, albumName) -fun songCountString(context: Context, songCount: Int): String = - context.resources.getQuantityString(R.plurals.item_songs, songCount, songCount) +fun songCountString(context: Context, songCount: Int): String { + val songString = + if (songCount == 1) context.resources.getString(R.string.song) else context.resources.getString(R.string.songs) + return "$songCount $songString" +} fun Artist.infoString(context: Context): String = buildInfoString( From b3e0c3e8656c6cf3513f1b89f1f9d615686db3ce Mon Sep 17 00:00:00 2001 From: chr56 Date: Thu, 6 Jun 2024 14:46:19 +0800 Subject: [PATCH 3/8] [model-strings] cleanup --- .../player/phonograph/model/Extensions.kt | 33 +++++++------------ 1 file changed, 12 insertions(+), 21 deletions(-) diff --git a/app/src/main/java/player/phonograph/model/Extensions.kt b/app/src/main/java/player/phonograph/model/Extensions.kt index 40e8aeabc..842ba7643 100644 --- a/app/src/main/java/player/phonograph/model/Extensions.kt +++ b/app/src/main/java/player/phonograph/model/Extensions.kt @@ -9,36 +9,27 @@ import android.content.Context import java.util.* import player.phonograph.R -fun Song.infoString(): String = - buildInfoString(artistName, albumName) - fun songCountString(context: Context, songCount: Int): String { val songString = if (songCount == 1) context.resources.getString(R.string.song) else context.resources.getString(R.string.songs) return "$songCount $songString" } +fun albumCountString(context: Context, albumCount: Int): String { + val albumString = + if (albumCount == 1) context.resources.getString(R.string.album) else context.resources.getString(R.string.albums) + return "$albumCount $albumString" +} + +fun Song.infoString(): String = + buildInfoString(artistName, albumName) + fun Artist.infoString(context: Context): String = buildInfoString( albumCountString(context, albumCount), songCountString(context, songCount) ) -fun isArtistNameUnknown(artistName: String?): Boolean = when { - artistName.isNullOrBlank() -> false // not certain - artistName == Artist.UNKNOWN_ARTIST_DISPLAY_NAME -> true - artistName.trim().lowercase() == "unknown" -> true - artistName.trim().lowercase() == "" -> true - else -> false -} - -fun albumCountString(context: Context, albumCount: Int): String { - val albumString = if (albumCount == 1) context.resources.getString(R.string.album) else context.resources.getString( - R.string.albums - ) - return "$albumCount $albumString" -} - fun Album.infoString(context: Context): String = buildInfoString( artistName, @@ -56,10 +47,10 @@ fun Genre.infoString(context: Context): String = */ fun buildInfoString(string1: String?, string2: String?): String = when { - string1.isNullOrEmpty() && !string2.isNullOrEmpty() -> string2 - !string1.isNullOrEmpty() && string2.isNullOrEmpty() -> string1 + string1.isNullOrEmpty() && !string2.isNullOrEmpty() -> string2 + !string1.isNullOrEmpty() && string2.isNullOrEmpty() -> string1 !string1.isNullOrEmpty() && !string2.isNullOrEmpty() -> "$string1 • $string2" - else -> "" + else -> "" } fun getReadableDurationString(songDurationMillis: Long): String { From d94ca0e0b6e405dcbec7dbb6c4c10ec17cae33f8 Mon Sep 17 00:00:00 2001 From: chr56 Date: Thu, 6 Jun 2024 12:54:19 +0800 Subject: [PATCH 4/8] [coil] do not fetching images in Mapping --- .../player/phonograph/coil/album/AlbumImageMapper.kt | 10 ++-------- .../phonograph/coil/artist/ArtistImageMapper.kt | 11 ++--------- .../java/player/phonograph/coil/model/AlbumImage.kt | 9 ++++++--- .../java/player/phonograph/coil/model/ArtistImage.kt | 9 ++++++--- .../phonograph/coil/model/CompositeLoaderTarget.kt | 4 +++- .../phonograph/coil/retriever/FetcherDelegate.kt | 12 +++++------- 6 files changed, 24 insertions(+), 31 deletions(-) diff --git a/app/src/main/java/player/phonograph/coil/album/AlbumImageMapper.kt b/app/src/main/java/player/phonograph/coil/album/AlbumImageMapper.kt index 1ffef177e..d90e2da8e 100644 --- a/app/src/main/java/player/phonograph/coil/album/AlbumImageMapper.kt +++ b/app/src/main/java/player/phonograph/coil/album/AlbumImageMapper.kt @@ -2,16 +2,10 @@ package player.phonograph.coil.album import coil.map.Mapper import coil.request.Options -import player.phonograph.coil.model.SongImage import player.phonograph.coil.model.AlbumImage import player.phonograph.model.Album -import player.phonograph.repo.loader.Songs -import kotlinx.coroutines.runBlocking class AlbumImageMapper : Mapper { - override fun map(data: Album, options: Options): AlbumImage? = AlbumImage( - data.id, - data.title, - runBlocking{ Songs.album(options.context, data.id).map { SongImage.from(it) } } - ).takeIf { it.files.isNotEmpty() } + override fun map(data: Album, options: Options): AlbumImage = + AlbumImage(data.id, data.title) } \ No newline at end of file diff --git a/app/src/main/java/player/phonograph/coil/artist/ArtistImageMapper.kt b/app/src/main/java/player/phonograph/coil/artist/ArtistImageMapper.kt index fa6060699..a75aca169 100644 --- a/app/src/main/java/player/phonograph/coil/artist/ArtistImageMapper.kt +++ b/app/src/main/java/player/phonograph/coil/artist/ArtistImageMapper.kt @@ -7,16 +7,9 @@ package player.phonograph.coil.artist import coil.map.Mapper import coil.request.Options import player.phonograph.coil.model.ArtistImage -import player.phonograph.coil.model.SongImage import player.phonograph.model.Artist -import player.phonograph.repo.loader.Songs -import kotlinx.coroutines.runBlocking class ArtistImageMapper : Mapper { - override fun map(data: Artist, options: Options): ArtistImage? = - ArtistImage( - data.id, - data.name, - runBlocking { Songs.artist(options.context, data.id).map { SongImage.from(it) } } - ).takeIf { it.files.isNotEmpty() } + override fun map(data: Artist, options: Options): ArtistImage = + ArtistImage(data.id, data.name) } diff --git a/app/src/main/java/player/phonograph/coil/model/AlbumImage.kt b/app/src/main/java/player/phonograph/coil/model/AlbumImage.kt index 8225e64ec..e80b87bad 100644 --- a/app/src/main/java/player/phonograph/coil/model/AlbumImage.kt +++ b/app/src/main/java/player/phonograph/coil/model/AlbumImage.kt @@ -4,14 +4,17 @@ package player.phonograph.coil.model +import player.phonograph.repo.loader.Songs +import android.content.Context + data class AlbumImage( override val id: Long, val name: String, - val files: List, ) : CompositeLoaderTarget { - override fun disassemble(): Iterable = files + override suspend fun items(context: Context): Iterable = + Songs.album(context, id).map { SongImage.from(it) } override fun toString(): String = - "AlbumImage(name=$name, id=$id, files=${files.joinToString(prefix = "[", postfix = "]") { it.path }})" + "AlbumImage(name=$name, id=$id,)" } \ No newline at end of file diff --git a/app/src/main/java/player/phonograph/coil/model/ArtistImage.kt b/app/src/main/java/player/phonograph/coil/model/ArtistImage.kt index 32e38e12c..18a95f764 100644 --- a/app/src/main/java/player/phonograph/coil/model/ArtistImage.kt +++ b/app/src/main/java/player/phonograph/coil/model/ArtistImage.kt @@ -4,14 +4,17 @@ package player.phonograph.coil.model +import player.phonograph.repo.loader.Songs +import android.content.Context + data class ArtistImage( override val id: Long, val name: String, - val files: List, ) : CompositeLoaderTarget { - override fun disassemble(): Iterable = files + override suspend fun items(context: Context): Iterable = + Songs.artist(context, id).map { SongImage.from(it) } override fun toString(): String = - "ArtistImage(name=$name, id=$id, files=${files.joinToString(prefix = "[", postfix = "]") { it.path }})" + "ArtistImage(name=$name, id=$id,)" } diff --git a/app/src/main/java/player/phonograph/coil/model/CompositeLoaderTarget.kt b/app/src/main/java/player/phonograph/coil/model/CompositeLoaderTarget.kt index 8984499ea..9e4eb5530 100644 --- a/app/src/main/java/player/phonograph/coil/model/CompositeLoaderTarget.kt +++ b/app/src/main/java/player/phonograph/coil/model/CompositeLoaderTarget.kt @@ -4,6 +4,8 @@ package player.phonograph.coil.model +import android.content.Context + interface CompositeLoaderTarget : LoaderTarget { - fun disassemble(): Iterable + suspend fun items(context: Context): Iterable } \ No newline at end of file diff --git a/app/src/main/java/player/phonograph/coil/retriever/FetcherDelegate.kt b/app/src/main/java/player/phonograph/coil/retriever/FetcherDelegate.kt index 13a3e564c..12d97f8c7 100644 --- a/app/src/main/java/player/phonograph/coil/retriever/FetcherDelegate.kt +++ b/app/src/main/java/player/phonograph/coil/retriever/FetcherDelegate.kt @@ -12,8 +12,6 @@ import player.phonograph.coil.model.CompositeLoaderTarget import player.phonograph.coil.model.LoaderTarget import player.phonograph.coil.model.SongImage import player.phonograph.mechanism.setting.CoilImageConfig -import player.phonograph.settings.Keys -import player.phonograph.settings.Setting import player.phonograph.util.debug import android.content.Context import android.util.Log @@ -31,7 +29,7 @@ sealed class FetcherDelegate { abstract val cacheStore: CacheStore.Cache - fun retrieve( + suspend fun retrieve( target: T, context: Context, size: Size, @@ -75,7 +73,7 @@ sealed class FetcherDelegate { } } - abstract fun retrieveImpl( + abstract suspend fun retrieveImpl( target: T, context: Context, size: Size, @@ -95,7 +93,7 @@ class AudioFileImageFetcherDelegate( override val cacheStore: CacheStore.Cache = CacheStore.AudioFiles(context.applicationContext) - override fun retrieveImpl(target: SongImage, context: Context, size: Size, rawImage: Boolean): FetchResult? { + override suspend fun retrieveImpl(target: SongImage, context: Context, size: Size, rawImage: Boolean): FetchResult? { return retriever.retrieve(target.path, target.albumId, context, size, rawImage) } } @@ -104,7 +102,7 @@ sealed class CompositeFetcherDelegate, R : override val retriever: R, ) : FetcherDelegate() { - override fun retrieveImpl(target: T, context: Context, size: Size, rawImage: Boolean): FetchResult? { + override suspend fun retrieveImpl(target: T, context: Context, size: Size, rawImage: Boolean): FetchResult? { if (enableCache(context)) { val noImage = cacheStore.isNoImage(target, retriever.id) @@ -118,7 +116,7 @@ sealed class CompositeFetcherDelegate, R : val audioFilesCache = CacheStore.AudioFiles(context.applicationContext) - for (file in target.disassemble()) { + for (file in target.items(context)) { if (enableCache(context)) { val noSpecificImage = audioFilesCache.isNoImage(file, retriever.id) From f0d72a10f2c65447ba52cc7fcb0250e73b3d3183 Mon Sep 17 00:00:00 2001 From: chr56 Date: Sat, 1 Jun 2024 16:02:55 +0800 Subject: [PATCH 5/8] [PreloadImageCache] add `peek` --- app/src/main/java/player/phonograph/coil/PreloadImageCache.kt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/src/main/java/player/phonograph/coil/PreloadImageCache.kt b/app/src/main/java/player/phonograph/coil/PreloadImageCache.kt index a6b2f9739..282e0918c 100644 --- a/app/src/main/java/player/phonograph/coil/PreloadImageCache.kt +++ b/app/src/main/java/player/phonograph/coil/PreloadImageCache.kt @@ -39,6 +39,8 @@ abstract class AbsPreloadImageCache(size: Int, @CacheImplementation } } + fun peek(context: Context, key: K): G? = cache[id(key)] + suspend fun preload(context: Context, key: K) { loadAndStore(context, key) } From 0705328cfbb1eab8ad03906a118ddd206ae27190 Mon Sep 17 00:00:00 2001 From: chr56 Date: Thu, 6 Jun 2024 15:20:30 +0800 Subject: [PATCH 6/8] [DisplayAdapter] disable preload temporarily --- .../phonograph/ui/adapter/DisplayAdapter.kt | 52 ++++++++++++++----- 1 file changed, 39 insertions(+), 13 deletions(-) diff --git a/app/src/main/java/player/phonograph/ui/adapter/DisplayAdapter.kt b/app/src/main/java/player/phonograph/ui/adapter/DisplayAdapter.kt index 597f845c4..7216f3924 100644 --- a/app/src/main/java/player/phonograph/ui/adapter/DisplayAdapter.kt +++ b/app/src/main/java/player/phonograph/ui/adapter/DisplayAdapter.kt @@ -33,7 +33,6 @@ import android.graphics.drawable.BitmapDrawable import android.graphics.drawable.Drawable import android.os.Build.VERSION.SDK_INT import android.os.Build.VERSION_CODES.Q -import android.util.Log import android.view.LayoutInflater import android.view.View import android.view.ViewGroup @@ -57,7 +56,7 @@ abstract class DisplayAdapter( @SuppressLint("NotifyDataSetChanged") set(value) { field = value - if (config.layoutStyle.hasImage) imageCacheDelegate.preloadImages(activity, value) + // if (config.layoutStyle.hasImage) imageCacheDelegate.preloadImages(activity, value) notifyDataSetChanged() } @@ -92,13 +91,13 @@ abstract class DisplayAdapter( override fun getSectionName(position: Int): String = if (config.showSectionName) getSectionNameImp(position) else "" - override fun onViewAttachedToWindow(holder: DisplayViewHolder) { - if (holder.bindingAdapterPosition in dataset.indices) { - imageCacheDelegate.updateImage(activity, holder, dataset[holder.bindingAdapterPosition], config.usePalette) - } else{ - Log.v("ImageCacheDelegate", "Holder has already detached?") - } - } + // override fun onViewAttachedToWindow(holder: DisplayViewHolder) { + // if (holder.bindingAdapterPosition in dataset.indices) { + // imageCacheDelegate.updateImage(activity, holder, dataset[holder.bindingAdapterPosition], config.usePalette) + // } else{ + // Log.v("ImageCacheDelegate", "Holder has already detached?") + // } + // } // override fun onViewDetachedFromWindow(holder: DisplayViewHolder) {} @@ -123,7 +122,7 @@ abstract class DisplayAdapter( textSecondary?.text = item.getSecondaryText(itemView.context) textTertiary?.text = item.getTertiaryText(itemView.context) - prepareImage(imageType, item) + prepareImage(imageType, item, usePalette) controller.registerClicking(itemView, position) { onClick(position, dataset, image) @@ -160,7 +159,7 @@ abstract class DisplayAdapter( protected open fun getDescription(item: I): CharSequence? = item.getDescription(context = itemView.context) - protected open fun prepareImage(@ImageType imageType: Int, item: I) { + protected open fun prepareImage(@ImageType imageType: Int, item: I, usePalette: Boolean) { when (imageType) { IMAGE_TYPE_FIXED_ICON -> { image?.visibility = View.VISIBLE @@ -169,8 +168,7 @@ abstract class DisplayAdapter( IMAGE_TYPE_IMAGE -> { image?.visibility = View.VISIBLE - image?.setImageDrawable(defaultIcon) - setPaletteColors(themeFooterColor(itemView.context)) + image?.let { imageView -> fetchImage(item, imageView, usePalette) } } IMAGE_TYPE_TEXT -> { @@ -180,6 +178,30 @@ abstract class DisplayAdapter( } } + protected open fun fetchImage(item: I, imageView: ImageView, usePalette: Boolean) { + val context = imageView.context + coroutineScope.launch { + loadImage(context) + .from(item) + .into( + PaletteTargetBuilder() + .defaultColor(themeFooterColor(context)) + .view(imageView) + .onStart { + imageView.setImageDrawable(defaultIcon) + if (usePalette) setPaletteColors(themeFooterColor(itemView.context)) + } + .onResourceReady { result, paletteColor -> + imageView.setImageDrawable(result) + if (usePalette) setPaletteColors(paletteColor) + } + .build() + ) + .enqueue() + } + } + + protected open fun getIcon(item: I): Drawable? = defaultIcon protected open fun setImageText(text: String) { @@ -199,6 +221,10 @@ abstract class DisplayAdapter( textTertiary?.setTextColor(context.secondaryTextColor(color)) } } + + companion object { + val coroutineScope = CoroutineScope(SupervisorJob() + Dispatchers.IO) + } } class ImageCacheDelegate(val config: DisplayConfig) { From 26e393ee2cd7c183f10a88aeb56c4678a11aeb98 Mon Sep 17 00:00:00 2001 From: chr56 Date: Thu, 6 Jun 2024 15:35:57 +0800 Subject: [PATCH 7/8] [DisplayAdapter] new preload mechanism --- .../phonograph/ui/adapter/DisplayAdapter.kt | 93 +++++++++---------- 1 file changed, 44 insertions(+), 49 deletions(-) diff --git a/app/src/main/java/player/phonograph/ui/adapter/DisplayAdapter.kt b/app/src/main/java/player/phonograph/ui/adapter/DisplayAdapter.kt index 7216f3924..76c41e277 100644 --- a/app/src/main/java/player/phonograph/ui/adapter/DisplayAdapter.kt +++ b/app/src/main/java/player/phonograph/ui/adapter/DisplayAdapter.kt @@ -43,7 +43,6 @@ import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.launch import kotlinx.coroutines.suspendCancellableCoroutine -import kotlinx.coroutines.withContext abstract class DisplayAdapter( protected val activity: FragmentActivity, @@ -56,7 +55,7 @@ abstract class DisplayAdapter( @SuppressLint("NotifyDataSetChanged") set(value) { field = value - // if (config.layoutStyle.hasImage) imageCacheDelegate.preloadImages(activity, value) + if (config.layoutStyle.hasImage) imageCacheDelegate.startPreloadImages(activity, value) notifyDataSetChanged() } @@ -83,7 +82,7 @@ abstract class DisplayAdapter( override fun onBindViewHolder(holder: DisplayViewHolder, position: Int) { val item: I = dataset[position] - holder.bind(item, position, dataset, controller, config.imageType, config.usePalette) + holder.bind(item, position, dataset, controller, config.imageType, config.usePalette, imageCacheDelegate) } override fun getItemCount(): Int = dataset.size @@ -91,16 +90,6 @@ abstract class DisplayAdapter( override fun getSectionName(position: Int): String = if (config.showSectionName) getSectionNameImp(position) else "" - // override fun onViewAttachedToWindow(holder: DisplayViewHolder) { - // if (holder.bindingAdapterPosition in dataset.indices) { - // imageCacheDelegate.updateImage(activity, holder, dataset[holder.bindingAdapterPosition], config.usePalette) - // } else{ - // Log.v("ImageCacheDelegate", "Holder has already detached?") - // } - // } - - // override fun onViewDetachedFromWindow(holder: DisplayViewHolder) {} - // for inheriting open fun getSectionNameImp(position: Int): String = dataset[position].defaultSortOrderReference()?.substring(0..1) ?: "" @@ -114,6 +103,7 @@ abstract class DisplayAdapter( controller: MultiSelectionController, @ImageType imageType: Int, usePalette: Boolean, + imageCacheDelegate: ImageCacheDelegate, ) { shortSeparator?.visibility = View.VISIBLE itemView.isActivated = controller.isSelected(item) @@ -122,7 +112,7 @@ abstract class DisplayAdapter( textSecondary?.text = item.getSecondaryText(itemView.context) textTertiary?.text = item.getTertiaryText(itemView.context) - prepareImage(imageType, item, usePalette) + prepareImage(imageType, item, usePalette, imageCacheDelegate) controller.registerClicking(itemView, position) { onClick(position, dataset, image) @@ -159,7 +149,12 @@ abstract class DisplayAdapter( protected open fun getDescription(item: I): CharSequence? = item.getDescription(context = itemView.context) - protected open fun prepareImage(@ImageType imageType: Int, item: I, usePalette: Boolean) { + protected open fun prepareImage( + @ImageType imageType: Int, + item: I, + usePalette: Boolean, + imageCacheDelegate: ImageCacheDelegate, + ) { when (imageType) { IMAGE_TYPE_FIXED_ICON -> { image?.visibility = View.VISIBLE @@ -168,7 +163,7 @@ abstract class DisplayAdapter( IMAGE_TYPE_IMAGE -> { image?.visibility = View.VISIBLE - image?.let { imageView -> fetchImage(item, imageView, usePalette) } + image?.let { imageView -> fetchImage(item, imageView, usePalette, imageCacheDelegate) } } IMAGE_TYPE_TEXT -> { @@ -178,26 +173,37 @@ abstract class DisplayAdapter( } } - protected open fun fetchImage(item: I, imageView: ImageView, usePalette: Boolean) { + protected open fun fetchImage( + item: I, + imageView: ImageView, + usePalette: Boolean, + imageCacheDelegate: ImageCacheDelegate, + ) { val context = imageView.context - coroutineScope.launch { - loadImage(context) - .from(item) - .into( - PaletteTargetBuilder() - .defaultColor(themeFooterColor(context)) - .view(imageView) - .onStart { - imageView.setImageDrawable(defaultIcon) - if (usePalette) setPaletteColors(themeFooterColor(itemView.context)) - } - .onResourceReady { result, paletteColor -> - imageView.setImageDrawable(result) - if (usePalette) setPaletteColors(paletteColor) - } - .build() - ) - .enqueue() + val cached = imageCacheDelegate.peek(context, item) + if (cached != null) { + imageView.setImageBitmap(cached.bitmap) + if (usePalette) setPaletteColors(cached.paletteColor) + } else { + coroutineScope.launch { + loadImage(context) + .from(item) + .into( + PaletteTargetBuilder() + .defaultColor(themeFooterColor(context)) + .view(imageView) + .onStart { + imageView.setImageDrawable(defaultIcon) + if (usePalette) setPaletteColors(themeFooterColor(itemView.context)) + } + .onResourceReady { result, paletteColor -> + imageView.setImageDrawable(result) + if (usePalette) setPaletteColors(paletteColor) + } + .build() + ) + .enqueue() + } } } @@ -241,8 +247,8 @@ abstract class DisplayAdapter( _imageCache = value } - fun preloadImages(context: Context, items: Collection) { - if (config.imageType != IMAGE_TYPE_IMAGE && enabledPreload) return + fun startPreloadImages(context: Context, items: Collection) { + if (!enabledPreload || config.imageType != IMAGE_TYPE_IMAGE) return imageCache = DisplayPreloadImageCache(items.size.coerceAtLeast(1)) imageCache.imageLoaderScope.launch { @@ -252,18 +258,7 @@ abstract class DisplayAdapter( } } - fun updateImage(context: Context, viewHolder: DisplayViewHolder, item: I, usePalette: Boolean) { - if (config.imageType != IMAGE_TYPE_IMAGE) return - - imageCache.imageLoaderScope.launch { - val loaded = - if (enabledPreload) imageCache.fetch(context, item) else imageCache.read(context, item) - withContext(Dispatchers.Main) { - viewHolder.image?.setImageBitmap(loaded.bitmap) - if (usePalette) viewHolder.setPaletteColors(loaded.paletteColor) - } - } - } + fun peek(context: Context, item: I): PaletteBitmap? = imageCache.peek(context, item) private val enabledPreload: Boolean = Setting(App.instance)[Keys.preloadImages].data } From f1bd088b1210c27bd8f979a903d90461a185ad9a Mon Sep 17 00:00:00 2001 From: chr56 Date: Thu, 6 Jun 2024 15:45:17 +0800 Subject: [PATCH 8/8] [DisplayAdapter] fix default footer color --- .../main/java/player/phonograph/ui/adapter/DisplayAdapter.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/player/phonograph/ui/adapter/DisplayAdapter.kt b/app/src/main/java/player/phonograph/ui/adapter/DisplayAdapter.kt index 76c41e277..a8930afcb 100644 --- a/app/src/main/java/player/phonograph/ui/adapter/DisplayAdapter.kt +++ b/app/src/main/java/player/phonograph/ui/adapter/DisplayAdapter.kt @@ -194,7 +194,7 @@ abstract class DisplayAdapter( .view(imageView) .onStart { imageView.setImageDrawable(defaultIcon) - if (usePalette) setPaletteColors(themeFooterColor(itemView.context)) + setPaletteColors(themeFooterColor(itemView.context)) } .onResourceReady { result, paletteColor -> imageView.setImageDrawable(result)