From 844b4edf48b81c46acc096677c283cde0b1bca48 Mon Sep 17 00:00:00 2001 From: Isira Seneviratne Date: Sat, 22 Jun 2024 08:32:06 +0530 Subject: [PATCH] Migrate to Coil from Picasso --- app/src/main/java/org/schabi/newpipe/App.java | 32 +++++-- .../fragments/detail/VideoDetailFragment.java | 27 +++--- .../list/channel/ChannelFragment.java | 15 ++- .../list/comments/CommentRepliesFragment.java | 4 +- .../list/playlist/PlaylistFragment.java | 5 +- .../newpipe/info_list/StreamSegmentItem.kt | 44 ++++----- .../holder/ChannelMiniInfoItemHolder.java | 4 +- .../holder/CommentInfoItemHolder.java | 8 +- .../holder/PlaylistMiniInfoItemHolder.java | 4 +- .../holder/StreamMiniInfoItemHolder.java | 4 +- .../newpipe/local/feed/item/StreamItem.kt | 4 +- .../local/holder/LocalPlaylistItemHolder.java | 7 +- .../holder/LocalPlaylistStreamItemHolder.java | 6 +- .../LocalStatisticStreamItemHolder.java | 6 +- .../holder/RemotePlaylistItemHolder.java | 7 +- .../local/subscription/item/ChannelItem.kt | 4 +- .../item/PickerSubscriptionItem.kt | 4 +- .../org/schabi/newpipe/player/Player.java | 6 +- .../playqueue/PlayQueueItemBuilder.java | 4 +- .../SeekbarPreviewThumbnailHolder.java | 7 +- .../settings/ContentSettingsFragment.java | 20 ++-- .../settings/SelectChannelFragment.java | 4 +- .../settings/SelectPlaylistFragment.java | 17 ++-- .../schabi/newpipe/util/image/CoilHelper.kt | 94 +++++++++++++++++++ .../newpipe/util/image/PicassoHelper.java | 62 +----------- 25 files changed, 226 insertions(+), 173 deletions(-) create mode 100644 app/src/main/java/org/schabi/newpipe/util/image/CoilHelper.kt diff --git a/app/src/main/java/org/schabi/newpipe/App.java b/app/src/main/java/org/schabi/newpipe/App.java index d92425d20..22ee3aa8b 100644 --- a/app/src/main/java/org/schabi/newpipe/App.java +++ b/app/src/main/java/org/schabi/newpipe/App.java @@ -20,10 +20,10 @@ import org.schabi.newpipe.extractor.downloader.Downloader; import org.schabi.newpipe.ktx.ExceptionUtils; import org.schabi.newpipe.settings.NewPipeSettings; import org.schabi.newpipe.util.Localization; -import org.schabi.newpipe.util.image.ImageStrategy; -import org.schabi.newpipe.util.image.PicassoHelper; import org.schabi.newpipe.util.ServiceHelper; import org.schabi.newpipe.util.StateSaver; +import org.schabi.newpipe.util.image.ImageStrategy; +import org.schabi.newpipe.util.image.PicassoHelper; import org.schabi.newpipe.util.image.PreferredImageQuality; import java.io.IOException; @@ -32,6 +32,11 @@ import java.net.SocketException; import java.util.List; import java.util.Objects; +import coil.ImageLoader; +import coil.ImageLoaderFactory; +import coil.disk.DiskCache; +import coil.memory.MemoryCache; +import coil.util.DebugLogger; import io.reactivex.rxjava3.exceptions.CompositeException; import io.reactivex.rxjava3.exceptions.MissingBackpressureException; import io.reactivex.rxjava3.exceptions.OnErrorNotImplementedException; @@ -57,7 +62,7 @@ import io.reactivex.rxjava3.plugins.RxJavaPlugins; * along with NewPipe. If not, see . */ -public class App extends Application { +public class App extends Application implements ImageLoaderFactory { public static final String PACKAGE_NAME = BuildConfig.APPLICATION_ID; private static final String TAG = App.class.toString(); @@ -118,10 +123,25 @@ public class App extends Application { configureRxJavaErrorHandler(); } + @NonNull @Override - public void onTerminate() { - super.onTerminate(); - PicassoHelper.terminate(); + public ImageLoader newImageLoader() { + final var builder = new ImageLoader.Builder(this) + .memoryCache(() -> new MemoryCache.Builder(this) + .maxSizeBytes(10 * 1024 * 1024) + .build()) + .diskCache(() -> new DiskCache.Builder() + .maxSizeBytes(50 * 1024 * 1024) + .build()) + .allowRgb565(true); + + final var prefs = PreferenceManager.getDefaultSharedPreferences(this); + if (MainActivity.DEBUG + && prefs.getBoolean(getString(R.string.show_image_indicators_key), false)) { + builder.logger(new DebugLogger()); + } + + return builder.build(); } protected Downloader getDownloader() { diff --git a/app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java index 95b54f65a..da4b071c3 100644 --- a/app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java +++ b/app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java @@ -116,7 +116,7 @@ import org.schabi.newpipe.util.StreamTypeUtil; import org.schabi.newpipe.util.ThemeHelper; import org.schabi.newpipe.util.external_communication.KoreUtils; import org.schabi.newpipe.util.external_communication.ShareUtils; -import org.schabi.newpipe.util.image.PicassoHelper; +import org.schabi.newpipe.util.image.CoilHelper; import java.util.ArrayList; import java.util.Iterator; @@ -127,6 +127,7 @@ import java.util.Optional; import java.util.concurrent.TimeUnit; import java.util.function.Consumer; +import coil.util.CoilUtils; import icepick.State; import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers; import io.reactivex.rxjava3.disposables.CompositeDisposable; @@ -1471,7 +1472,10 @@ public final class VideoDetailFragment } } - PicassoHelper.cancelTag(PICASSO_VIDEO_DETAILS_TAG); + CoilUtils.dispose(binding.detailThumbnailImageView); + CoilUtils.dispose(binding.detailSubChannelThumbnailView); + CoilUtils.dispose(binding.overlayThumbnail); + binding.detailThumbnailImageView.setImageBitmap(null); binding.detailSubChannelThumbnailView.setImageBitmap(null); } @@ -1562,8 +1566,8 @@ public final class VideoDetailFragment binding.detailSecondaryControlPanel.setVisibility(View.GONE); checkUpdateProgressInfo(info); - PicassoHelper.loadDetailsThumbnail(info.getThumbnails()).tag(PICASSO_VIDEO_DETAILS_TAG) - .into(binding.detailThumbnailImageView); + CoilHelper.INSTANCE.loadDetailsThumbnail(binding.detailThumbnailImageView, + info.getThumbnails()); showMetaInfoInTextView(info.getMetaInfo(), binding.detailMetaInfoTextView, binding.detailMetaInfoSeparator, disposables); @@ -1613,8 +1617,8 @@ public final class VideoDetailFragment binding.detailUploaderTextView.setVisibility(View.GONE); } - PicassoHelper.loadAvatar(info.getUploaderAvatars()).tag(PICASSO_VIDEO_DETAILS_TAG) - .into(binding.detailSubChannelThumbnailView); + CoilHelper.INSTANCE.loadAvatar(binding.detailSubChannelThumbnailView, + info.getUploaderAvatars()); binding.detailSubChannelThumbnailView.setVisibility(View.VISIBLE); binding.detailUploaderThumbnailView.setVisibility(View.GONE); } @@ -1645,11 +1649,11 @@ public final class VideoDetailFragment binding.detailUploaderTextView.setVisibility(View.GONE); } - PicassoHelper.loadAvatar(info.getSubChannelAvatars()).tag(PICASSO_VIDEO_DETAILS_TAG) - .into(binding.detailSubChannelThumbnailView); + CoilHelper.INSTANCE.loadAvatar(binding.detailSubChannelThumbnailView, + info.getSubChannelAvatars()); binding.detailSubChannelThumbnailView.setVisibility(View.VISIBLE); - PicassoHelper.loadAvatar(info.getUploaderAvatars()).tag(PICASSO_VIDEO_DETAILS_TAG) - .into(binding.detailUploaderThumbnailView); + CoilHelper.INSTANCE.loadAvatar(binding.detailUploaderThumbnailView, + info.getUploaderAvatars()); binding.detailUploaderThumbnailView.setVisibility(View.VISIBLE); } @@ -2403,8 +2407,7 @@ public final class VideoDetailFragment binding.overlayTitleTextView.setText(isEmpty(overlayTitle) ? "" : overlayTitle); binding.overlayChannelTextView.setText(isEmpty(uploader) ? "" : uploader); binding.overlayThumbnail.setImageDrawable(null); - PicassoHelper.loadDetailsThumbnail(thumbnails).tag(PICASSO_VIDEO_DETAILS_TAG) - .into(binding.overlayThumbnail); + CoilHelper.INSTANCE.loadDetailsThumbnail(binding.overlayThumbnail, thumbnails); } private void setOverlayPlayPauseImage(final boolean playerIsPlaying) { diff --git a/app/src/main/java/org/schabi/newpipe/fragments/list/channel/ChannelFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/list/channel/ChannelFragment.java index fd382adbf..e2001f512 100644 --- a/app/src/main/java/org/schabi/newpipe/fragments/list/channel/ChannelFragment.java +++ b/app/src/main/java/org/schabi/newpipe/fragments/list/channel/ChannelFragment.java @@ -50,10 +50,11 @@ import org.schabi.newpipe.util.ExtractorHelper; import org.schabi.newpipe.util.Localization; import org.schabi.newpipe.util.NavigationHelper; import org.schabi.newpipe.util.StateSaver; -import org.schabi.newpipe.util.image.ImageStrategy; -import org.schabi.newpipe.util.image.PicassoHelper; import org.schabi.newpipe.util.ThemeHelper; import org.schabi.newpipe.util.external_communication.ShareUtils; +import org.schabi.newpipe.util.image.CoilHelper; +import org.schabi.newpipe.util.image.ImageStrategy; +import org.schabi.newpipe.util.image.PicassoHelper; import java.util.List; import java.util.Queue; @@ -587,17 +588,15 @@ public class ChannelFragment extends BaseStateFragment setInitialData(result.getServiceId(), result.getOriginalUrl(), result.getName()); if (ImageStrategy.shouldLoadImages() && !result.getBanners().isEmpty()) { - PicassoHelper.loadBanner(result.getBanners()).tag(PICASSO_CHANNEL_TAG) - .into(binding.channelBannerImage); + CoilHelper.INSTANCE.loadBanner(binding.channelBannerImage, result.getBanners()); } else { // do not waste space for the banner, if the user disabled images or there is not one binding.channelBannerImage.setImageDrawable(null); } - PicassoHelper.loadAvatar(result.getAvatars()).tag(PICASSO_CHANNEL_TAG) - .into(binding.channelAvatarView); - PicassoHelper.loadAvatar(result.getParentChannelAvatars()).tag(PICASSO_CHANNEL_TAG) - .into(binding.subChannelAvatarView); + CoilHelper.INSTANCE.loadAvatar(binding.channelAvatarView, result.getAvatars()); + CoilHelper.INSTANCE.loadAvatar(binding.subChannelAvatarView, + result.getParentChannelAvatars()); binding.channelTitleView.setText(result.getName()); binding.channelSubscriberView.setVisibility(View.VISIBLE); diff --git a/app/src/main/java/org/schabi/newpipe/fragments/list/comments/CommentRepliesFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/list/comments/CommentRepliesFragment.java index 304eaf55a..4eb73520f 100644 --- a/app/src/main/java/org/schabi/newpipe/fragments/list/comments/CommentRepliesFragment.java +++ b/app/src/main/java/org/schabi/newpipe/fragments/list/comments/CommentRepliesFragment.java @@ -23,8 +23,8 @@ import org.schabi.newpipe.util.DeviceUtils; import org.schabi.newpipe.util.ExtractorHelper; import org.schabi.newpipe.util.Localization; import org.schabi.newpipe.util.NavigationHelper; +import org.schabi.newpipe.util.image.CoilHelper; import org.schabi.newpipe.util.image.ImageStrategy; -import org.schabi.newpipe.util.image.PicassoHelper; import org.schabi.newpipe.util.text.TextLinkifier; import java.util.Queue; @@ -82,7 +82,7 @@ public final class CommentRepliesFragment final CommentsInfoItem item = commentsInfoItem; // load the author avatar - PicassoHelper.loadAvatar(item.getUploaderAvatars()).into(binding.authorAvatar); + CoilHelper.INSTANCE.loadAvatar(binding.authorAvatar, item.getUploaderAvatars()); binding.authorAvatar.setVisibility(ImageStrategy.shouldLoadImages() ? View.VISIBLE : View.GONE); diff --git a/app/src/main/java/org/schabi/newpipe/fragments/list/playlist/PlaylistFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/list/playlist/PlaylistFragment.java index 6410fb9ee..09ba3a736 100644 --- a/app/src/main/java/org/schabi/newpipe/fragments/list/playlist/PlaylistFragment.java +++ b/app/src/main/java/org/schabi/newpipe/fragments/list/playlist/PlaylistFragment.java @@ -53,6 +53,7 @@ import org.schabi.newpipe.util.Localization; import org.schabi.newpipe.util.NavigationHelper; import org.schabi.newpipe.util.PlayButtonHelper; import org.schabi.newpipe.util.external_communication.ShareUtils; +import org.schabi.newpipe.util.image.CoilHelper; import org.schabi.newpipe.util.image.PicassoHelper; import org.schabi.newpipe.util.text.TextEllipsizer; @@ -327,8 +328,8 @@ public class PlaylistFragment extends BaseListInfoFragment() { +) : BindableItem() { companion object { const val PAYLOAD_SELECT = 1 @@ -21,31 +20,32 @@ class StreamSegmentItem( var isSelected = false - override fun bind(viewHolder: GroupieViewHolder, position: Int) { - item.previewUrl?.let { - PicassoHelper.loadThumbnail(it) - .into(viewHolder.root.findViewById(R.id.previewImage)) - } - viewHolder.root.findViewById(R.id.textViewTitle).text = item.title + override fun bind(viewBinding: ItemStreamSegmentBinding, position: Int) { + CoilHelper.loadThumbnail(viewBinding.previewImage, item.previewUrl) + viewBinding.textViewTitle.text = item.title if (item.channelName == null) { - viewHolder.root.findViewById(R.id.textViewChannel).visibility = View.GONE + viewBinding.textViewChannel.visibility = View.GONE // When the channel name is displayed there is less space // and thus the segment title needs to be only one line height. // But when there is no channel name displayed, the title can be two lines long. // The default maxLines value is set to 1 to display all elements in the AS preview, - viewHolder.root.findViewById(R.id.textViewTitle).maxLines = 2 + viewBinding.textViewTitle.maxLines = 2 } else { - viewHolder.root.findViewById(R.id.textViewChannel).text = item.channelName - viewHolder.root.findViewById(R.id.textViewChannel).visibility = View.VISIBLE + viewBinding.textViewChannel.text = item.channelName + viewBinding.textViewChannel.visibility = View.VISIBLE } - viewHolder.root.findViewById(R.id.textViewStartSeconds).text = + viewBinding.textViewStartSeconds.text = Localization.getDurationString(item.startTimeSeconds.toLong()) - viewHolder.root.setOnClickListener { onClick.onItemClick(this, item.startTimeSeconds) } - viewHolder.root.setOnLongClickListener { onClick.onItemLongClick(this, item.startTimeSeconds); true } - viewHolder.root.isSelected = isSelected + viewBinding.root.setOnClickListener { onClick.onItemClick(this, item.startTimeSeconds) } + viewBinding.root.setOnLongClickListener { onClick.onItemLongClick(this, item.startTimeSeconds); true } + viewBinding.root.isSelected = isSelected } - override fun bind(viewHolder: GroupieViewHolder, position: Int, payloads: MutableList) { + override fun bind( + viewHolder: GroupieViewHolder, + position: Int, + payloads: MutableList + ) { if (payloads.contains(PAYLOAD_SELECT)) { viewHolder.root.isSelected = isSelected return @@ -54,4 +54,6 @@ class StreamSegmentItem( } override fun getLayout() = R.layout.item_stream_segment + + override fun initializeViewBinding(view: View) = ItemStreamSegmentBinding.bind(view) } diff --git a/app/src/main/java/org/schabi/newpipe/info_list/holder/ChannelMiniInfoItemHolder.java b/app/src/main/java/org/schabi/newpipe/info_list/holder/ChannelMiniInfoItemHolder.java index 7afc05c6c..92a5054e1 100644 --- a/app/src/main/java/org/schabi/newpipe/info_list/holder/ChannelMiniInfoItemHolder.java +++ b/app/src/main/java/org/schabi/newpipe/info_list/holder/ChannelMiniInfoItemHolder.java @@ -13,8 +13,8 @@ import org.schabi.newpipe.extractor.channel.ChannelInfoItem; import org.schabi.newpipe.extractor.utils.Utils; import org.schabi.newpipe.info_list.InfoItemBuilder; import org.schabi.newpipe.local.history.HistoryRecordManager; -import org.schabi.newpipe.util.image.PicassoHelper; import org.schabi.newpipe.util.Localization; +import org.schabi.newpipe.util.image.CoilHelper; public class ChannelMiniInfoItemHolder extends InfoItemHolder { private final ImageView itemThumbnailView; @@ -56,7 +56,7 @@ public class ChannelMiniInfoItemHolder extends InfoItemHolder { itemAdditionalDetailView.setText(getDetailLine(item)); } - PicassoHelper.loadAvatar(item.getThumbnails()).into(itemThumbnailView); + CoilHelper.INSTANCE.loadAvatar(itemThumbnailView, item.getThumbnails()); itemView.setOnClickListener(view -> { if (itemBuilder.getOnChannelSelectedListener() != null) { diff --git a/app/src/main/java/org/schabi/newpipe/info_list/holder/CommentInfoItemHolder.java b/app/src/main/java/org/schabi/newpipe/info_list/holder/CommentInfoItemHolder.java index 839aa1813..a3316d3fe 100644 --- a/app/src/main/java/org/schabi/newpipe/info_list/holder/CommentInfoItemHolder.java +++ b/app/src/main/java/org/schabi/newpipe/info_list/holder/CommentInfoItemHolder.java @@ -27,8 +27,8 @@ import org.schabi.newpipe.util.DeviceUtils; import org.schabi.newpipe.util.Localization; import org.schabi.newpipe.util.NavigationHelper; import org.schabi.newpipe.util.external_communication.ShareUtils; +import org.schabi.newpipe.util.image.CoilHelper; import org.schabi.newpipe.util.image.ImageStrategy; -import org.schabi.newpipe.util.image.PicassoHelper; import org.schabi.newpipe.util.text.TextEllipsizer; public class CommentInfoItemHolder extends InfoItemHolder { @@ -82,14 +82,12 @@ public class CommentInfoItemHolder extends InfoItemHolder { @Override public void updateFromItem(final InfoItem infoItem, final HistoryRecordManager historyRecordManager) { - if (!(infoItem instanceof CommentsInfoItem)) { + if (!(infoItem instanceof CommentsInfoItem item)) { return; } - final CommentsInfoItem item = (CommentsInfoItem) infoItem; - // load the author avatar - PicassoHelper.loadAvatar(item.getUploaderAvatars()).into(itemThumbnailView); + CoilHelper.INSTANCE.loadAvatar(itemThumbnailView, item.getUploaderAvatars()); if (ImageStrategy.shouldLoadImages()) { itemThumbnailView.setVisibility(View.VISIBLE); itemRoot.setPadding(commentVerticalPadding, commentVerticalPadding, diff --git a/app/src/main/java/org/schabi/newpipe/info_list/holder/PlaylistMiniInfoItemHolder.java b/app/src/main/java/org/schabi/newpipe/info_list/holder/PlaylistMiniInfoItemHolder.java index c9216d9a9..b7949318d 100644 --- a/app/src/main/java/org/schabi/newpipe/info_list/holder/PlaylistMiniInfoItemHolder.java +++ b/app/src/main/java/org/schabi/newpipe/info_list/holder/PlaylistMiniInfoItemHolder.java @@ -9,8 +9,8 @@ import org.schabi.newpipe.extractor.InfoItem; import org.schabi.newpipe.extractor.playlist.PlaylistInfoItem; import org.schabi.newpipe.info_list.InfoItemBuilder; import org.schabi.newpipe.local.history.HistoryRecordManager; -import org.schabi.newpipe.util.image.PicassoHelper; import org.schabi.newpipe.util.Localization; +import org.schabi.newpipe.util.image.CoilHelper; public class PlaylistMiniInfoItemHolder extends InfoItemHolder { public final ImageView itemThumbnailView; @@ -46,7 +46,7 @@ public class PlaylistMiniInfoItemHolder extends InfoItemHolder { .localizeStreamCountMini(itemStreamCountView.getContext(), item.getStreamCount())); itemUploaderView.setText(item.getUploaderName()); - PicassoHelper.loadPlaylistThumbnail(item.getThumbnails()).into(itemThumbnailView); + CoilHelper.INSTANCE.loadPlaylistThumbnail(itemThumbnailView, item.getThumbnails()); itemView.setOnClickListener(view -> { if (itemBuilder.getOnPlaylistSelectedListener() != null) { diff --git a/app/src/main/java/org/schabi/newpipe/info_list/holder/StreamMiniInfoItemHolder.java b/app/src/main/java/org/schabi/newpipe/info_list/holder/StreamMiniInfoItemHolder.java index 01f3be6b3..32fa8bf60 100644 --- a/app/src/main/java/org/schabi/newpipe/info_list/holder/StreamMiniInfoItemHolder.java +++ b/app/src/main/java/org/schabi/newpipe/info_list/holder/StreamMiniInfoItemHolder.java @@ -16,8 +16,8 @@ import org.schabi.newpipe.ktx.ViewUtils; import org.schabi.newpipe.local.history.HistoryRecordManager; import org.schabi.newpipe.util.DependentPreferenceHelper; import org.schabi.newpipe.util.Localization; -import org.schabi.newpipe.util.image.PicassoHelper; import org.schabi.newpipe.util.StreamTypeUtil; +import org.schabi.newpipe.util.image.CoilHelper; import org.schabi.newpipe.views.AnimatedProgressBar; import java.util.concurrent.TimeUnit; @@ -87,7 +87,7 @@ public class StreamMiniInfoItemHolder extends InfoItemHolder { } // Default thumbnail is shown on error, while loading and if the url is empty - PicassoHelper.loadThumbnail(item.getThumbnails()).into(itemThumbnailView); + CoilHelper.INSTANCE.loadThumbnail(itemThumbnailView, item.getThumbnails()); itemView.setOnClickListener(view -> { if (itemBuilder.getOnStreamSelectedListener() != null) { diff --git a/app/src/main/java/org/schabi/newpipe/local/feed/item/StreamItem.kt b/app/src/main/java/org/schabi/newpipe/local/feed/item/StreamItem.kt index 4a071d6df..030bb7a76 100644 --- a/app/src/main/java/org/schabi/newpipe/local/feed/item/StreamItem.kt +++ b/app/src/main/java/org/schabi/newpipe/local/feed/item/StreamItem.kt @@ -19,7 +19,7 @@ import org.schabi.newpipe.extractor.stream.StreamType.POST_LIVE_STREAM import org.schabi.newpipe.extractor.stream.StreamType.VIDEO_STREAM import org.schabi.newpipe.util.Localization import org.schabi.newpipe.util.StreamTypeUtil -import org.schabi.newpipe.util.image.PicassoHelper +import org.schabi.newpipe.util.image.CoilHelper import java.util.concurrent.TimeUnit import java.util.function.Consumer @@ -101,7 +101,7 @@ data class StreamItem( viewBinding.itemProgressView.visibility = View.GONE } - PicassoHelper.loadThumbnail(stream.thumbnailUrl).into(viewBinding.itemThumbnailView) + CoilHelper.loadThumbnail(viewBinding.itemThumbnailView, stream.thumbnailUrl) if (itemVersion != ItemVersion.MINI) { viewBinding.itemAdditionalDetails.text = diff --git a/app/src/main/java/org/schabi/newpipe/local/holder/LocalPlaylistItemHolder.java b/app/src/main/java/org/schabi/newpipe/local/holder/LocalPlaylistItemHolder.java index 336f5cfe3..a11438374 100644 --- a/app/src/main/java/org/schabi/newpipe/local/holder/LocalPlaylistItemHolder.java +++ b/app/src/main/java/org/schabi/newpipe/local/holder/LocalPlaylistItemHolder.java @@ -8,8 +8,8 @@ import org.schabi.newpipe.database.playlist.PlaylistDuplicatesEntry; import org.schabi.newpipe.database.playlist.PlaylistMetadataEntry; import org.schabi.newpipe.local.LocalItemBuilder; import org.schabi.newpipe.local.history.HistoryRecordManager; -import org.schabi.newpipe.util.image.PicassoHelper; import org.schabi.newpipe.util.Localization; +import org.schabi.newpipe.util.image.CoilHelper; import java.time.format.DateTimeFormatter; @@ -30,17 +30,16 @@ public class LocalPlaylistItemHolder extends PlaylistItemHolder { public void updateFromItem(final LocalItem localItem, final HistoryRecordManager historyRecordManager, final DateTimeFormatter dateTimeFormatter) { - if (!(localItem instanceof PlaylistMetadataEntry)) { + if (!(localItem instanceof PlaylistMetadataEntry item)) { return; } - final PlaylistMetadataEntry item = (PlaylistMetadataEntry) localItem; itemTitleView.setText(item.name); itemStreamCountView.setText(Localization.localizeStreamCountMini( itemStreamCountView.getContext(), item.streamCount)); itemUploaderView.setVisibility(View.INVISIBLE); - PicassoHelper.loadPlaylistThumbnail(item.thumbnailUrl).into(itemThumbnailView); + CoilHelper.INSTANCE.loadPlaylistThumbnail(itemThumbnailView, item.thumbnailUrl); if (item instanceof PlaylistDuplicatesEntry && ((PlaylistDuplicatesEntry) item).timesStreamIsContained > 0) { diff --git a/app/src/main/java/org/schabi/newpipe/local/holder/LocalPlaylistStreamItemHolder.java b/app/src/main/java/org/schabi/newpipe/local/holder/LocalPlaylistStreamItemHolder.java index 89a714fd7..7dc71bfb4 100644 --- a/app/src/main/java/org/schabi/newpipe/local/holder/LocalPlaylistStreamItemHolder.java +++ b/app/src/main/java/org/schabi/newpipe/local/holder/LocalPlaylistStreamItemHolder.java @@ -16,8 +16,8 @@ import org.schabi.newpipe.local.LocalItemBuilder; import org.schabi.newpipe.local.history.HistoryRecordManager; import org.schabi.newpipe.util.DependentPreferenceHelper; import org.schabi.newpipe.util.Localization; -import org.schabi.newpipe.util.image.PicassoHelper; import org.schabi.newpipe.util.ServiceHelper; +import org.schabi.newpipe.util.image.CoilHelper; import org.schabi.newpipe.views.AnimatedProgressBar; import java.time.format.DateTimeFormatter; @@ -83,8 +83,8 @@ public class LocalPlaylistStreamItemHolder extends LocalItemHolder { } // Default thumbnail is shown on error, while loading and if the url is empty - PicassoHelper.loadThumbnail(item.getStreamEntity().getThumbnailUrl()) - .into(itemThumbnailView); + CoilHelper.INSTANCE.loadThumbnail(itemThumbnailView, + item.getStreamEntity().getThumbnailUrl()); itemView.setOnClickListener(view -> { if (itemBuilder.getOnItemSelectedListener() != null) { diff --git a/app/src/main/java/org/schabi/newpipe/local/holder/LocalStatisticStreamItemHolder.java b/app/src/main/java/org/schabi/newpipe/local/holder/LocalStatisticStreamItemHolder.java index 150a35eb5..f26a76ad9 100644 --- a/app/src/main/java/org/schabi/newpipe/local/holder/LocalStatisticStreamItemHolder.java +++ b/app/src/main/java/org/schabi/newpipe/local/holder/LocalStatisticStreamItemHolder.java @@ -16,8 +16,8 @@ import org.schabi.newpipe.local.LocalItemBuilder; import org.schabi.newpipe.local.history.HistoryRecordManager; import org.schabi.newpipe.util.DependentPreferenceHelper; import org.schabi.newpipe.util.Localization; -import org.schabi.newpipe.util.image.PicassoHelper; import org.schabi.newpipe.util.ServiceHelper; +import org.schabi.newpipe.util.image.CoilHelper; import org.schabi.newpipe.views.AnimatedProgressBar; import java.time.format.DateTimeFormatter; @@ -117,8 +117,8 @@ public class LocalStatisticStreamItemHolder extends LocalItemHolder { } // Default thumbnail is shown on error, while loading and if the url is empty - PicassoHelper.loadThumbnail(item.getStreamEntity().getThumbnailUrl()) - .into(itemThumbnailView); + CoilHelper.INSTANCE.loadThumbnail(itemThumbnailView, + item.getStreamEntity().getThumbnailUrl()); itemView.setOnClickListener(view -> { if (itemBuilder.getOnItemSelectedListener() != null) { diff --git a/app/src/main/java/org/schabi/newpipe/local/holder/RemotePlaylistItemHolder.java b/app/src/main/java/org/schabi/newpipe/local/holder/RemotePlaylistItemHolder.java index 765732063..f79f3c785 100644 --- a/app/src/main/java/org/schabi/newpipe/local/holder/RemotePlaylistItemHolder.java +++ b/app/src/main/java/org/schabi/newpipe/local/holder/RemotePlaylistItemHolder.java @@ -8,8 +8,8 @@ import org.schabi.newpipe.database.playlist.model.PlaylistRemoteEntity; import org.schabi.newpipe.local.LocalItemBuilder; import org.schabi.newpipe.local.history.HistoryRecordManager; import org.schabi.newpipe.util.Localization; -import org.schabi.newpipe.util.image.PicassoHelper; import org.schabi.newpipe.util.ServiceHelper; +import org.schabi.newpipe.util.image.CoilHelper; import java.time.format.DateTimeFormatter; @@ -29,10 +29,9 @@ public class RemotePlaylistItemHolder extends PlaylistItemHolder { public void updateFromItem(final LocalItem localItem, final HistoryRecordManager historyRecordManager, final DateTimeFormatter dateTimeFormatter) { - if (!(localItem instanceof PlaylistRemoteEntity)) { + if (!(localItem instanceof PlaylistRemoteEntity item)) { return; } - final PlaylistRemoteEntity item = (PlaylistRemoteEntity) localItem; itemTitleView.setText(item.getName()); itemStreamCountView.setText(Localization.localizeStreamCountMini( @@ -45,7 +44,7 @@ public class RemotePlaylistItemHolder extends PlaylistItemHolder { itemUploaderView.setText(ServiceHelper.getNameOfServiceById(item.getServiceId())); } - PicassoHelper.loadPlaylistThumbnail(item.getThumbnailUrl()).into(itemThumbnailView); + CoilHelper.INSTANCE.loadPlaylistThumbnail(itemThumbnailView, item.getThumbnailUrl()); super.updateFromItem(localItem, historyRecordManager, dateTimeFormatter); } diff --git a/app/src/main/java/org/schabi/newpipe/local/subscription/item/ChannelItem.kt b/app/src/main/java/org/schabi/newpipe/local/subscription/item/ChannelItem.kt index bc39dafe6..ca626e704 100644 --- a/app/src/main/java/org/schabi/newpipe/local/subscription/item/ChannelItem.kt +++ b/app/src/main/java/org/schabi/newpipe/local/subscription/item/ChannelItem.kt @@ -9,7 +9,7 @@ import org.schabi.newpipe.R import org.schabi.newpipe.extractor.channel.ChannelInfoItem import org.schabi.newpipe.util.Localization import org.schabi.newpipe.util.OnClickGesture -import org.schabi.newpipe.util.image.PicassoHelper +import org.schabi.newpipe.util.image.CoilHelper class ChannelItem( private val infoItem: ChannelInfoItem, @@ -39,7 +39,7 @@ class ChannelItem( itemChannelDescriptionView.text = infoItem.description } - PicassoHelper.loadAvatar(infoItem.thumbnails).into(itemThumbnailView) + CoilHelper.loadAvatar(itemThumbnailView, infoItem.thumbnails) gesturesListener?.run { viewHolder.root.setOnClickListener { selected(infoItem) } diff --git a/app/src/main/java/org/schabi/newpipe/local/subscription/item/PickerSubscriptionItem.kt b/app/src/main/java/org/schabi/newpipe/local/subscription/item/PickerSubscriptionItem.kt index 3a4c6e41b..da35447e3 100644 --- a/app/src/main/java/org/schabi/newpipe/local/subscription/item/PickerSubscriptionItem.kt +++ b/app/src/main/java/org/schabi/newpipe/local/subscription/item/PickerSubscriptionItem.kt @@ -10,7 +10,7 @@ import org.schabi.newpipe.database.subscription.SubscriptionEntity import org.schabi.newpipe.databinding.PickerSubscriptionItemBinding import org.schabi.newpipe.ktx.AnimationType import org.schabi.newpipe.ktx.animate -import org.schabi.newpipe.util.image.PicassoHelper +import org.schabi.newpipe.util.image.CoilHelper data class PickerSubscriptionItem( val subscriptionEntity: SubscriptionEntity, @@ -21,7 +21,7 @@ data class PickerSubscriptionItem( override fun getSpanSize(spanCount: Int, position: Int): Int = 1 override fun bind(viewBinding: PickerSubscriptionItemBinding, position: Int) { - PicassoHelper.loadAvatar(subscriptionEntity.avatarUrl).into(viewBinding.thumbnailView) + CoilHelper.loadAvatar(viewBinding.thumbnailView, subscriptionEntity.avatarUrl) viewBinding.titleView.text = subscriptionEntity.name viewBinding.selectedHighlight.isVisible = isSelected } diff --git a/app/src/main/java/org/schabi/newpipe/player/Player.java b/app/src/main/java/org/schabi/newpipe/player/Player.java index 49e72328e..49b1611be 100644 --- a/app/src/main/java/org/schabi/newpipe/player/Player.java +++ b/app/src/main/java/org/schabi/newpipe/player/Player.java @@ -86,8 +86,8 @@ import org.schabi.newpipe.databinding.PlayerBinding; import org.schabi.newpipe.error.ErrorInfo; import org.schabi.newpipe.error.ErrorUtil; import org.schabi.newpipe.error.UserAction; -import org.schabi.newpipe.extractor.stream.AudioStream; import org.schabi.newpipe.extractor.Image; +import org.schabi.newpipe.extractor.stream.AudioStream; import org.schabi.newpipe.extractor.stream.StreamInfo; import org.schabi.newpipe.extractor.stream.StreamType; import org.schabi.newpipe.extractor.stream.VideoStream; @@ -118,9 +118,9 @@ import org.schabi.newpipe.player.ui.VideoPlayerUi; import org.schabi.newpipe.util.DependentPreferenceHelper; import org.schabi.newpipe.util.ListHelper; import org.schabi.newpipe.util.NavigationHelper; -import org.schabi.newpipe.util.image.PicassoHelper; import org.schabi.newpipe.util.SerializedCache; import org.schabi.newpipe.util.StreamTypeUtil; +import org.schabi.newpipe.util.image.PicassoHelper; import java.util.List; import java.util.Optional; @@ -816,7 +816,7 @@ public final class Player implements PlaybackListener, Listener { cancelLoadingCurrentThumbnail(); // Unset currentThumbnail, since it is now outdated. This ensures it is not used in media - // session metadata while the new thumbnail is being loaded by Picasso. + // session metadata while the new thumbnail is being loaded by Coil. onThumbnailLoaded(null); if (thumbnails.isEmpty()) { return; diff --git a/app/src/main/java/org/schabi/newpipe/player/playqueue/PlayQueueItemBuilder.java b/app/src/main/java/org/schabi/newpipe/player/playqueue/PlayQueueItemBuilder.java index 066f92c26..8994aef79 100644 --- a/app/src/main/java/org/schabi/newpipe/player/playqueue/PlayQueueItemBuilder.java +++ b/app/src/main/java/org/schabi/newpipe/player/playqueue/PlayQueueItemBuilder.java @@ -6,8 +6,8 @@ import android.view.MotionEvent; import android.view.View; import org.schabi.newpipe.util.Localization; -import org.schabi.newpipe.util.image.PicassoHelper; import org.schabi.newpipe.util.ServiceHelper; +import org.schabi.newpipe.util.image.CoilHelper; public class PlayQueueItemBuilder { private static final String TAG = PlayQueueItemBuilder.class.toString(); @@ -33,7 +33,7 @@ public class PlayQueueItemBuilder { holder.itemDurationView.setVisibility(View.GONE); } - PicassoHelper.loadThumbnail(item.getThumbnails()).into(holder.itemThumbnailView); + CoilHelper.INSTANCE.loadThumbnail(holder.itemThumbnailView, item.getThumbnails()); holder.itemRoot.setOnClickListener(view -> { if (onItemClickListener != null) { diff --git a/app/src/main/java/org/schabi/newpipe/player/seekbarpreview/SeekbarPreviewThumbnailHolder.java b/app/src/main/java/org/schabi/newpipe/player/seekbarpreview/SeekbarPreviewThumbnailHolder.java index 26065de15..c7c53b097 100644 --- a/app/src/main/java/org/schabi/newpipe/player/seekbarpreview/SeekbarPreviewThumbnailHolder.java +++ b/app/src/main/java/org/schabi/newpipe/player/seekbarpreview/SeekbarPreviewThumbnailHolder.java @@ -13,8 +13,9 @@ import androidx.collection.SparseArrayCompat; import com.google.common.base.Stopwatch; +import org.schabi.newpipe.App; import org.schabi.newpipe.extractor.stream.Frameset; -import org.schabi.newpipe.util.image.PicassoHelper; +import org.schabi.newpipe.util.image.CoilHelper; import java.util.Comparator; import java.util.List; @@ -177,8 +178,8 @@ public class SeekbarPreviewThumbnailHolder { Log.d(TAG, "Downloading bitmap for seekbarPreview from '" + url + "'"); // Gets the bitmap within the timeout of 15 seconds imposed by default by OkHttpClient - // Ensure that your are not running on the main-Thread this will otherwise hang - final Bitmap bitmap = PicassoHelper.loadSeekbarThumbnailPreview(url).get(); + // Ensure that you are not running on the main thread, otherwise this will hang + final var bitmap = CoilHelper.INSTANCE.loadBitmap(App.getApp(), url); if (sw != null) { Log.d(TAG, "Download of bitmap for seekbarPreview from '" + url + "' took " diff --git a/app/src/main/java/org/schabi/newpipe/settings/ContentSettingsFragment.java b/app/src/main/java/org/schabi/newpipe/settings/ContentSettingsFragment.java index ec2bed67a..4e6830cb9 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/ContentSettingsFragment.java +++ b/app/src/main/java/org/schabi/newpipe/settings/ContentSettingsFragment.java @@ -13,10 +13,9 @@ import org.schabi.newpipe.extractor.NewPipe; import org.schabi.newpipe.extractor.localization.ContentCountry; import org.schabi.newpipe.extractor.localization.Localization; import org.schabi.newpipe.util.image.ImageStrategy; -import org.schabi.newpipe.util.image.PicassoHelper; import org.schabi.newpipe.util.image.PreferredImageQuality; -import java.io.IOException; +import coil.Coil; public class ContentSettingsFragment extends BasePreferenceFragment { private String youtubeRestrictedModeEnabledKey; @@ -42,14 +41,17 @@ public class ContentSettingsFragment extends BasePreferenceFragment { (preference, newValue) -> { ImageStrategy.setPreferredImageQuality(PreferredImageQuality .fromPreferenceKey(requireContext(), (String) newValue)); - try { - PicassoHelper.clearCache(preference.getContext()); - Toast.makeText(preference.getContext(), - R.string.thumbnail_cache_wipe_complete_notice, Toast.LENGTH_SHORT) - .show(); - } catch (final IOException e) { - Log.e(TAG, "Unable to clear Picasso cache", e); + final var loader = Coil.imageLoader(preference.getContext()); + if (loader.getMemoryCache() != null) { + loader.getMemoryCache().clear(); } + if (loader.getDiskCache() != null) { + loader.getDiskCache().clear(); + } + Toast.makeText(preference.getContext(), + R.string.thumbnail_cache_wipe_complete_notice, Toast.LENGTH_SHORT) + .show(); + return true; }); } diff --git a/app/src/main/java/org/schabi/newpipe/settings/SelectChannelFragment.java b/app/src/main/java/org/schabi/newpipe/settings/SelectChannelFragment.java index 37335421d..c566313e3 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/SelectChannelFragment.java +++ b/app/src/main/java/org/schabi/newpipe/settings/SelectChannelFragment.java @@ -19,8 +19,8 @@ import org.schabi.newpipe.R; import org.schabi.newpipe.database.subscription.SubscriptionEntity; import org.schabi.newpipe.error.ErrorUtil; import org.schabi.newpipe.local.subscription.SubscriptionManager; -import org.schabi.newpipe.util.image.PicassoHelper; import org.schabi.newpipe.util.ThemeHelper; +import org.schabi.newpipe.util.image.CoilHelper; import java.util.List; import java.util.Vector; @@ -190,7 +190,7 @@ public class SelectChannelFragment extends DialogFragment { final SubscriptionEntity entry = subscriptions.get(position); holder.titleView.setText(entry.getName()); holder.view.setOnClickListener(view -> clickedItem(position)); - PicassoHelper.loadAvatar(entry.getAvatarUrl()).into(holder.thumbnailView); + CoilHelper.INSTANCE.loadAvatar(holder.thumbnailView, entry.getAvatarUrl()); } @Override diff --git a/app/src/main/java/org/schabi/newpipe/settings/SelectPlaylistFragment.java b/app/src/main/java/org/schabi/newpipe/settings/SelectPlaylistFragment.java index 36abef9e5..c340dca22 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/SelectPlaylistFragment.java +++ b/app/src/main/java/org/schabi/newpipe/settings/SelectPlaylistFragment.java @@ -27,7 +27,7 @@ import org.schabi.newpipe.error.ErrorUtil; import org.schabi.newpipe.error.UserAction; import org.schabi.newpipe.local.playlist.LocalPlaylistManager; import org.schabi.newpipe.local.playlist.RemotePlaylistManager; -import org.schabi.newpipe.util.image.PicassoHelper; +import org.schabi.newpipe.util.image.CoilHelper; import java.util.List; import java.util.Vector; @@ -154,20 +154,15 @@ public class SelectPlaylistFragment extends DialogFragment { final int position) { final PlaylistLocalItem selectedItem = playlists.get(position); - if (selectedItem instanceof PlaylistMetadataEntry) { - final PlaylistMetadataEntry entry = ((PlaylistMetadataEntry) selectedItem); - + if (selectedItem instanceof PlaylistMetadataEntry entry) { holder.titleView.setText(entry.name); holder.view.setOnClickListener(view -> clickedItem(position)); - PicassoHelper.loadPlaylistThumbnail(entry.thumbnailUrl).into(holder.thumbnailView); - - } else if (selectedItem instanceof PlaylistRemoteEntity) { - final PlaylistRemoteEntity entry = ((PlaylistRemoteEntity) selectedItem); - + CoilHelper.INSTANCE.loadPlaylistThumbnail(holder.thumbnailView, entry.thumbnailUrl); + } else if (selectedItem instanceof PlaylistRemoteEntity entry) { holder.titleView.setText(entry.getName()); holder.view.setOnClickListener(view -> clickedItem(position)); - PicassoHelper.loadPlaylistThumbnail(entry.getThumbnailUrl()) - .into(holder.thumbnailView); + CoilHelper.INSTANCE.loadPlaylistThumbnail(holder.thumbnailView, + entry.getThumbnailUrl()); } } diff --git a/app/src/main/java/org/schabi/newpipe/util/image/CoilHelper.kt b/app/src/main/java/org/schabi/newpipe/util/image/CoilHelper.kt new file mode 100644 index 000000000..ce92341d5 --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/util/image/CoilHelper.kt @@ -0,0 +1,94 @@ +package org.schabi.newpipe.util.image + +import android.content.Context +import android.graphics.Bitmap +import android.widget.ImageView +import androidx.annotation.DrawableRes +import androidx.core.graphics.drawable.toBitmapOrNull +import coil.executeBlocking +import coil.imageLoader +import coil.request.ImageRequest +import org.schabi.newpipe.R +import org.schabi.newpipe.extractor.Image + +object CoilHelper { + fun loadBitmap(context: Context, url: String): Bitmap? { + val request = ImageRequest.Builder(context) + .data(url) + .build() + return context.imageLoader.executeBlocking(request).drawable?.toBitmapOrNull() + } + + fun loadAvatar(target: ImageView, images: List) { + loadImageDefault(target, images, R.drawable.placeholder_person) + } + + fun loadAvatar(target: ImageView, url: String?) { + loadImageDefault(target, url, R.drawable.placeholder_person) + } + + fun loadThumbnail(target: ImageView, images: List) { + loadImageDefault(target, images, R.drawable.placeholder_thumbnail_video) + } + + fun loadThumbnail(target: ImageView, url: String?) { + loadImageDefault(target, url, R.drawable.placeholder_thumbnail_video) + } + + fun loadDetailsThumbnail(target: ImageView, images: List) { + val url = ImageStrategy.choosePreferredImage(images) + loadImageDefault(target, url, R.drawable.placeholder_thumbnail_video, false) + } + + fun loadBanner(target: ImageView, images: List) { + loadImageDefault(target, images, R.drawable.placeholder_channel_banner) + } + + fun loadPlaylistThumbnail(target: ImageView, images: List) { + loadImageDefault(target, images, R.drawable.placeholder_thumbnail_playlist) + } + + fun loadPlaylistThumbnail(target: ImageView, url: String?) { + loadImageDefault(target, url, R.drawable.placeholder_thumbnail_playlist) + } + + private fun loadImageDefault( + target: ImageView, + images: List, + @DrawableRes placeholderResId: Int + ) { + loadImageDefault(target, ImageStrategy.choosePreferredImage(images), placeholderResId) + } + + private fun loadImageDefault( + target: ImageView, + url: String?, + @DrawableRes placeholderResId: Int, + showPlaceholder: Boolean = true + ) { + val request = getImageRequest(target.context, url, placeholderResId, showPlaceholder) + .build() + target.context.imageLoader.enqueue(request) + } + + private fun getImageRequest( + context: Context, + url: String?, + @DrawableRes placeholderResId: Int, + showPlaceholderWhileLoading: Boolean = true + ): ImageRequest.Builder { + // if the URL was chosen with `choosePreferredImage` it will be null, but check again + // `shouldLoadImages` in case the URL was chosen with `imageListToDbUrl` (which is the case + // for URLs stored in the database) + val takenUrl = url?.takeIf { it.isNotEmpty() && ImageStrategy.shouldLoadImages() } + + return ImageRequest.Builder(context) + .data(takenUrl) + .error(placeholderResId) + .apply { + if (takenUrl != null || showPlaceholderWhileLoading) { + placeholder(placeholderResId) + } + } + } +} diff --git a/app/src/main/java/org/schabi/newpipe/util/image/PicassoHelper.java b/app/src/main/java/org/schabi/newpipe/util/image/PicassoHelper.java index 4b116bdf9..257f36133 100644 --- a/app/src/main/java/org/schabi/newpipe/util/image/PicassoHelper.java +++ b/app/src/main/java/org/schabi/newpipe/util/image/PicassoHelper.java @@ -25,7 +25,6 @@ import org.schabi.newpipe.R; import org.schabi.newpipe.extractor.Image; import java.io.File; -import java.io.IOException; import java.util.List; import java.util.concurrent.TimeUnit; @@ -63,26 +62,6 @@ public final class PicassoHelper { .build(); } - public static void terminate() { - picassoCache = null; - picassoDownloaderClient = null; - - if (picassoInstance != null) { - picassoInstance.shutdown(); - picassoInstance = null; - } - } - - public static void clearCache(final Context context) throws IOException { - picassoInstance.shutdown(); - picassoCache.clear(); // clear memory cache - final okhttp3.Cache diskCache = picassoDownloaderClient.cache(); - if (diskCache != null) { - diskCache.delete(); // clear disk cache - } - init(context); - } - public static void cancelTag(final Object tag) { picassoInstance.cancelTag(tag); } @@ -91,53 +70,14 @@ public final class PicassoHelper { picassoInstance.setIndicatorsEnabled(enabled); // useful for debugging } - - public static RequestCreator loadAvatar(@NonNull final List images) { - return loadImageDefault(images, R.drawable.placeholder_person); - } - - public static RequestCreator loadAvatar(@Nullable final String url) { - return loadImageDefault(url, R.drawable.placeholder_person); - } - public static RequestCreator loadThumbnail(@NonNull final List images) { return loadImageDefault(images, R.drawable.placeholder_thumbnail_video); } - public static RequestCreator loadThumbnail(@Nullable final String url) { - return loadImageDefault(url, R.drawable.placeholder_thumbnail_video); - } - - public static RequestCreator loadDetailsThumbnail(@NonNull final List images) { - return loadImageDefault(choosePreferredImage(images), - R.drawable.placeholder_thumbnail_video, false); - } - - public static RequestCreator loadBanner(@NonNull final List images) { - return loadImageDefault(images, R.drawable.placeholder_channel_banner); - } - - public static RequestCreator loadPlaylistThumbnail(@NonNull final List images) { - return loadImageDefault(images, R.drawable.placeholder_thumbnail_playlist); - } - - public static RequestCreator loadPlaylistThumbnail(@Nullable final String url) { - return loadImageDefault(url, R.drawable.placeholder_thumbnail_playlist); - } - - public static RequestCreator loadSeekbarThumbnailPreview(@Nullable final String url) { - return picassoInstance.load(url); - } - - public static RequestCreator loadNotificationIcon(@Nullable final String url) { - return loadImageDefault(url, R.drawable.ic_newpipe_triangle_white); - } - - public static RequestCreator loadScaledDownThumbnail(final Context context, @NonNull final List images) { // scale down the notification thumbnail for performance - return PicassoHelper.loadThumbnail(images) + return loadThumbnail(images) .transform(new Transformation() { @Override public Bitmap transform(final Bitmap source) {