Migrate to Coil from Picasso

This commit is contained in:
Isira Seneviratne 2024-06-22 08:32:06 +05:30
parent 92a7f22d3c
commit 844b4edf48
25 changed files with 226 additions and 173 deletions

View File

@ -20,10 +20,10 @@ import org.schabi.newpipe.extractor.downloader.Downloader;
import org.schabi.newpipe.ktx.ExceptionUtils; import org.schabi.newpipe.ktx.ExceptionUtils;
import org.schabi.newpipe.settings.NewPipeSettings; import org.schabi.newpipe.settings.NewPipeSettings;
import org.schabi.newpipe.util.Localization; 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.ServiceHelper;
import org.schabi.newpipe.util.StateSaver; 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 org.schabi.newpipe.util.image.PreferredImageQuality;
import java.io.IOException; import java.io.IOException;
@ -32,6 +32,11 @@ import java.net.SocketException;
import java.util.List; import java.util.List;
import java.util.Objects; 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.CompositeException;
import io.reactivex.rxjava3.exceptions.MissingBackpressureException; import io.reactivex.rxjava3.exceptions.MissingBackpressureException;
import io.reactivex.rxjava3.exceptions.OnErrorNotImplementedException; import io.reactivex.rxjava3.exceptions.OnErrorNotImplementedException;
@ -57,7 +62,7 @@ import io.reactivex.rxjava3.plugins.RxJavaPlugins;
* along with NewPipe. If not, see <http://www.gnu.org/licenses/>. * along with NewPipe. If not, see <http://www.gnu.org/licenses/>.
*/ */
public class App extends Application { public class App extends Application implements ImageLoaderFactory {
public static final String PACKAGE_NAME = BuildConfig.APPLICATION_ID; public static final String PACKAGE_NAME = BuildConfig.APPLICATION_ID;
private static final String TAG = App.class.toString(); private static final String TAG = App.class.toString();
@ -118,10 +123,25 @@ public class App extends Application {
configureRxJavaErrorHandler(); configureRxJavaErrorHandler();
} }
@NonNull
@Override @Override
public void onTerminate() { public ImageLoader newImageLoader() {
super.onTerminate(); final var builder = new ImageLoader.Builder(this)
PicassoHelper.terminate(); .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() { protected Downloader getDownloader() {

View File

@ -116,7 +116,7 @@ import org.schabi.newpipe.util.StreamTypeUtil;
import org.schabi.newpipe.util.ThemeHelper; import org.schabi.newpipe.util.ThemeHelper;
import org.schabi.newpipe.util.external_communication.KoreUtils; import org.schabi.newpipe.util.external_communication.KoreUtils;
import org.schabi.newpipe.util.external_communication.ShareUtils; 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.ArrayList;
import java.util.Iterator; import java.util.Iterator;
@ -127,6 +127,7 @@ import java.util.Optional;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.function.Consumer; import java.util.function.Consumer;
import coil.util.CoilUtils;
import icepick.State; import icepick.State;
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers; import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
import io.reactivex.rxjava3.disposables.CompositeDisposable; 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.detailThumbnailImageView.setImageBitmap(null);
binding.detailSubChannelThumbnailView.setImageBitmap(null); binding.detailSubChannelThumbnailView.setImageBitmap(null);
} }
@ -1562,8 +1566,8 @@ public final class VideoDetailFragment
binding.detailSecondaryControlPanel.setVisibility(View.GONE); binding.detailSecondaryControlPanel.setVisibility(View.GONE);
checkUpdateProgressInfo(info); checkUpdateProgressInfo(info);
PicassoHelper.loadDetailsThumbnail(info.getThumbnails()).tag(PICASSO_VIDEO_DETAILS_TAG) CoilHelper.INSTANCE.loadDetailsThumbnail(binding.detailThumbnailImageView,
.into(binding.detailThumbnailImageView); info.getThumbnails());
showMetaInfoInTextView(info.getMetaInfo(), binding.detailMetaInfoTextView, showMetaInfoInTextView(info.getMetaInfo(), binding.detailMetaInfoTextView,
binding.detailMetaInfoSeparator, disposables); binding.detailMetaInfoSeparator, disposables);
@ -1613,8 +1617,8 @@ public final class VideoDetailFragment
binding.detailUploaderTextView.setVisibility(View.GONE); binding.detailUploaderTextView.setVisibility(View.GONE);
} }
PicassoHelper.loadAvatar(info.getUploaderAvatars()).tag(PICASSO_VIDEO_DETAILS_TAG) CoilHelper.INSTANCE.loadAvatar(binding.detailSubChannelThumbnailView,
.into(binding.detailSubChannelThumbnailView); info.getUploaderAvatars());
binding.detailSubChannelThumbnailView.setVisibility(View.VISIBLE); binding.detailSubChannelThumbnailView.setVisibility(View.VISIBLE);
binding.detailUploaderThumbnailView.setVisibility(View.GONE); binding.detailUploaderThumbnailView.setVisibility(View.GONE);
} }
@ -1645,11 +1649,11 @@ public final class VideoDetailFragment
binding.detailUploaderTextView.setVisibility(View.GONE); binding.detailUploaderTextView.setVisibility(View.GONE);
} }
PicassoHelper.loadAvatar(info.getSubChannelAvatars()).tag(PICASSO_VIDEO_DETAILS_TAG) CoilHelper.INSTANCE.loadAvatar(binding.detailSubChannelThumbnailView,
.into(binding.detailSubChannelThumbnailView); info.getSubChannelAvatars());
binding.detailSubChannelThumbnailView.setVisibility(View.VISIBLE); binding.detailSubChannelThumbnailView.setVisibility(View.VISIBLE);
PicassoHelper.loadAvatar(info.getUploaderAvatars()).tag(PICASSO_VIDEO_DETAILS_TAG) CoilHelper.INSTANCE.loadAvatar(binding.detailUploaderThumbnailView,
.into(binding.detailUploaderThumbnailView); info.getUploaderAvatars());
binding.detailUploaderThumbnailView.setVisibility(View.VISIBLE); binding.detailUploaderThumbnailView.setVisibility(View.VISIBLE);
} }
@ -2403,8 +2407,7 @@ public final class VideoDetailFragment
binding.overlayTitleTextView.setText(isEmpty(overlayTitle) ? "" : overlayTitle); binding.overlayTitleTextView.setText(isEmpty(overlayTitle) ? "" : overlayTitle);
binding.overlayChannelTextView.setText(isEmpty(uploader) ? "" : uploader); binding.overlayChannelTextView.setText(isEmpty(uploader) ? "" : uploader);
binding.overlayThumbnail.setImageDrawable(null); binding.overlayThumbnail.setImageDrawable(null);
PicassoHelper.loadDetailsThumbnail(thumbnails).tag(PICASSO_VIDEO_DETAILS_TAG) CoilHelper.INSTANCE.loadDetailsThumbnail(binding.overlayThumbnail, thumbnails);
.into(binding.overlayThumbnail);
} }
private void setOverlayPlayPauseImage(final boolean playerIsPlaying) { private void setOverlayPlayPauseImage(final boolean playerIsPlaying) {

View File

@ -50,10 +50,11 @@ import org.schabi.newpipe.util.ExtractorHelper;
import org.schabi.newpipe.util.Localization; import org.schabi.newpipe.util.Localization;
import org.schabi.newpipe.util.NavigationHelper; import org.schabi.newpipe.util.NavigationHelper;
import org.schabi.newpipe.util.StateSaver; 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.ThemeHelper;
import org.schabi.newpipe.util.external_communication.ShareUtils; 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.List;
import java.util.Queue; import java.util.Queue;
@ -587,17 +588,15 @@ public class ChannelFragment extends BaseStateFragment<ChannelInfo>
setInitialData(result.getServiceId(), result.getOriginalUrl(), result.getName()); setInitialData(result.getServiceId(), result.getOriginalUrl(), result.getName());
if (ImageStrategy.shouldLoadImages() && !result.getBanners().isEmpty()) { if (ImageStrategy.shouldLoadImages() && !result.getBanners().isEmpty()) {
PicassoHelper.loadBanner(result.getBanners()).tag(PICASSO_CHANNEL_TAG) CoilHelper.INSTANCE.loadBanner(binding.channelBannerImage, result.getBanners());
.into(binding.channelBannerImage);
} else { } else {
// do not waste space for the banner, if the user disabled images or there is not one // do not waste space for the banner, if the user disabled images or there is not one
binding.channelBannerImage.setImageDrawable(null); binding.channelBannerImage.setImageDrawable(null);
} }
PicassoHelper.loadAvatar(result.getAvatars()).tag(PICASSO_CHANNEL_TAG) CoilHelper.INSTANCE.loadAvatar(binding.channelAvatarView, result.getAvatars());
.into(binding.channelAvatarView); CoilHelper.INSTANCE.loadAvatar(binding.subChannelAvatarView,
PicassoHelper.loadAvatar(result.getParentChannelAvatars()).tag(PICASSO_CHANNEL_TAG) result.getParentChannelAvatars());
.into(binding.subChannelAvatarView);
binding.channelTitleView.setText(result.getName()); binding.channelTitleView.setText(result.getName());
binding.channelSubscriberView.setVisibility(View.VISIBLE); binding.channelSubscriberView.setVisibility(View.VISIBLE);

View File

@ -23,8 +23,8 @@ import org.schabi.newpipe.util.DeviceUtils;
import org.schabi.newpipe.util.ExtractorHelper; import org.schabi.newpipe.util.ExtractorHelper;
import org.schabi.newpipe.util.Localization; import org.schabi.newpipe.util.Localization;
import org.schabi.newpipe.util.NavigationHelper; 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.ImageStrategy;
import org.schabi.newpipe.util.image.PicassoHelper;
import org.schabi.newpipe.util.text.TextLinkifier; import org.schabi.newpipe.util.text.TextLinkifier;
import java.util.Queue; import java.util.Queue;
@ -82,7 +82,7 @@ public final class CommentRepliesFragment
final CommentsInfoItem item = commentsInfoItem; final CommentsInfoItem item = commentsInfoItem;
// load the author avatar // load the author avatar
PicassoHelper.loadAvatar(item.getUploaderAvatars()).into(binding.authorAvatar); CoilHelper.INSTANCE.loadAvatar(binding.authorAvatar, item.getUploaderAvatars());
binding.authorAvatar.setVisibility(ImageStrategy.shouldLoadImages() binding.authorAvatar.setVisibility(ImageStrategy.shouldLoadImages()
? View.VISIBLE : View.GONE); ? View.VISIBLE : View.GONE);

View File

@ -53,6 +53,7 @@ import org.schabi.newpipe.util.Localization;
import org.schabi.newpipe.util.NavigationHelper; import org.schabi.newpipe.util.NavigationHelper;
import org.schabi.newpipe.util.PlayButtonHelper; import org.schabi.newpipe.util.PlayButtonHelper;
import org.schabi.newpipe.util.external_communication.ShareUtils; 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.image.PicassoHelper;
import org.schabi.newpipe.util.text.TextEllipsizer; import org.schabi.newpipe.util.text.TextEllipsizer;
@ -327,8 +328,8 @@ public class PlaylistFragment extends BaseListInfoFragment<StreamInfoItem, Playl
R.drawable.ic_radio) R.drawable.ic_radio)
); );
} else { } else {
PicassoHelper.loadAvatar(result.getUploaderAvatars()).tag(PICASSO_PLAYLIST_TAG) CoilHelper.INSTANCE.loadAvatar(headerBinding.uploaderAvatarView,
.into(headerBinding.uploaderAvatarView); result.getUploaderAvatars());
} }
streamCount = result.getStreamCount(); streamCount = result.getStreamCount();

View File

@ -1,19 +1,18 @@
package org.schabi.newpipe.info_list package org.schabi.newpipe.info_list
import android.view.View import android.view.View
import android.widget.ImageView import com.xwray.groupie.viewbinding.BindableItem
import android.widget.TextView import com.xwray.groupie.viewbinding.GroupieViewHolder
import com.xwray.groupie.GroupieViewHolder
import com.xwray.groupie.Item
import org.schabi.newpipe.R import org.schabi.newpipe.R
import org.schabi.newpipe.databinding.ItemStreamSegmentBinding
import org.schabi.newpipe.extractor.stream.StreamSegment import org.schabi.newpipe.extractor.stream.StreamSegment
import org.schabi.newpipe.util.Localization import org.schabi.newpipe.util.Localization
import org.schabi.newpipe.util.image.PicassoHelper import org.schabi.newpipe.util.image.CoilHelper
class StreamSegmentItem( class StreamSegmentItem(
private val item: StreamSegment, private val item: StreamSegment,
private val onClick: StreamSegmentAdapter.StreamSegmentListener private val onClick: StreamSegmentAdapter.StreamSegmentListener
) : Item<GroupieViewHolder>() { ) : BindableItem<ItemStreamSegmentBinding>() {
companion object { companion object {
const val PAYLOAD_SELECT = 1 const val PAYLOAD_SELECT = 1
@ -21,31 +20,32 @@ class StreamSegmentItem(
var isSelected = false var isSelected = false
override fun bind(viewHolder: GroupieViewHolder, position: Int) { override fun bind(viewBinding: ItemStreamSegmentBinding, position: Int) {
item.previewUrl?.let { CoilHelper.loadThumbnail(viewBinding.previewImage, item.previewUrl)
PicassoHelper.loadThumbnail(it) viewBinding.textViewTitle.text = item.title
.into(viewHolder.root.findViewById<ImageView>(R.id.previewImage))
}
viewHolder.root.findViewById<TextView>(R.id.textViewTitle).text = item.title
if (item.channelName == null) { if (item.channelName == null) {
viewHolder.root.findViewById<TextView>(R.id.textViewChannel).visibility = View.GONE viewBinding.textViewChannel.visibility = View.GONE
// When the channel name is displayed there is less space // When the channel name is displayed there is less space
// and thus the segment title needs to be only one line height. // 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. // 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, // The default maxLines value is set to 1 to display all elements in the AS preview,
viewHolder.root.findViewById<TextView>(R.id.textViewTitle).maxLines = 2 viewBinding.textViewTitle.maxLines = 2
} else { } else {
viewHolder.root.findViewById<TextView>(R.id.textViewChannel).text = item.channelName viewBinding.textViewChannel.text = item.channelName
viewHolder.root.findViewById<TextView>(R.id.textViewChannel).visibility = View.VISIBLE viewBinding.textViewChannel.visibility = View.VISIBLE
} }
viewHolder.root.findViewById<TextView>(R.id.textViewStartSeconds).text = viewBinding.textViewStartSeconds.text =
Localization.getDurationString(item.startTimeSeconds.toLong()) Localization.getDurationString(item.startTimeSeconds.toLong())
viewHolder.root.setOnClickListener { onClick.onItemClick(this, item.startTimeSeconds) } viewBinding.root.setOnClickListener { onClick.onItemClick(this, item.startTimeSeconds) }
viewHolder.root.setOnLongClickListener { onClick.onItemLongClick(this, item.startTimeSeconds); true } viewBinding.root.setOnLongClickListener { onClick.onItemLongClick(this, item.startTimeSeconds); true }
viewHolder.root.isSelected = isSelected viewBinding.root.isSelected = isSelected
} }
override fun bind(viewHolder: GroupieViewHolder, position: Int, payloads: MutableList<Any>) { override fun bind(
viewHolder: GroupieViewHolder<ItemStreamSegmentBinding>,
position: Int,
payloads: MutableList<Any>
) {
if (payloads.contains(PAYLOAD_SELECT)) { if (payloads.contains(PAYLOAD_SELECT)) {
viewHolder.root.isSelected = isSelected viewHolder.root.isSelected = isSelected
return return
@ -54,4 +54,6 @@ class StreamSegmentItem(
} }
override fun getLayout() = R.layout.item_stream_segment override fun getLayout() = R.layout.item_stream_segment
override fun initializeViewBinding(view: View) = ItemStreamSegmentBinding.bind(view)
} }

View File

@ -13,8 +13,8 @@ import org.schabi.newpipe.extractor.channel.ChannelInfoItem;
import org.schabi.newpipe.extractor.utils.Utils; import org.schabi.newpipe.extractor.utils.Utils;
import org.schabi.newpipe.info_list.InfoItemBuilder; import org.schabi.newpipe.info_list.InfoItemBuilder;
import org.schabi.newpipe.local.history.HistoryRecordManager; 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.Localization;
import org.schabi.newpipe.util.image.CoilHelper;
public class ChannelMiniInfoItemHolder extends InfoItemHolder { public class ChannelMiniInfoItemHolder extends InfoItemHolder {
private final ImageView itemThumbnailView; private final ImageView itemThumbnailView;
@ -56,7 +56,7 @@ public class ChannelMiniInfoItemHolder extends InfoItemHolder {
itemAdditionalDetailView.setText(getDetailLine(item)); itemAdditionalDetailView.setText(getDetailLine(item));
} }
PicassoHelper.loadAvatar(item.getThumbnails()).into(itemThumbnailView); CoilHelper.INSTANCE.loadAvatar(itemThumbnailView, item.getThumbnails());
itemView.setOnClickListener(view -> { itemView.setOnClickListener(view -> {
if (itemBuilder.getOnChannelSelectedListener() != null) { if (itemBuilder.getOnChannelSelectedListener() != null) {

View File

@ -27,8 +27,8 @@ import org.schabi.newpipe.util.DeviceUtils;
import org.schabi.newpipe.util.Localization; import org.schabi.newpipe.util.Localization;
import org.schabi.newpipe.util.NavigationHelper; import org.schabi.newpipe.util.NavigationHelper;
import org.schabi.newpipe.util.external_communication.ShareUtils; 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.ImageStrategy;
import org.schabi.newpipe.util.image.PicassoHelper;
import org.schabi.newpipe.util.text.TextEllipsizer; import org.schabi.newpipe.util.text.TextEllipsizer;
public class CommentInfoItemHolder extends InfoItemHolder { public class CommentInfoItemHolder extends InfoItemHolder {
@ -82,14 +82,12 @@ public class CommentInfoItemHolder extends InfoItemHolder {
@Override @Override
public void updateFromItem(final InfoItem infoItem, public void updateFromItem(final InfoItem infoItem,
final HistoryRecordManager historyRecordManager) { final HistoryRecordManager historyRecordManager) {
if (!(infoItem instanceof CommentsInfoItem)) { if (!(infoItem instanceof CommentsInfoItem item)) {
return; return;
} }
final CommentsInfoItem item = (CommentsInfoItem) infoItem;
// load the author avatar // load the author avatar
PicassoHelper.loadAvatar(item.getUploaderAvatars()).into(itemThumbnailView); CoilHelper.INSTANCE.loadAvatar(itemThumbnailView, item.getUploaderAvatars());
if (ImageStrategy.shouldLoadImages()) { if (ImageStrategy.shouldLoadImages()) {
itemThumbnailView.setVisibility(View.VISIBLE); itemThumbnailView.setVisibility(View.VISIBLE);
itemRoot.setPadding(commentVerticalPadding, commentVerticalPadding, itemRoot.setPadding(commentVerticalPadding, commentVerticalPadding,

View File

@ -9,8 +9,8 @@ import org.schabi.newpipe.extractor.InfoItem;
import org.schabi.newpipe.extractor.playlist.PlaylistInfoItem; import org.schabi.newpipe.extractor.playlist.PlaylistInfoItem;
import org.schabi.newpipe.info_list.InfoItemBuilder; import org.schabi.newpipe.info_list.InfoItemBuilder;
import org.schabi.newpipe.local.history.HistoryRecordManager; 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.Localization;
import org.schabi.newpipe.util.image.CoilHelper;
public class PlaylistMiniInfoItemHolder extends InfoItemHolder { public class PlaylistMiniInfoItemHolder extends InfoItemHolder {
public final ImageView itemThumbnailView; public final ImageView itemThumbnailView;
@ -46,7 +46,7 @@ public class PlaylistMiniInfoItemHolder extends InfoItemHolder {
.localizeStreamCountMini(itemStreamCountView.getContext(), item.getStreamCount())); .localizeStreamCountMini(itemStreamCountView.getContext(), item.getStreamCount()));
itemUploaderView.setText(item.getUploaderName()); itemUploaderView.setText(item.getUploaderName());
PicassoHelper.loadPlaylistThumbnail(item.getThumbnails()).into(itemThumbnailView); CoilHelper.INSTANCE.loadPlaylistThumbnail(itemThumbnailView, item.getThumbnails());
itemView.setOnClickListener(view -> { itemView.setOnClickListener(view -> {
if (itemBuilder.getOnPlaylistSelectedListener() != null) { if (itemBuilder.getOnPlaylistSelectedListener() != null) {

View File

@ -16,8 +16,8 @@ import org.schabi.newpipe.ktx.ViewUtils;
import org.schabi.newpipe.local.history.HistoryRecordManager; import org.schabi.newpipe.local.history.HistoryRecordManager;
import org.schabi.newpipe.util.DependentPreferenceHelper; import org.schabi.newpipe.util.DependentPreferenceHelper;
import org.schabi.newpipe.util.Localization; import org.schabi.newpipe.util.Localization;
import org.schabi.newpipe.util.image.PicassoHelper;
import org.schabi.newpipe.util.StreamTypeUtil; import org.schabi.newpipe.util.StreamTypeUtil;
import org.schabi.newpipe.util.image.CoilHelper;
import org.schabi.newpipe.views.AnimatedProgressBar; import org.schabi.newpipe.views.AnimatedProgressBar;
import java.util.concurrent.TimeUnit; 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 // 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 -> { itemView.setOnClickListener(view -> {
if (itemBuilder.getOnStreamSelectedListener() != null) { if (itemBuilder.getOnStreamSelectedListener() != null) {

View File

@ -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.extractor.stream.StreamType.VIDEO_STREAM
import org.schabi.newpipe.util.Localization import org.schabi.newpipe.util.Localization
import org.schabi.newpipe.util.StreamTypeUtil 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.concurrent.TimeUnit
import java.util.function.Consumer import java.util.function.Consumer
@ -101,7 +101,7 @@ data class StreamItem(
viewBinding.itemProgressView.visibility = View.GONE viewBinding.itemProgressView.visibility = View.GONE
} }
PicassoHelper.loadThumbnail(stream.thumbnailUrl).into(viewBinding.itemThumbnailView) CoilHelper.loadThumbnail(viewBinding.itemThumbnailView, stream.thumbnailUrl)
if (itemVersion != ItemVersion.MINI) { if (itemVersion != ItemVersion.MINI) {
viewBinding.itemAdditionalDetails.text = viewBinding.itemAdditionalDetails.text =

View File

@ -8,8 +8,8 @@ import org.schabi.newpipe.database.playlist.PlaylistDuplicatesEntry;
import org.schabi.newpipe.database.playlist.PlaylistMetadataEntry; import org.schabi.newpipe.database.playlist.PlaylistMetadataEntry;
import org.schabi.newpipe.local.LocalItemBuilder; import org.schabi.newpipe.local.LocalItemBuilder;
import org.schabi.newpipe.local.history.HistoryRecordManager; 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.Localization;
import org.schabi.newpipe.util.image.CoilHelper;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
@ -30,17 +30,16 @@ public class LocalPlaylistItemHolder extends PlaylistItemHolder {
public void updateFromItem(final LocalItem localItem, public void updateFromItem(final LocalItem localItem,
final HistoryRecordManager historyRecordManager, final HistoryRecordManager historyRecordManager,
final DateTimeFormatter dateTimeFormatter) { final DateTimeFormatter dateTimeFormatter) {
if (!(localItem instanceof PlaylistMetadataEntry)) { if (!(localItem instanceof PlaylistMetadataEntry item)) {
return; return;
} }
final PlaylistMetadataEntry item = (PlaylistMetadataEntry) localItem;
itemTitleView.setText(item.name); itemTitleView.setText(item.name);
itemStreamCountView.setText(Localization.localizeStreamCountMini( itemStreamCountView.setText(Localization.localizeStreamCountMini(
itemStreamCountView.getContext(), item.streamCount)); itemStreamCountView.getContext(), item.streamCount));
itemUploaderView.setVisibility(View.INVISIBLE); itemUploaderView.setVisibility(View.INVISIBLE);
PicassoHelper.loadPlaylistThumbnail(item.thumbnailUrl).into(itemThumbnailView); CoilHelper.INSTANCE.loadPlaylistThumbnail(itemThumbnailView, item.thumbnailUrl);
if (item instanceof PlaylistDuplicatesEntry if (item instanceof PlaylistDuplicatesEntry
&& ((PlaylistDuplicatesEntry) item).timesStreamIsContained > 0) { && ((PlaylistDuplicatesEntry) item).timesStreamIsContained > 0) {

View File

@ -16,8 +16,8 @@ import org.schabi.newpipe.local.LocalItemBuilder;
import org.schabi.newpipe.local.history.HistoryRecordManager; import org.schabi.newpipe.local.history.HistoryRecordManager;
import org.schabi.newpipe.util.DependentPreferenceHelper; import org.schabi.newpipe.util.DependentPreferenceHelper;
import org.schabi.newpipe.util.Localization; import org.schabi.newpipe.util.Localization;
import org.schabi.newpipe.util.image.PicassoHelper;
import org.schabi.newpipe.util.ServiceHelper; import org.schabi.newpipe.util.ServiceHelper;
import org.schabi.newpipe.util.image.CoilHelper;
import org.schabi.newpipe.views.AnimatedProgressBar; import org.schabi.newpipe.views.AnimatedProgressBar;
import java.time.format.DateTimeFormatter; 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 // Default thumbnail is shown on error, while loading and if the url is empty
PicassoHelper.loadThumbnail(item.getStreamEntity().getThumbnailUrl()) CoilHelper.INSTANCE.loadThumbnail(itemThumbnailView,
.into(itemThumbnailView); item.getStreamEntity().getThumbnailUrl());
itemView.setOnClickListener(view -> { itemView.setOnClickListener(view -> {
if (itemBuilder.getOnItemSelectedListener() != null) { if (itemBuilder.getOnItemSelectedListener() != null) {

View File

@ -16,8 +16,8 @@ import org.schabi.newpipe.local.LocalItemBuilder;
import org.schabi.newpipe.local.history.HistoryRecordManager; import org.schabi.newpipe.local.history.HistoryRecordManager;
import org.schabi.newpipe.util.DependentPreferenceHelper; import org.schabi.newpipe.util.DependentPreferenceHelper;
import org.schabi.newpipe.util.Localization; import org.schabi.newpipe.util.Localization;
import org.schabi.newpipe.util.image.PicassoHelper;
import org.schabi.newpipe.util.ServiceHelper; import org.schabi.newpipe.util.ServiceHelper;
import org.schabi.newpipe.util.image.CoilHelper;
import org.schabi.newpipe.views.AnimatedProgressBar; import org.schabi.newpipe.views.AnimatedProgressBar;
import java.time.format.DateTimeFormatter; 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 // Default thumbnail is shown on error, while loading and if the url is empty
PicassoHelper.loadThumbnail(item.getStreamEntity().getThumbnailUrl()) CoilHelper.INSTANCE.loadThumbnail(itemThumbnailView,
.into(itemThumbnailView); item.getStreamEntity().getThumbnailUrl());
itemView.setOnClickListener(view -> { itemView.setOnClickListener(view -> {
if (itemBuilder.getOnItemSelectedListener() != null) { if (itemBuilder.getOnItemSelectedListener() != null) {

View File

@ -8,8 +8,8 @@ import org.schabi.newpipe.database.playlist.model.PlaylistRemoteEntity;
import org.schabi.newpipe.local.LocalItemBuilder; import org.schabi.newpipe.local.LocalItemBuilder;
import org.schabi.newpipe.local.history.HistoryRecordManager; import org.schabi.newpipe.local.history.HistoryRecordManager;
import org.schabi.newpipe.util.Localization; import org.schabi.newpipe.util.Localization;
import org.schabi.newpipe.util.image.PicassoHelper;
import org.schabi.newpipe.util.ServiceHelper; import org.schabi.newpipe.util.ServiceHelper;
import org.schabi.newpipe.util.image.CoilHelper;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
@ -29,10 +29,9 @@ public class RemotePlaylistItemHolder extends PlaylistItemHolder {
public void updateFromItem(final LocalItem localItem, public void updateFromItem(final LocalItem localItem,
final HistoryRecordManager historyRecordManager, final HistoryRecordManager historyRecordManager,
final DateTimeFormatter dateTimeFormatter) { final DateTimeFormatter dateTimeFormatter) {
if (!(localItem instanceof PlaylistRemoteEntity)) { if (!(localItem instanceof PlaylistRemoteEntity item)) {
return; return;
} }
final PlaylistRemoteEntity item = (PlaylistRemoteEntity) localItem;
itemTitleView.setText(item.getName()); itemTitleView.setText(item.getName());
itemStreamCountView.setText(Localization.localizeStreamCountMini( itemStreamCountView.setText(Localization.localizeStreamCountMini(
@ -45,7 +44,7 @@ public class RemotePlaylistItemHolder extends PlaylistItemHolder {
itemUploaderView.setText(ServiceHelper.getNameOfServiceById(item.getServiceId())); itemUploaderView.setText(ServiceHelper.getNameOfServiceById(item.getServiceId()));
} }
PicassoHelper.loadPlaylistThumbnail(item.getThumbnailUrl()).into(itemThumbnailView); CoilHelper.INSTANCE.loadPlaylistThumbnail(itemThumbnailView, item.getThumbnailUrl());
super.updateFromItem(localItem, historyRecordManager, dateTimeFormatter); super.updateFromItem(localItem, historyRecordManager, dateTimeFormatter);
} }

View File

@ -9,7 +9,7 @@ import org.schabi.newpipe.R
import org.schabi.newpipe.extractor.channel.ChannelInfoItem import org.schabi.newpipe.extractor.channel.ChannelInfoItem
import org.schabi.newpipe.util.Localization import org.schabi.newpipe.util.Localization
import org.schabi.newpipe.util.OnClickGesture import org.schabi.newpipe.util.OnClickGesture
import org.schabi.newpipe.util.image.PicassoHelper import org.schabi.newpipe.util.image.CoilHelper
class ChannelItem( class ChannelItem(
private val infoItem: ChannelInfoItem, private val infoItem: ChannelInfoItem,
@ -39,7 +39,7 @@ class ChannelItem(
itemChannelDescriptionView.text = infoItem.description itemChannelDescriptionView.text = infoItem.description
} }
PicassoHelper.loadAvatar(infoItem.thumbnails).into(itemThumbnailView) CoilHelper.loadAvatar(itemThumbnailView, infoItem.thumbnails)
gesturesListener?.run { gesturesListener?.run {
viewHolder.root.setOnClickListener { selected(infoItem) } viewHolder.root.setOnClickListener { selected(infoItem) }

View File

@ -10,7 +10,7 @@ import org.schabi.newpipe.database.subscription.SubscriptionEntity
import org.schabi.newpipe.databinding.PickerSubscriptionItemBinding import org.schabi.newpipe.databinding.PickerSubscriptionItemBinding
import org.schabi.newpipe.ktx.AnimationType import org.schabi.newpipe.ktx.AnimationType
import org.schabi.newpipe.ktx.animate import org.schabi.newpipe.ktx.animate
import org.schabi.newpipe.util.image.PicassoHelper import org.schabi.newpipe.util.image.CoilHelper
data class PickerSubscriptionItem( data class PickerSubscriptionItem(
val subscriptionEntity: SubscriptionEntity, val subscriptionEntity: SubscriptionEntity,
@ -21,7 +21,7 @@ data class PickerSubscriptionItem(
override fun getSpanSize(spanCount: Int, position: Int): Int = 1 override fun getSpanSize(spanCount: Int, position: Int): Int = 1
override fun bind(viewBinding: PickerSubscriptionItemBinding, position: Int) { 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.titleView.text = subscriptionEntity.name
viewBinding.selectedHighlight.isVisible = isSelected viewBinding.selectedHighlight.isVisible = isSelected
} }

View File

@ -86,8 +86,8 @@ import org.schabi.newpipe.databinding.PlayerBinding;
import org.schabi.newpipe.error.ErrorInfo; import org.schabi.newpipe.error.ErrorInfo;
import org.schabi.newpipe.error.ErrorUtil; import org.schabi.newpipe.error.ErrorUtil;
import org.schabi.newpipe.error.UserAction; import org.schabi.newpipe.error.UserAction;
import org.schabi.newpipe.extractor.stream.AudioStream;
import org.schabi.newpipe.extractor.Image; 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.StreamInfo;
import org.schabi.newpipe.extractor.stream.StreamType; import org.schabi.newpipe.extractor.stream.StreamType;
import org.schabi.newpipe.extractor.stream.VideoStream; 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.DependentPreferenceHelper;
import org.schabi.newpipe.util.ListHelper; import org.schabi.newpipe.util.ListHelper;
import org.schabi.newpipe.util.NavigationHelper; import org.schabi.newpipe.util.NavigationHelper;
import org.schabi.newpipe.util.image.PicassoHelper;
import org.schabi.newpipe.util.SerializedCache; import org.schabi.newpipe.util.SerializedCache;
import org.schabi.newpipe.util.StreamTypeUtil; import org.schabi.newpipe.util.StreamTypeUtil;
import org.schabi.newpipe.util.image.PicassoHelper;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
@ -816,7 +816,7 @@ public final class Player implements PlaybackListener, Listener {
cancelLoadingCurrentThumbnail(); cancelLoadingCurrentThumbnail();
// Unset currentThumbnail, since it is now outdated. This ensures it is not used in media // 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); onThumbnailLoaded(null);
if (thumbnails.isEmpty()) { if (thumbnails.isEmpty()) {
return; return;

View File

@ -6,8 +6,8 @@ import android.view.MotionEvent;
import android.view.View; import android.view.View;
import org.schabi.newpipe.util.Localization; import org.schabi.newpipe.util.Localization;
import org.schabi.newpipe.util.image.PicassoHelper;
import org.schabi.newpipe.util.ServiceHelper; import org.schabi.newpipe.util.ServiceHelper;
import org.schabi.newpipe.util.image.CoilHelper;
public class PlayQueueItemBuilder { public class PlayQueueItemBuilder {
private static final String TAG = PlayQueueItemBuilder.class.toString(); private static final String TAG = PlayQueueItemBuilder.class.toString();
@ -33,7 +33,7 @@ public class PlayQueueItemBuilder {
holder.itemDurationView.setVisibility(View.GONE); holder.itemDurationView.setVisibility(View.GONE);
} }
PicassoHelper.loadThumbnail(item.getThumbnails()).into(holder.itemThumbnailView); CoilHelper.INSTANCE.loadThumbnail(holder.itemThumbnailView, item.getThumbnails());
holder.itemRoot.setOnClickListener(view -> { holder.itemRoot.setOnClickListener(view -> {
if (onItemClickListener != null) { if (onItemClickListener != null) {

View File

@ -13,8 +13,9 @@ import androidx.collection.SparseArrayCompat;
import com.google.common.base.Stopwatch; import com.google.common.base.Stopwatch;
import org.schabi.newpipe.App;
import org.schabi.newpipe.extractor.stream.Frameset; 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.Comparator;
import java.util.List; import java.util.List;
@ -177,8 +178,8 @@ public class SeekbarPreviewThumbnailHolder {
Log.d(TAG, "Downloading bitmap for seekbarPreview from '" + url + "'"); Log.d(TAG, "Downloading bitmap for seekbarPreview from '" + url + "'");
// Gets the bitmap within the timeout of 15 seconds imposed by default by OkHttpClient // 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 // Ensure that you are not running on the main thread, otherwise this will hang
final Bitmap bitmap = PicassoHelper.loadSeekbarThumbnailPreview(url).get(); final var bitmap = CoilHelper.INSTANCE.loadBitmap(App.getApp(), url);
if (sw != null) { if (sw != null) {
Log.d(TAG, "Download of bitmap for seekbarPreview from '" + url + "' took " Log.d(TAG, "Download of bitmap for seekbarPreview from '" + url + "' took "

View File

@ -13,10 +13,9 @@ import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.localization.ContentCountry; import org.schabi.newpipe.extractor.localization.ContentCountry;
import org.schabi.newpipe.extractor.localization.Localization; import org.schabi.newpipe.extractor.localization.Localization;
import org.schabi.newpipe.util.image.ImageStrategy; import org.schabi.newpipe.util.image.ImageStrategy;
import org.schabi.newpipe.util.image.PicassoHelper;
import org.schabi.newpipe.util.image.PreferredImageQuality; import org.schabi.newpipe.util.image.PreferredImageQuality;
import java.io.IOException; import coil.Coil;
public class ContentSettingsFragment extends BasePreferenceFragment { public class ContentSettingsFragment extends BasePreferenceFragment {
private String youtubeRestrictedModeEnabledKey; private String youtubeRestrictedModeEnabledKey;
@ -42,14 +41,17 @@ public class ContentSettingsFragment extends BasePreferenceFragment {
(preference, newValue) -> { (preference, newValue) -> {
ImageStrategy.setPreferredImageQuality(PreferredImageQuality ImageStrategy.setPreferredImageQuality(PreferredImageQuality
.fromPreferenceKey(requireContext(), (String) newValue)); .fromPreferenceKey(requireContext(), (String) newValue));
try { final var loader = Coil.imageLoader(preference.getContext());
PicassoHelper.clearCache(preference.getContext()); if (loader.getMemoryCache() != null) {
loader.getMemoryCache().clear();
}
if (loader.getDiskCache() != null) {
loader.getDiskCache().clear();
}
Toast.makeText(preference.getContext(), Toast.makeText(preference.getContext(),
R.string.thumbnail_cache_wipe_complete_notice, Toast.LENGTH_SHORT) R.string.thumbnail_cache_wipe_complete_notice, Toast.LENGTH_SHORT)
.show(); .show();
} catch (final IOException e) {
Log.e(TAG, "Unable to clear Picasso cache", e);
}
return true; return true;
}); });
} }

View File

@ -19,8 +19,8 @@ import org.schabi.newpipe.R;
import org.schabi.newpipe.database.subscription.SubscriptionEntity; import org.schabi.newpipe.database.subscription.SubscriptionEntity;
import org.schabi.newpipe.error.ErrorUtil; import org.schabi.newpipe.error.ErrorUtil;
import org.schabi.newpipe.local.subscription.SubscriptionManager; 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.ThemeHelper;
import org.schabi.newpipe.util.image.CoilHelper;
import java.util.List; import java.util.List;
import java.util.Vector; import java.util.Vector;
@ -190,7 +190,7 @@ public class SelectChannelFragment extends DialogFragment {
final SubscriptionEntity entry = subscriptions.get(position); final SubscriptionEntity entry = subscriptions.get(position);
holder.titleView.setText(entry.getName()); holder.titleView.setText(entry.getName());
holder.view.setOnClickListener(view -> clickedItem(position)); holder.view.setOnClickListener(view -> clickedItem(position));
PicassoHelper.loadAvatar(entry.getAvatarUrl()).into(holder.thumbnailView); CoilHelper.INSTANCE.loadAvatar(holder.thumbnailView, entry.getAvatarUrl());
} }
@Override @Override

View File

@ -27,7 +27,7 @@ import org.schabi.newpipe.error.ErrorUtil;
import org.schabi.newpipe.error.UserAction; import org.schabi.newpipe.error.UserAction;
import org.schabi.newpipe.local.playlist.LocalPlaylistManager; import org.schabi.newpipe.local.playlist.LocalPlaylistManager;
import org.schabi.newpipe.local.playlist.RemotePlaylistManager; 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.List;
import java.util.Vector; import java.util.Vector;
@ -154,20 +154,15 @@ public class SelectPlaylistFragment extends DialogFragment {
final int position) { final int position) {
final PlaylistLocalItem selectedItem = playlists.get(position); final PlaylistLocalItem selectedItem = playlists.get(position);
if (selectedItem instanceof PlaylistMetadataEntry) { if (selectedItem instanceof PlaylistMetadataEntry entry) {
final PlaylistMetadataEntry entry = ((PlaylistMetadataEntry) selectedItem);
holder.titleView.setText(entry.name); holder.titleView.setText(entry.name);
holder.view.setOnClickListener(view -> clickedItem(position)); holder.view.setOnClickListener(view -> clickedItem(position));
PicassoHelper.loadPlaylistThumbnail(entry.thumbnailUrl).into(holder.thumbnailView); CoilHelper.INSTANCE.loadPlaylistThumbnail(holder.thumbnailView, entry.thumbnailUrl);
} else if (selectedItem instanceof PlaylistRemoteEntity entry) {
} else if (selectedItem instanceof PlaylistRemoteEntity) {
final PlaylistRemoteEntity entry = ((PlaylistRemoteEntity) selectedItem);
holder.titleView.setText(entry.getName()); holder.titleView.setText(entry.getName());
holder.view.setOnClickListener(view -> clickedItem(position)); holder.view.setOnClickListener(view -> clickedItem(position));
PicassoHelper.loadPlaylistThumbnail(entry.getThumbnailUrl()) CoilHelper.INSTANCE.loadPlaylistThumbnail(holder.thumbnailView,
.into(holder.thumbnailView); entry.getThumbnailUrl());
} }
} }

View File

@ -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<Image>) {
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<Image>) {
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<Image>) {
val url = ImageStrategy.choosePreferredImage(images)
loadImageDefault(target, url, R.drawable.placeholder_thumbnail_video, false)
}
fun loadBanner(target: ImageView, images: List<Image>) {
loadImageDefault(target, images, R.drawable.placeholder_channel_banner)
}
fun loadPlaylistThumbnail(target: ImageView, images: List<Image>) {
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<Image>,
@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)
}
}
}
}

View File

@ -25,7 +25,6 @@ import org.schabi.newpipe.R;
import org.schabi.newpipe.extractor.Image; import org.schabi.newpipe.extractor.Image;
import java.io.File; import java.io.File;
import java.io.IOException;
import java.util.List; import java.util.List;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@ -63,26 +62,6 @@ public final class PicassoHelper {
.build(); .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) { public static void cancelTag(final Object tag) {
picassoInstance.cancelTag(tag); picassoInstance.cancelTag(tag);
} }
@ -91,53 +70,14 @@ public final class PicassoHelper {
picassoInstance.setIndicatorsEnabled(enabled); // useful for debugging picassoInstance.setIndicatorsEnabled(enabled); // useful for debugging
} }
public static RequestCreator loadAvatar(@NonNull final List<Image> 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<Image> images) { public static RequestCreator loadThumbnail(@NonNull final List<Image> images) {
return loadImageDefault(images, R.drawable.placeholder_thumbnail_video); 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<Image> images) {
return loadImageDefault(choosePreferredImage(images),
R.drawable.placeholder_thumbnail_video, false);
}
public static RequestCreator loadBanner(@NonNull final List<Image> images) {
return loadImageDefault(images, R.drawable.placeholder_channel_banner);
}
public static RequestCreator loadPlaylistThumbnail(@NonNull final List<Image> 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, public static RequestCreator loadScaledDownThumbnail(final Context context,
@NonNull final List<Image> images) { @NonNull final List<Image> images) {
// scale down the notification thumbnail for performance // scale down the notification thumbnail for performance
return PicassoHelper.loadThumbnail(images) return loadThumbnail(images)
.transform(new Transformation() { .transform(new Transformation() {
@Override @Override
public Bitmap transform(final Bitmap source) { public Bitmap transform(final Bitmap source) {