Replace UniversalImageLoader with Picasso

This commit is contained in:
Stypox 2021-03-27 14:37:44 +01:00
parent 9c5ac069d7
commit fcef783bbb
No known key found for this signature in database
GPG Key ID: 4BDF1B40A49FDD23
32 changed files with 294 additions and 528 deletions

View File

@ -246,7 +246,8 @@ dependencies {
// Circular ImageView // Circular ImageView
implementation "de.hdodenhof:circleimageview:3.1.0" implementation "de.hdodenhof:circleimageview:3.1.0"
// Image loading // Image loading
implementation "com.nostra13.universalimageloader:universal-image-loader:1.9.5" //noinspection GradleDependency --> 2.8 is the last version, not 2.71828!
implementation "com.squareup.picasso:picasso:2.8"
// Markdown library for Android // Markdown library for Android
implementation "io.noties.markwon:core:${markwonVersion}" implementation "io.noties.markwon:core:${markwonVersion}"

View File

@ -11,10 +11,6 @@ import androidx.core.app.NotificationManagerCompat;
import androidx.multidex.MultiDexApplication; import androidx.multidex.MultiDexApplication;
import androidx.preference.PreferenceManager; import androidx.preference.PreferenceManager;
import com.nostra13.universalimageloader.cache.memory.impl.LRULimitedMemoryCache;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.ImageLoaderConfiguration;
import org.acra.ACRA; import org.acra.ACRA;
import org.acra.config.ACRAConfigurationException; import org.acra.config.ACRAConfigurationException;
import org.acra.config.CoreConfiguration; import org.acra.config.CoreConfiguration;
@ -28,6 +24,7 @@ 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.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;
@ -65,9 +62,9 @@ import io.reactivex.rxjava3.plugins.RxJavaPlugins;
*/ */
public class App extends MultiDexApplication { public class App extends MultiDexApplication {
protected static final String TAG = App.class.toString();
private static App app;
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 App app;
@Nullable @Nullable
private Disposable disposable = null; private Disposable disposable = null;
@ -103,7 +100,9 @@ public class App extends MultiDexApplication {
ServiceHelper.initServices(this); ServiceHelper.initServices(this);
// Initialize image loader // Initialize image loader
ImageLoader.getInstance().init(getImageLoaderConfigurations(10, 50)); PicassoHelper.init(this);
PicassoHelper.setShouldLoadImages(PreferenceManager.getDefaultSharedPreferences(this)
.getBoolean(getString(R.string.download_thumbnail_key), true));
configureRxJavaErrorHandler(); configureRxJavaErrorHandler();
@ -117,6 +116,7 @@ public class App extends MultiDexApplication {
disposable.dispose(); disposable.dispose();
} }
super.onTerminate(); super.onTerminate();
PicassoHelper.terminate();
} }
protected Downloader getDownloader() { protected Downloader getDownloader() {
@ -201,15 +201,6 @@ public class App extends MultiDexApplication {
}); });
} }
private ImageLoaderConfiguration getImageLoaderConfigurations(final int memoryCacheSizeMb,
final int diskCacheSizeMb) {
return new ImageLoaderConfiguration.Builder(this)
.memoryCache(new LRULimitedMemoryCache(memoryCacheSizeMb * 1024 * 1024))
.diskCacheSize(diskCacheSizeMb * 1024 * 1024)
.imageDownloader(new ImageDownloader(getApplicationContext()))
.build();
}
/** /**
* Called in {@link #attachBaseContext(Context)} after calling the {@code super} method. * Called in {@link #attachBaseContext(Context)} after calling the {@code super} method.
* Should be overridden if MultiDex is enabled, since it has to be initialized before ACRA. * Should be overridden if MultiDex is enabled, since it has to be initialized before ACRA.

View File

@ -10,14 +10,11 @@ import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentManager;
import com.nostra13.universalimageloader.core.ImageLoader;
import icepick.Icepick; import icepick.Icepick;
import icepick.State; import icepick.State;
import leakcanary.AppWatcher; import leakcanary.AppWatcher;
public abstract class BaseFragment extends Fragment { public abstract class BaseFragment extends Fragment {
public static final ImageLoader IMAGE_LOADER = ImageLoader.getInstance();
protected final String TAG = getClass().getSimpleName() + "@" + Integer.toHexString(hashCode()); protected final String TAG = getClass().getSimpleName() + "@" + Integer.toHexString(hashCode());
protected final boolean DEBUG = MainActivity.DEBUG; protected final boolean DEBUG = MainActivity.DEBUG;
protected AppCompatActivity activity; protected AppCompatActivity activity;

View File

@ -17,7 +17,6 @@ import org.schabi.newpipe.util.InfoCache;
import org.schabi.newpipe.util.TLSSocketFactoryCompat; import org.schabi.newpipe.util.TLSSocketFactoryCompat;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream;
import java.security.KeyManagementException; import java.security.KeyManagementException;
import java.security.KeyStore; import java.security.KeyStore;
import java.security.KeyStoreException; import java.security.KeyStoreException;
@ -194,36 +193,6 @@ public final class DownloaderImpl extends Downloader {
} }
} }
public InputStream stream(final String siteUrl) throws IOException {
try {
final okhttp3.Request.Builder requestBuilder = new okhttp3.Request.Builder()
.method("GET", null).url(siteUrl)
.addHeader("User-Agent", USER_AGENT);
final String cookies = getCookies(siteUrl);
if (!cookies.isEmpty()) {
requestBuilder.addHeader("Cookie", cookies);
}
final okhttp3.Request request = requestBuilder.build();
final okhttp3.Response response = client.newCall(request).execute();
final ResponseBody body = response.body();
if (response.code() == 429) {
throw new ReCaptchaException("reCaptcha Challenge requested", siteUrl);
}
if (body == null) {
response.close();
return null;
}
return body.byteStream();
} catch (final ReCaptchaException e) {
throw new IOException(e.getMessage(), e.getCause());
}
}
@Override @Override
public Response execute(@NonNull final Request request) public Response execute(@NonNull final Request request)
throws IOException, ReCaptchaException { throws IOException, ReCaptchaException {

View File

@ -1,48 +0,0 @@
package org.schabi.newpipe;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.Resources;
import androidx.preference.PreferenceManager;
import com.nostra13.universalimageloader.core.download.BaseImageDownloader;
import org.schabi.newpipe.extractor.NewPipe;
import java.io.IOException;
import java.io.InputStream;
public class ImageDownloader extends BaseImageDownloader {
private final Resources resources;
private final SharedPreferences preferences;
private final String downloadThumbnailKey;
public ImageDownloader(final Context context) {
super(context);
this.resources = context.getResources();
this.preferences = PreferenceManager.getDefaultSharedPreferences(context);
this.downloadThumbnailKey = context.getString(R.string.download_thumbnail_key);
}
private boolean isDownloadingThumbnail() {
return preferences.getBoolean(downloadThumbnailKey, true);
}
@SuppressLint("ResourceType")
@Override
public InputStream getStream(final String imageUri, final Object extra) throws IOException {
if (isDownloadingThumbnail()) {
return super.getStream(imageUri, extra);
} else {
return resources.openRawResource(R.drawable.dummy_thumbnail_dark);
}
}
protected InputStream getStreamFromNetwork(final String imageUri, final Object extra)
throws IOException {
final DownloaderImpl downloader = (DownloaderImpl) NewPipe.getDownloader();
return downloader.stream(imageUri);
}
}

View File

@ -48,9 +48,7 @@ import com.google.android.exoplayer2.PlaybackParameters;
import com.google.android.material.appbar.AppBarLayout; import com.google.android.material.appbar.AppBarLayout;
import com.google.android.material.bottomsheet.BottomSheetBehavior; import com.google.android.material.bottomsheet.BottomSheetBehavior;
import com.google.android.material.tabs.TabLayout; import com.google.android.material.tabs.TabLayout;
import com.nostra13.universalimageloader.core.assist.FailReason; import com.squareup.picasso.Callback;
import com.nostra13.universalimageloader.core.listener.ImageLoadingListener;
import com.nostra13.universalimageloader.core.listener.SimpleImageLoadingListener;
import org.schabi.newpipe.App; import org.schabi.newpipe.App;
import org.schabi.newpipe.R; import org.schabi.newpipe.R;
@ -90,14 +88,14 @@ import org.schabi.newpipe.player.playqueue.SinglePlayQueue;
import org.schabi.newpipe.util.Constants; import org.schabi.newpipe.util.Constants;
import org.schabi.newpipe.util.DeviceUtils; import org.schabi.newpipe.util.DeviceUtils;
import org.schabi.newpipe.util.ExtractorHelper; import org.schabi.newpipe.util.ExtractorHelper;
import org.schabi.newpipe.util.ImageDisplayConstants;
import org.schabi.newpipe.util.external_communication.KoreUtils;
import org.schabi.newpipe.util.ListHelper; import org.schabi.newpipe.util.ListHelper;
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.PermissionHelper; import org.schabi.newpipe.util.PermissionHelper;
import org.schabi.newpipe.util.external_communication.ShareUtils; import org.schabi.newpipe.util.PicassoHelper;
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.ShareUtils;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Iterator; import java.util.Iterator;
@ -151,6 +149,8 @@ public final class VideoDetailFragment
private static final String DESCRIPTION_TAB_TAG = "DESCRIPTION TAB"; private static final String DESCRIPTION_TAB_TAG = "DESCRIPTION TAB";
private static final String EMPTY_TAB_TAG = "EMPTY TAB"; private static final String EMPTY_TAB_TAG = "EMPTY TAB";
private static final String PICASSO_VIDEO_DETAILS_TAG = "PICASSO_VIDEO_DETAILS_TAG";
// tabs // tabs
private boolean showComments; private boolean showComments;
private boolean showRelatedItems; private boolean showRelatedItems;
@ -686,33 +686,23 @@ public final class VideoDetailFragment
} }
private void initThumbnailViews(@NonNull final StreamInfo info) { private void initThumbnailViews(@NonNull final StreamInfo info) {
binding.detailThumbnailImageView.setImageResource(R.drawable.dummy_thumbnail_dark); PicassoHelper.loadThumbnail(info.getThumbnailUrl()).tag(PICASSO_VIDEO_DETAILS_TAG)
.into(binding.detailThumbnailImageView, new Callback() {
@Override
public void onSuccess() {
}
if (!isEmpty(info.getThumbnailUrl())) { @Override
final ImageLoadingListener onFailListener = new SimpleImageLoadingListener() { public void onError(final Exception e) {
@Override showSnackBarError(new ErrorInfo(e, UserAction.LOAD_IMAGE,
public void onLoadingFailed(final String imageUri, final View view, info.getThumbnailUrl(), info));
final FailReason failReason) { }
showSnackBarError(new ErrorInfo(failReason.getCause(), UserAction.LOAD_IMAGE, });
imageUri, info));
}
};
IMAGE_LOADER.displayImage(info.getThumbnailUrl(), binding.detailThumbnailImageView, PicassoHelper.loadAvatar(info.getSubChannelAvatarUrl()).tag(PICASSO_VIDEO_DETAILS_TAG)
ImageDisplayConstants.DISPLAY_THUMBNAIL_OPTIONS, onFailListener); .into(binding.detailSubChannelThumbnailView);
} PicassoHelper.loadAvatar(info.getUploaderAvatarUrl()).tag(PICASSO_VIDEO_DETAILS_TAG)
.into(binding.detailUploaderThumbnailView);
if (!isEmpty(info.getSubChannelAvatarUrl())) {
IMAGE_LOADER.displayImage(info.getSubChannelAvatarUrl(),
binding.detailSubChannelThumbnailView,
ImageDisplayConstants.DISPLAY_AVATAR_OPTIONS);
}
if (!isEmpty(info.getUploaderAvatarUrl())) {
IMAGE_LOADER.displayImage(info.getUploaderAvatarUrl(),
binding.detailUploaderThumbnailView,
ImageDisplayConstants.DISPLAY_AVATAR_OPTIONS);
}
} }
/*////////////////////////////////////////////////////////////////////////// /*//////////////////////////////////////////////////////////////////////////
@ -1446,8 +1436,7 @@ public final class VideoDetailFragment
} }
} }
IMAGE_LOADER.cancelDisplayTask(binding.detailThumbnailImageView); PicassoHelper.cancelTag(PICASSO_VIDEO_DETAILS_TAG);
IMAGE_LOADER.cancelDisplayTask(binding.detailSubChannelThumbnailView);
binding.detailThumbnailImageView.setImageBitmap(null); binding.detailThumbnailImageView.setImageBitmap(null);
binding.detailSubChannelThumbnailView.setImageBitmap(null); binding.detailSubChannelThumbnailView.setImageBitmap(null);
} }
@ -2278,10 +2267,8 @@ 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.setImageResource(R.drawable.dummy_thumbnail_dark); binding.overlayThumbnail.setImageResource(R.drawable.dummy_thumbnail_dark);
if (!isEmpty(thumbnailUrl)) { PicassoHelper.loadThumbnail(thumbnailUrl).tag(PICASSO_VIDEO_DETAILS_TAG)
IMAGE_LOADER.displayImage(thumbnailUrl, binding.overlayThumbnail, .into(binding.overlayThumbnail);
ImageDisplayConstants.DISPLAY_THUMBNAIL_OPTIONS, null);
}
} }
private void setOverlayPlayPauseImage(final boolean playerIsPlaying) { private void setOverlayPlayPauseImage(final boolean playerIsPlaying) {

View File

@ -40,10 +40,10 @@ import org.schabi.newpipe.local.subscription.SubscriptionManager;
import org.schabi.newpipe.player.playqueue.ChannelPlayQueue; import org.schabi.newpipe.player.playqueue.ChannelPlayQueue;
import org.schabi.newpipe.player.playqueue.PlayQueue; import org.schabi.newpipe.player.playqueue.PlayQueue;
import org.schabi.newpipe.util.ExtractorHelper; import org.schabi.newpipe.util.ExtractorHelper;
import org.schabi.newpipe.util.ImageDisplayConstants;
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.PicassoHelper;
import org.schabi.newpipe.util.ThemeHelper; import org.schabi.newpipe.util.ThemeHelper;
import java.util.ArrayList; import java.util.ArrayList;
@ -66,7 +66,10 @@ import static org.schabi.newpipe.ktx.ViewUtils.animateBackgroundColor;
public class ChannelFragment extends BaseListInfoFragment<ChannelInfo> public class ChannelFragment extends BaseListInfoFragment<ChannelInfo>
implements View.OnClickListener { implements View.OnClickListener {
private static final int BUTTON_DEBOUNCE_INTERVAL = 100; private static final int BUTTON_DEBOUNCE_INTERVAL = 100;
private static final String PICASSO_CHANNEL_TAG = "PICASSO_CHANNEL_TAG";
private final CompositeDisposable disposables = new CompositeDisposable(); private final CompositeDisposable disposables = new CompositeDisposable();
private Disposable subscribeButtonMonitor; private Disposable subscribeButtonMonitor;
@ -421,10 +424,7 @@ public class ChannelFragment extends BaseListInfoFragment<ChannelInfo>
@Override @Override
public void showLoading() { public void showLoading() {
super.showLoading(); super.showLoading();
PicassoHelper.cancelTag(PICASSO_CHANNEL_TAG);
IMAGE_LOADER.cancelDisplayTask(headerBinding.channelBannerImage);
IMAGE_LOADER.cancelDisplayTask(headerBinding.channelAvatarView);
IMAGE_LOADER.cancelDisplayTask(headerBinding.subChannelAvatarView);
animate(headerBinding.channelSubscribeButton, false, 100); animate(headerBinding.channelSubscribeButton, false, 100);
} }
@ -433,13 +433,12 @@ public class ChannelFragment extends BaseListInfoFragment<ChannelInfo>
super.handleResult(result); super.handleResult(result);
headerBinding.getRoot().setVisibility(View.VISIBLE); headerBinding.getRoot().setVisibility(View.VISIBLE);
IMAGE_LOADER.displayImage(result.getBannerUrl(), headerBinding.channelBannerImage, PicassoHelper.loadBanner(result.getBannerUrl()).tag(PICASSO_CHANNEL_TAG)
ImageDisplayConstants.DISPLAY_BANNER_OPTIONS); .into(headerBinding.channelBannerImage);
IMAGE_LOADER.displayImage(result.getAvatarUrl(), headerBinding.channelAvatarView, PicassoHelper.loadAvatar(result.getAvatarUrl()).tag(PICASSO_CHANNEL_TAG)
ImageDisplayConstants.DISPLAY_AVATAR_OPTIONS); .into(headerBinding.channelAvatarView);
IMAGE_LOADER.displayImage(result.getParentChannelAvatarUrl(), PicassoHelper.loadAvatar(result.getParentChannelAvatarUrl()).tag(PICASSO_CHANNEL_TAG)
headerBinding.subChannelAvatarView, .into(headerBinding.subChannelAvatarView);
ImageDisplayConstants.DISPLAY_AVATAR_OPTIONS);
headerBinding.channelSubscriberView.setVisibility(View.VISIBLE); headerBinding.channelSubscriberView.setVisibility(View.VISIBLE);
if (result.getSubscriberCount() >= 0) { if (result.getSubscriberCount() >= 0) {

View File

@ -41,7 +41,7 @@ import org.schabi.newpipe.player.helper.PlayerHolder;
import org.schabi.newpipe.player.playqueue.PlayQueue; import org.schabi.newpipe.player.playqueue.PlayQueue;
import org.schabi.newpipe.player.playqueue.PlaylistPlayQueue; import org.schabi.newpipe.player.playqueue.PlaylistPlayQueue;
import org.schabi.newpipe.util.ExtractorHelper; import org.schabi.newpipe.util.ExtractorHelper;
import org.schabi.newpipe.util.ImageDisplayConstants; import org.schabi.newpipe.util.PicassoHelper;
import org.schabi.newpipe.util.external_communication.KoreUtils; import org.schabi.newpipe.util.external_communication.KoreUtils;
import org.schabi.newpipe.util.Localization; import org.schabi.newpipe.util.Localization;
import org.schabi.newpipe.util.NavigationHelper; import org.schabi.newpipe.util.NavigationHelper;
@ -64,12 +64,16 @@ import static org.schabi.newpipe.ktx.ViewUtils.animate;
import static org.schabi.newpipe.ktx.ViewUtils.animateHideRecyclerViewAllowingScrolling; import static org.schabi.newpipe.ktx.ViewUtils.animateHideRecyclerViewAllowingScrolling;
public class PlaylistFragment extends BaseListInfoFragment<PlaylistInfo> { public class PlaylistFragment extends BaseListInfoFragment<PlaylistInfo> {
private static final String PICASSO_PLAYLIST_TAG = "PICASSO_PLAYLIST_TAG";
private CompositeDisposable disposables; private CompositeDisposable disposables;
private Subscription bookmarkReactor; private Subscription bookmarkReactor;
private AtomicBoolean isBookmarkButtonReady; private AtomicBoolean isBookmarkButtonReady;
private RemotePlaylistManager remotePlaylistManager; private RemotePlaylistManager remotePlaylistManager;
private PlaylistRemoteEntity playlistEntity; private PlaylistRemoteEntity playlistEntity;
/*////////////////////////////////////////////////////////////////////////// /*//////////////////////////////////////////////////////////////////////////
// Views // Views
//////////////////////////////////////////////////////////////////////////*/ //////////////////////////////////////////////////////////////////////////*/
@ -274,7 +278,7 @@ public class PlaylistFragment extends BaseListInfoFragment<PlaylistInfo> {
animate(headerBinding.getRoot(), false, 200); animate(headerBinding.getRoot(), false, 200);
animateHideRecyclerViewAllowingScrolling(itemsList); animateHideRecyclerViewAllowingScrolling(itemsList);
IMAGE_LOADER.cancelDisplayTask(headerBinding.uploaderAvatarView); PicassoHelper.cancelTag(PICASSO_PLAYLIST_TAG);
animate(headerBinding.uploaderLayout, false, 200); animate(headerBinding.uploaderLayout, false, 200);
} }
@ -317,8 +321,8 @@ public class PlaylistFragment extends BaseListInfoFragment<PlaylistInfo> {
R.drawable.ic_radio) R.drawable.ic_radio)
); );
} else { } else {
IMAGE_LOADER.displayImage(avatarUrl, headerBinding.uploaderAvatarView, PicassoHelper.loadAvatar(avatarUrl).tag(PICASSO_PLAYLIST_TAG)
ImageDisplayConstants.DISPLAY_AVATAR_OPTIONS); .into(headerBinding.uploaderAvatarView);
} }
headerBinding.playlistStreamCount.setText(Localization headerBinding.playlistStreamCount.setText(Localization

View File

@ -6,8 +6,6 @@ import android.view.ViewGroup;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import com.nostra13.universalimageloader.core.ImageLoader;
import org.schabi.newpipe.extractor.InfoItem; import org.schabi.newpipe.extractor.InfoItem;
import org.schabi.newpipe.extractor.channel.ChannelInfoItem; import org.schabi.newpipe.extractor.channel.ChannelInfoItem;
import org.schabi.newpipe.extractor.comments.CommentsInfoItem; import org.schabi.newpipe.extractor.comments.CommentsInfoItem;
@ -51,7 +49,6 @@ import org.schabi.newpipe.util.OnClickGesture;
public class InfoItemBuilder { public class InfoItemBuilder {
private final Context context; private final Context context;
private final ImageLoader imageLoader = ImageLoader.getInstance();
private OnClickGesture<StreamInfoItem> onStreamSelectedListener; private OnClickGesture<StreamInfoItem> onStreamSelectedListener;
private OnClickGesture<ChannelInfoItem> onChannelSelectedListener; private OnClickGesture<ChannelInfoItem> onChannelSelectedListener;
@ -101,10 +98,6 @@ public class InfoItemBuilder {
return context; return context;
} }
public ImageLoader getImageLoader() {
return imageLoader;
}
public OnClickGesture<StreamInfoItem> getOnStreamSelectedListener() { public OnClickGesture<StreamInfoItem> getOnStreamSelectedListener() {
return onStreamSelectedListener; return onStreamSelectedListener;
} }

View File

@ -3,13 +3,12 @@ package org.schabi.newpipe.info_list
import android.view.View import android.view.View
import android.widget.ImageView import android.widget.ImageView
import android.widget.TextView import android.widget.TextView
import com.nostra13.universalimageloader.core.ImageLoader
import com.xwray.groupie.GroupieViewHolder import com.xwray.groupie.GroupieViewHolder
import com.xwray.groupie.Item import com.xwray.groupie.Item
import org.schabi.newpipe.R import org.schabi.newpipe.R
import org.schabi.newpipe.extractor.stream.StreamSegment import org.schabi.newpipe.extractor.stream.StreamSegment
import org.schabi.newpipe.util.ImageDisplayConstants
import org.schabi.newpipe.util.Localization import org.schabi.newpipe.util.Localization
import org.schabi.newpipe.util.PicassoHelper
class StreamSegmentItem( class StreamSegmentItem(
private val item: StreamSegment, private val item: StreamSegment,
@ -24,10 +23,8 @@ class StreamSegmentItem(
override fun bind(viewHolder: GroupieViewHolder, position: Int) { override fun bind(viewHolder: GroupieViewHolder, position: Int) {
item.previewUrl?.let { item.previewUrl?.let {
ImageLoader.getInstance().displayImage( PicassoHelper.loadThumbnail(it)
it, viewHolder.root.findViewById<ImageView>(R.id.previewImage), .into(viewHolder.root.findViewById<ImageView>(R.id.previewImage))
ImageDisplayConstants.DISPLAY_THUMBNAIL_OPTIONS
)
} }
viewHolder.root.findViewById<TextView>(R.id.textViewTitle).text = item.title viewHolder.root.findViewById<TextView>(R.id.textViewTitle).text = item.title
if (item.channelName == null) { if (item.channelName == null) {

View File

@ -8,7 +8,7 @@ import org.schabi.newpipe.extractor.InfoItem;
import org.schabi.newpipe.extractor.channel.ChannelInfoItem; import org.schabi.newpipe.extractor.channel.ChannelInfoItem;
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.ImageDisplayConstants; import org.schabi.newpipe.util.PicassoHelper;
import org.schabi.newpipe.util.Localization; import org.schabi.newpipe.util.Localization;
import de.hdodenhof.circleimageview.CircleImageView; import de.hdodenhof.circleimageview.CircleImageView;
@ -43,10 +43,7 @@ public class ChannelMiniInfoItemHolder extends InfoItemHolder {
itemTitleView.setText(item.getName()); itemTitleView.setText(item.getName());
itemAdditionalDetailView.setText(getDetailLine(item)); itemAdditionalDetailView.setText(getDetailLine(item));
itemBuilder.getImageLoader() PicassoHelper.loadThumbnail(item.getThumbnailUrl()).into(itemThumbnailView);
.displayImage(item.getThumbnailUrl(),
itemThumbnailView,
ImageDisplayConstants.DISPLAY_THUMBNAIL_OPTIONS);
itemView.setOnClickListener(view -> { itemView.setOnClickListener(view -> {
if (itemBuilder.getOnChannelSelectedListener() != null) { if (itemBuilder.getOnChannelSelectedListener() != null) {

View File

@ -1,6 +1,5 @@
package org.schabi.newpipe.info_list.holder; package org.schabi.newpipe.info_list.holder;
import android.content.SharedPreferences;
import android.text.TextUtils; import android.text.TextUtils;
import android.text.method.LinkMovementMethod; import android.text.method.LinkMovementMethod;
import android.text.style.URLSpan; import android.text.style.URLSpan;
@ -12,7 +11,6 @@ import android.widget.RelativeLayout;
import android.widget.TextView; import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.app.AppCompatActivity;
import androidx.preference.PreferenceManager;
import org.schabi.newpipe.R; import org.schabi.newpipe.R;
import org.schabi.newpipe.error.ErrorActivity; import org.schabi.newpipe.error.ErrorActivity;
@ -22,11 +20,11 @@ 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.CommentTextOnTouchListener; import org.schabi.newpipe.util.CommentTextOnTouchListener;
import org.schabi.newpipe.util.DeviceUtils; import org.schabi.newpipe.util.DeviceUtils;
import org.schabi.newpipe.util.ImageDisplayConstants;
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.TimestampExtractor; import org.schabi.newpipe.util.external_communication.TimestampExtractor;
import org.schabi.newpipe.util.external_communication.ShareUtils; import org.schabi.newpipe.util.external_communication.ShareUtils;
import org.schabi.newpipe.util.PicassoHelper;
import java.util.regex.Matcher; import java.util.regex.Matcher;
@ -38,11 +36,9 @@ public class CommentsMiniInfoItemHolder extends InfoItemHolder {
private static final int COMMENT_DEFAULT_LINES = 2; private static final int COMMENT_DEFAULT_LINES = 2;
private static final int COMMENT_EXPANDED_LINES = 1000; private static final int COMMENT_EXPANDED_LINES = 1000;
private final String downloadThumbnailKey;
private final int commentHorizontalPadding; private final int commentHorizontalPadding;
private final int commentVerticalPadding; private final int commentVerticalPadding;
private SharedPreferences preferences = null;
private final RelativeLayout itemRoot; private final RelativeLayout itemRoot;
public final CircleImageView itemThumbnailView; public final CircleImageView itemThumbnailView;
private final TextView itemContentView; private final TextView itemContentView;
@ -83,9 +79,6 @@ public class CommentsMiniInfoItemHolder extends InfoItemHolder {
itemPublishedTime = itemView.findViewById(R.id.itemPublishedTime); itemPublishedTime = itemView.findViewById(R.id.itemPublishedTime);
itemContentView = itemView.findViewById(R.id.itemCommentContentView); itemContentView = itemView.findViewById(R.id.itemCommentContentView);
downloadThumbnailKey = infoItemBuilder.getContext().
getString(R.string.download_thumbnail_key);
commentHorizontalPadding = (int) infoItemBuilder.getContext() commentHorizontalPadding = (int) infoItemBuilder.getContext()
.getResources().getDimension(R.dimen.comments_horizontal_padding); .getResources().getDimension(R.dimen.comments_horizontal_padding);
commentVerticalPadding = (int) infoItemBuilder.getContext() commentVerticalPadding = (int) infoItemBuilder.getContext()
@ -105,14 +98,8 @@ public class CommentsMiniInfoItemHolder extends InfoItemHolder {
} }
final CommentsInfoItem item = (CommentsInfoItem) infoItem; final CommentsInfoItem item = (CommentsInfoItem) infoItem;
preferences = PreferenceManager.getDefaultSharedPreferences(itemBuilder.getContext()); PicassoHelper.loadAvatar(item.getUploaderAvatarUrl()).into(itemThumbnailView);
if (PicassoHelper.getShouldLoadImages()) {
itemBuilder.getImageLoader()
.displayImage(item.getUploaderAvatarUrl(),
itemThumbnailView,
ImageDisplayConstants.DISPLAY_THUMBNAIL_OPTIONS);
if (preferences.getBoolean(downloadThumbnailKey, true)) {
itemThumbnailView.setVisibility(View.VISIBLE); itemThumbnailView.setVisibility(View.VISIBLE);
itemRoot.setPadding(commentVerticalPadding, commentVerticalPadding, itemRoot.setPadding(commentVerticalPadding, commentVerticalPadding,
commentVerticalPadding, commentVerticalPadding); commentVerticalPadding, commentVerticalPadding);

View File

@ -9,7 +9,7 @@ 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.ImageDisplayConstants; import org.schabi.newpipe.util.PicassoHelper;
import org.schabi.newpipe.util.Localization; import org.schabi.newpipe.util.Localization;
public class PlaylistMiniInfoItemHolder extends InfoItemHolder { public class PlaylistMiniInfoItemHolder extends InfoItemHolder {
@ -46,9 +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());
itemBuilder.getImageLoader() PicassoHelper.loadPlaylistThumbnail(item.getThumbnailUrl()).into(itemThumbnailView);
.displayImage(item.getThumbnailUrl(), itemThumbnailView,
ImageDisplayConstants.DISPLAY_THUMBNAIL_OPTIONS);
itemView.setOnClickListener(view -> { itemView.setOnClickListener(view -> {
if (itemBuilder.getOnPlaylistSelectedListener() != null) { if (itemBuilder.getOnPlaylistSelectedListener() != null) {

View File

@ -15,7 +15,7 @@ import org.schabi.newpipe.extractor.stream.StreamType;
import org.schabi.newpipe.info_list.InfoItemBuilder; import org.schabi.newpipe.info_list.InfoItemBuilder;
import org.schabi.newpipe.ktx.ViewUtils; 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.ImageDisplayConstants; import org.schabi.newpipe.util.PicassoHelper;
import org.schabi.newpipe.util.Localization; import org.schabi.newpipe.util.Localization;
import org.schabi.newpipe.views.AnimatedProgressBar; import org.schabi.newpipe.views.AnimatedProgressBar;
@ -83,10 +83,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
itemBuilder.getImageLoader() PicassoHelper.loadThumbnail(item.getThumbnailUrl()).into(itemThumbnailView);
.displayImage(item.getThumbnailUrl(),
itemThumbnailView,
ImageDisplayConstants.DISPLAY_THUMBNAIL_OPTIONS);
itemView.setOnClickListener(view -> { itemView.setOnClickListener(view -> {
if (itemBuilder.getOnStreamSelectedListener() != null) { if (itemBuilder.getOnStreamSelectedListener() != null) {

View File

@ -1,10 +1,6 @@
package org.schabi.newpipe.local; package org.schabi.newpipe.local;
import android.content.Context; import android.content.Context;
import android.widget.ImageView;
import com.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.ImageLoader;
import org.schabi.newpipe.database.LocalItem; import org.schabi.newpipe.database.LocalItem;
import org.schabi.newpipe.util.OnClickGesture; import org.schabi.newpipe.util.OnClickGesture;
@ -31,7 +27,6 @@ import org.schabi.newpipe.util.OnClickGesture;
public class LocalItemBuilder { public class LocalItemBuilder {
private final Context context; private final Context context;
private final ImageLoader imageLoader = ImageLoader.getInstance();
private OnClickGesture<LocalItem> onSelectedListener; private OnClickGesture<LocalItem> onSelectedListener;
@ -43,11 +38,6 @@ public class LocalItemBuilder {
return context; return context;
} }
public void displayImage(final String url, final ImageView view,
final DisplayImageOptions options) {
imageLoader.displayImage(url, view, options);
}
public OnClickGesture<LocalItem> getOnItemSelectedListener() { public OnClickGesture<LocalItem> getOnItemSelectedListener() {
return onSelectedListener; return onSelectedListener;
} }

View File

@ -5,7 +5,6 @@ import android.text.TextUtils
import android.view.View import android.view.View
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.preference.PreferenceManager import androidx.preference.PreferenceManager
import com.nostra13.universalimageloader.core.ImageLoader
import com.xwray.groupie.viewbinding.BindableItem import com.xwray.groupie.viewbinding.BindableItem
import org.schabi.newpipe.MainActivity import org.schabi.newpipe.MainActivity
import org.schabi.newpipe.R import org.schabi.newpipe.R
@ -16,8 +15,8 @@ import org.schabi.newpipe.extractor.stream.StreamType.AUDIO_LIVE_STREAM
import org.schabi.newpipe.extractor.stream.StreamType.AUDIO_STREAM import org.schabi.newpipe.extractor.stream.StreamType.AUDIO_STREAM
import org.schabi.newpipe.extractor.stream.StreamType.LIVE_STREAM import org.schabi.newpipe.extractor.stream.StreamType.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.ImageDisplayConstants
import org.schabi.newpipe.util.Localization import org.schabi.newpipe.util.Localization
import org.schabi.newpipe.util.PicassoHelper
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
data class StreamItem( data class StreamItem(
@ -93,10 +92,7 @@ data class StreamItem(
viewBinding.itemProgressView.visibility = View.GONE viewBinding.itemProgressView.visibility = View.GONE
} }
ImageLoader.getInstance().displayImage( PicassoHelper.loadThumbnail(stream.thumbnailUrl).into(viewBinding.itemThumbnailView)
stream.thumbnailUrl, viewBinding.itemThumbnailView,
ImageDisplayConstants.DISPLAY_THUMBNAIL_OPTIONS
)
if (itemVersion != ItemVersion.MINI) { if (itemVersion != ItemVersion.MINI) {
viewBinding.itemAdditionalDetails.text = viewBinding.itemAdditionalDetails.text =

View File

@ -7,7 +7,7 @@ import org.schabi.newpipe.database.LocalItem;
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.ImageDisplayConstants; import org.schabi.newpipe.util.PicassoHelper;
import org.schabi.newpipe.util.Localization; import org.schabi.newpipe.util.Localization;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
@ -36,8 +36,7 @@ public class LocalPlaylistItemHolder extends PlaylistItemHolder {
itemStreamCountView.getContext(), item.streamCount)); itemStreamCountView.getContext(), item.streamCount));
itemUploaderView.setVisibility(View.INVISIBLE); itemUploaderView.setVisibility(View.INVISIBLE);
itemBuilder.displayImage(item.thumbnailUrl, itemThumbnailView, PicassoHelper.loadPlaylistThumbnail(item.thumbnailUrl).into(itemThumbnailView);
ImageDisplayConstants.DISPLAY_PLAYLIST_OPTIONS);
super.updateFromItem(localItem, historyRecordManager, dateTimeFormatter); super.updateFromItem(localItem, historyRecordManager, dateTimeFormatter);
} }

View File

@ -15,7 +15,7 @@ import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.ktx.ViewUtils; import org.schabi.newpipe.ktx.ViewUtils;
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.ImageDisplayConstants; import org.schabi.newpipe.util.PicassoHelper;
import org.schabi.newpipe.util.Localization; import org.schabi.newpipe.util.Localization;
import org.schabi.newpipe.views.AnimatedProgressBar; import org.schabi.newpipe.views.AnimatedProgressBar;
@ -81,8 +81,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
itemBuilder.displayImage(item.getStreamEntity().getThumbnailUrl(), itemThumbnailView, PicassoHelper.loadThumbnail(item.getStreamEntity().getThumbnailUrl())
ImageDisplayConstants.DISPLAY_THUMBNAIL_OPTIONS); .into(itemThumbnailView);
itemView.setOnClickListener(view -> { itemView.setOnClickListener(view -> {
if (itemBuilder.getOnItemSelectedListener() != null) { if (itemBuilder.getOnItemSelectedListener() != null) {

View File

@ -15,7 +15,7 @@ import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.ktx.ViewUtils; import org.schabi.newpipe.ktx.ViewUtils;
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.ImageDisplayConstants; import org.schabi.newpipe.util.PicassoHelper;
import org.schabi.newpipe.util.Localization; import org.schabi.newpipe.util.Localization;
import org.schabi.newpipe.views.AnimatedProgressBar; import org.schabi.newpipe.views.AnimatedProgressBar;
@ -114,8 +114,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
itemBuilder.displayImage(item.getStreamEntity().getThumbnailUrl(), itemThumbnailView, PicassoHelper.loadThumbnail(item.getStreamEntity().getThumbnailUrl())
ImageDisplayConstants.DISPLAY_THUMBNAIL_OPTIONS); .into(itemThumbnailView);
itemView.setOnClickListener(view -> { itemView.setOnClickListener(view -> {
if (itemBuilder.getOnItemSelectedListener() != null) { if (itemBuilder.getOnItemSelectedListener() != null) {

View File

@ -8,7 +8,7 @@ import org.schabi.newpipe.database.playlist.model.PlaylistRemoteEntity;
import org.schabi.newpipe.extractor.NewPipe; import org.schabi.newpipe.extractor.NewPipe;
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.ImageDisplayConstants; import org.schabi.newpipe.util.PicassoHelper;
import org.schabi.newpipe.util.Localization; import org.schabi.newpipe.util.Localization;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
@ -44,9 +44,7 @@ public class RemotePlaylistItemHolder extends PlaylistItemHolder {
itemUploaderView.setText(NewPipe.getNameOfService(item.getServiceId())); itemUploaderView.setText(NewPipe.getNameOfService(item.getServiceId()));
} }
PicassoHelper.loadPlaylistThumbnail(item.getThumbnailUrl()).into(itemThumbnailView);
itemBuilder.displayImage(item.getThumbnailUrl(), itemThumbnailView,
ImageDisplayConstants.DISPLAY_PLAYLIST_OPTIONS);
super.updateFromItem(localItem, historyRecordManager, dateTimeFormatter); super.updateFromItem(localItem, historyRecordManager, dateTimeFormatter);
} }

View File

@ -3,14 +3,13 @@ package org.schabi.newpipe.local.subscription.item
import android.content.Context import android.content.Context
import android.widget.ImageView import android.widget.ImageView
import android.widget.TextView import android.widget.TextView
import com.nostra13.universalimageloader.core.ImageLoader
import com.xwray.groupie.GroupieViewHolder import com.xwray.groupie.GroupieViewHolder
import com.xwray.groupie.Item import com.xwray.groupie.Item
import org.schabi.newpipe.R import org.schabi.newpipe.R
import org.schabi.newpipe.extractor.channel.ChannelInfoItem import org.schabi.newpipe.extractor.channel.ChannelInfoItem
import org.schabi.newpipe.util.ImageDisplayConstants
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.PicassoHelper
class ChannelItem( class ChannelItem(
private val infoItem: ChannelInfoItem, private val infoItem: ChannelInfoItem,
@ -40,10 +39,7 @@ class ChannelItem(
itemChannelDescriptionView.text = infoItem.description itemChannelDescriptionView.text = infoItem.description
} }
ImageLoader.getInstance().displayImage( PicassoHelper.loadThumbnail(infoItem.thumbnailUrl).into(itemThumbnailView)
infoItem.thumbnailUrl, itemThumbnailView,
ImageDisplayConstants.DISPLAY_THUMBNAIL_OPTIONS
)
gesturesListener?.run { gesturesListener?.run {
viewHolder.root.setOnClickListener { selected(infoItem) } viewHolder.root.setOnClickListener { selected(infoItem) }

View File

@ -3,7 +3,6 @@ package org.schabi.newpipe.local.subscription.item
import android.view.View import android.view.View
import androidx.core.view.isGone import androidx.core.view.isGone
import androidx.core.view.isVisible import androidx.core.view.isVisible
import com.nostra13.universalimageloader.core.ImageLoader
import com.xwray.groupie.viewbinding.BindableItem import com.xwray.groupie.viewbinding.BindableItem
import com.xwray.groupie.viewbinding.GroupieViewHolder import com.xwray.groupie.viewbinding.GroupieViewHolder
import org.schabi.newpipe.R import org.schabi.newpipe.R
@ -11,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.ImageDisplayConstants import org.schabi.newpipe.util.PicassoHelper
data class PickerSubscriptionItem( data class PickerSubscriptionItem(
val subscriptionEntity: SubscriptionEntity, val subscriptionEntity: SubscriptionEntity,
@ -22,11 +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) {
ImageLoader.getInstance().displayImage( PicassoHelper.loadAvatar(subscriptionEntity.avatarUrl).into(viewBinding.thumbnailView)
subscriptionEntity.avatarUrl,
viewBinding.thumbnailView, ImageDisplayConstants.DISPLAY_AVATAR_OPTIONS
)
viewBinding.titleView.text = subscriptionEntity.name viewBinding.titleView.text = subscriptionEntity.name
viewBinding.selectedHighlight.isVisible = isSelected viewBinding.selectedHighlight.isVisible = isSelected
} }

View File

@ -18,6 +18,7 @@ import android.graphics.BitmapFactory;
import android.graphics.Color; import android.graphics.Color;
import android.graphics.PorterDuff; import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter; import android.graphics.PorterDuffColorFilter;
import android.graphics.drawable.Drawable;
import android.media.AudioManager; import android.media.AudioManager;
import android.net.Uri; import android.net.Uri;
import android.os.Build; import android.os.Build;
@ -82,9 +83,9 @@ import com.google.android.exoplayer2.upstream.DefaultBandwidthMeter;
import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.util.Util;
import com.google.android.exoplayer2.video.VideoListener; import com.google.android.exoplayer2.video.VideoListener;
import com.google.android.material.floatingactionbutton.FloatingActionButton; import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.nostra13.universalimageloader.core.ImageLoader; import com.squareup.picasso.Picasso;
import com.nostra13.universalimageloader.core.assist.FailReason; import com.squareup.picasso.Target;
import com.nostra13.universalimageloader.core.listener.ImageLoadingListener; import com.squareup.picasso.Transformation;
import org.schabi.newpipe.DownloaderImpl; import org.schabi.newpipe.DownloaderImpl;
import org.schabi.newpipe.MainActivity; import org.schabi.newpipe.MainActivity;
@ -128,11 +129,11 @@ import org.schabi.newpipe.player.resolver.VideoPlaybackResolver;
import org.schabi.newpipe.player.seekbarpreview.SeekbarPreviewThumbnailHelper; import org.schabi.newpipe.player.seekbarpreview.SeekbarPreviewThumbnailHelper;
import org.schabi.newpipe.player.seekbarpreview.SeekbarPreviewThumbnailHolder; import org.schabi.newpipe.player.seekbarpreview.SeekbarPreviewThumbnailHolder;
import org.schabi.newpipe.util.DeviceUtils; import org.schabi.newpipe.util.DeviceUtils;
import org.schabi.newpipe.util.ImageDisplayConstants; import org.schabi.newpipe.util.external_communication.KoreUtils;
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.PicassoHelper;
import org.schabi.newpipe.util.SerializedCache; import org.schabi.newpipe.util.SerializedCache;
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.views.ExpandableSurfaceView; import org.schabi.newpipe.views.ExpandableSurfaceView;
@ -196,7 +197,6 @@ import static org.schabi.newpipe.util.Localization.containsCaseInsensitive;
public final class Player implements public final class Player implements
EventListener, EventListener,
PlaybackListener, PlaybackListener,
ImageLoadingListener,
VideoListener, VideoListener,
SeekBar.OnSeekBarChangeListener, SeekBar.OnSeekBarChangeListener,
View.OnClickListener, View.OnClickListener,
@ -250,6 +250,9 @@ public final class Player implements
private static final int RENDERER_UNAVAILABLE = -1; private static final int RENDERER_UNAVAILABLE = -1;
private static final String PICASSO_PLAYER_TAG = "PICASSO_PLAYER_TAG";
private static final String PICASSO_TRANSFORMATION_KEY = "PICASSO_TRANSFORMATION_KEY";
/*////////////////////////////////////////////////////////////////////////// /*//////////////////////////////////////////////////////////////////////////
// Playback // Playback
//////////////////////////////////////////////////////////////////////////*/ //////////////////////////////////////////////////////////////////////////*/
@ -820,7 +823,7 @@ public final class Player implements
databaseUpdateDisposable.clear(); databaseUpdateDisposable.clear();
progressUpdateDisposable.set(null); progressUpdateDisposable.set(null);
ImageLoader.getInstance().stop(); PicassoHelper.cancelTag(PICASSO_PLAYER_TAG);
if (binding != null) { if (binding != null) {
binding.endScreen.setImageBitmap(null); binding.endScreen.setImageBitmap(null);
@ -1215,14 +1218,71 @@ public final class Player implements
private void initThumbnail(final String url) { private void initThumbnail(final String url) {
if (DEBUG) { if (DEBUG) {
Log.d(TAG, "Thumbnail - initThumbnail() called"); Log.d(TAG, "Thumbnail - initThumbnail() called with url = ["
+ (url == null ? "null" : url) + "]");
} }
if (url == null || url.isEmpty()) { if (url == null || url.isEmpty()) {
return; return;
} }
ImageLoader.getInstance().resume();
ImageLoader.getInstance() // scale down the notification thumbnail for performance
.loadImage(url, ImageDisplayConstants.DISPLAY_THUMBNAIL_OPTIONS, this); PicassoHelper.loadThumbnail(url)
.tag(PICASSO_PLAYER_TAG)
.transform(new Transformation() {
@Override
public Bitmap transform(final Bitmap source) {
final float notificationThumbnailWidth = Math.min(
context.getResources()
.getDimension(R.dimen.player_notification_thumbnail_width),
source.getWidth());
return Bitmap.createScaledBitmap(
source,
(int) notificationThumbnailWidth,
(int) (source.getHeight()
/ (source.getWidth() / notificationThumbnailWidth)),
true);
}
@Override
public String key() {
return PICASSO_TRANSFORMATION_KEY;
}
})
.into(new Target() {
@Override
public void onBitmapLoaded(final Bitmap bitmap, final Picasso.LoadedFrom from) {
if (DEBUG) {
Log.d(TAG, "Thumbnail - onLoadingComplete() called with: "
+ "url = [" + url + "], " + "loadedImage = [" + bitmap + " -> "
+ bitmap.getWidth() + "x" + bitmap.getHeight()
+ "], from = [" + from + "]");
}
currentThumbnail = bitmap;
NotificationUtil.getInstance()
.createNotificationIfNeededAndUpdate(Player.this, false);
// there is a new thumbnail, so changed the end screen thumbnail, too.
updateEndScreenThumbnail();
}
@Override
public void onBitmapFailed(final Exception e, final Drawable errorDrawable) {
Log.e(TAG, "Thumbnail - onBitmapFailed() called with: url = ["
+ url + "]", e);
currentThumbnail = null;
NotificationUtil.getInstance()
.createNotificationIfNeededAndUpdate(Player.this, false);
}
@Override
public void onPrepareLoad(final Drawable placeHolderDrawable) {
if (DEBUG) {
Log.d(TAG, "Thumbnail - onLoadingStarted() called with: url = ["
+ url + "]");
}
}
});
} }
/** /**
@ -1296,61 +1356,6 @@ public final class Player implements
return Math.min(currentThumbnail.getHeight(), screenHeight); return Math.min(currentThumbnail.getHeight(), screenHeight);
} }
} }
@Override
public void onLoadingStarted(final String imageUri, final View view) {
if (DEBUG) {
Log.d(TAG, "Thumbnail - onLoadingStarted() called on: "
+ "imageUri = [" + imageUri + "], view = [" + view + "]");
}
}
@Override
public void onLoadingFailed(final String imageUri, final View view,
final FailReason failReason) {
Log.e(TAG, "Thumbnail - onLoadingFailed() called on imageUri = [" + imageUri + "]",
failReason.getCause());
currentThumbnail = null;
NotificationUtil.getInstance().createNotificationIfNeededAndUpdate(this, false);
}
@Override
public void onLoadingComplete(final String imageUri, final View view,
final Bitmap loadedImage) {
// scale down the notification thumbnail for performance
final float notificationThumbnailWidth = Math.min(
context.getResources().getDimension(R.dimen.player_notification_thumbnail_width),
loadedImage.getWidth());
currentThumbnail = Bitmap.createScaledBitmap(
loadedImage,
(int) notificationThumbnailWidth,
(int) (loadedImage.getHeight()
/ (loadedImage.getWidth() / notificationThumbnailWidth)),
true);
if (DEBUG) {
Log.d(TAG, "Thumbnail - onLoadingComplete() called with: "
+ "imageUri = [" + imageUri + "], view = [" + view + "], "
+ "loadedImage = [" + loadedImage + "], "
+ loadedImage.getWidth() + "x" + loadedImage.getHeight()
+ ", scaled notification width = " + notificationThumbnailWidth);
}
NotificationUtil.getInstance().createNotificationIfNeededAndUpdate(this, false);
// there is a new thumbnail, thus the end screen thumbnail needs to be changed, too.
updateEndScreenThumbnail();
}
@Override
public void onLoadingCancelled(final String imageUri, final View view) {
if (DEBUG) {
Log.d(TAG, "Thumbnail - onLoadingCancelled() called with: "
+ "imageUri = [" + imageUri + "], view = [" + view + "]");
}
currentThumbnail = null;
NotificationUtil.getInstance().createNotificationIfNeededAndUpdate(this, false);
}
//endregion //endregion

View File

@ -5,11 +5,9 @@ import android.text.TextUtils;
import android.view.MotionEvent; import android.view.MotionEvent;
import android.view.View; import android.view.View;
import com.nostra13.universalimageloader.core.ImageLoader;
import org.schabi.newpipe.extractor.NewPipe; import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.util.ImageDisplayConstants;
import org.schabi.newpipe.util.Localization; import org.schabi.newpipe.util.Localization;
import org.schabi.newpipe.util.PicassoHelper;
public class PlayQueueItemBuilder { public class PlayQueueItemBuilder {
private static final String TAG = PlayQueueItemBuilder.class.toString(); private static final String TAG = PlayQueueItemBuilder.class.toString();
@ -35,8 +33,7 @@ public class PlayQueueItemBuilder {
holder.itemDurationView.setVisibility(View.GONE); holder.itemDurationView.setVisibility(View.GONE);
} }
ImageLoader.getInstance().displayImage(item.getThumbnailUrl(), holder.itemThumbnailView, PicassoHelper.loadThumbnail(item.getThumbnailUrl()).into(holder.itemThumbnailView);
ImageDisplayConstants.DISPLAY_THUMBNAIL_OPTIONS);
holder.itemRoot.setOnClickListener(view -> { holder.itemRoot.setOnClickListener(view -> {
if (onItemClickListener != null) { if (onItemClickListener != null) {

View File

@ -1,16 +1,18 @@
package org.schabi.newpipe.player.seekbarpreview; package org.schabi.newpipe.player.seekbarpreview;
import static org.schabi.newpipe.player.seekbarpreview.SeekbarPreviewThumbnailHelper.SeekbarPreviewThumbnailType;
import android.content.Context; import android.content.Context;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.util.Log; import android.util.Log;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.google.common.base.Stopwatch; import com.google.common.base.Stopwatch;
import com.nostra13.universalimageloader.core.ImageLoader;
import org.schabi.newpipe.extractor.stream.Frameset; import org.schabi.newpipe.extractor.stream.Frameset;
import org.schabi.newpipe.util.ImageDisplayConstants; import org.schabi.newpipe.util.PicassoHelper;
import java.util.Comparator; import java.util.Comparator;
import java.util.HashMap; import java.util.HashMap;
@ -21,11 +23,8 @@ import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.function.Supplier; import java.util.function.Supplier;
import static org.schabi.newpipe.player.seekbarpreview.SeekbarPreviewThumbnailHelper.SeekbarPreviewThumbnailType;
public class SeekbarPreviewThumbnailHolder { public class SeekbarPreviewThumbnailHolder {
// This has to be <= 23 chars on devices running Android 7 or lower (API <= 25) // This has to be <= 23 chars on devices running Android 7 or lower (API <= 25)
@ -174,6 +173,7 @@ public class SeekbarPreviewThumbnailHolder {
} }
} }
@Nullable
private Bitmap getBitMapFrom(final String url) { private Bitmap getBitMapFrom(final String url) {
if (url == null) { if (url == null) {
Log.w(TAG, "url is null; This should never happen"); Log.w(TAG, "url is null; This should never happen");
@ -182,24 +182,11 @@ public class SeekbarPreviewThumbnailHolder {
final Stopwatch sw = Log.isLoggable(TAG, Log.DEBUG) ? Stopwatch.createStarted() : null; final Stopwatch sw = Log.isLoggable(TAG, Log.DEBUG) ? Stopwatch.createStarted() : null;
try { try {
final SyncImageLoadingListener syncImageLoadingListener =
new SyncImageLoadingListener();
Log.d(TAG, "Downloading bitmap for seekbarPreview from '" + url + "'"); Log.d(TAG, "Downloading bitmap for seekbarPreview from '" + url + "'");
// Ensure that everything is running // Gets the bitmap within the timeout of 15 seconds imposed by default by OkHttpClient
ImageLoader.getInstance().resume();
// Load the image
// Impl-Note:
// Ensure that your are not running on the main-Thread this will otherwise hang // Ensure that your are not running on the main-Thread this will otherwise hang
ImageLoader.getInstance().loadImage( final Bitmap bitmap = PicassoHelper.loadSeekbarThumbnailPreview(url).get();
url,
ImageDisplayConstants.DISPLAY_SEEKBAR_PREVIEW_OPTIONS,
syncImageLoadingListener);
// Get the bitmap within the timeout
final Bitmap bitmap =
syncImageLoadingListener.waitForBitmapOrThrow(30, TimeUnit.SECONDS);
if (sw != null) { if (sw != null) {
Log.d(TAG, Log.d(TAG,

View File

@ -1,87 +0,0 @@
package org.schabi.newpipe.player.seekbarpreview;
import android.graphics.Bitmap;
import android.view.View;
import com.nostra13.universalimageloader.core.assist.FailReason;
import com.nostra13.universalimageloader.core.listener.SimpleImageLoadingListener;
import java.util.concurrent.CancellationException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
/**
* Listener for synchronously downloading of an image/bitmap.
*/
public class SyncImageLoadingListener extends SimpleImageLoadingListener {
private final CountDownLatch countDownLatch = new CountDownLatch(1);
private Bitmap bitmap;
private boolean cancelled = false;
private FailReason failReason = null;
@SuppressWarnings("checkstyle:HiddenField")
@Override
public void onLoadingFailed(
final String imageUri,
final View view,
final FailReason failReason) {
this.failReason = failReason;
countDownLatch.countDown();
}
@Override
public void onLoadingComplete(
final String imageUri,
final View view,
final Bitmap loadedImage) {
bitmap = loadedImage;
countDownLatch.countDown();
}
@Override
public void onLoadingCancelled(final String imageUri, final View view) {
cancelled = true;
countDownLatch.countDown();
}
public Bitmap waitForBitmapOrThrow(final long timeout, final TimeUnit timeUnit)
throws InterruptedException, TimeoutException {
// Wait for the download to finish
if (!countDownLatch.await(timeout, timeUnit)) {
throw new TimeoutException("Couldn't get the image in time");
}
if (isCancelled()) {
throw new CancellationException("Download of image was cancelled");
}
if (getFailReason() != null) {
throw new RuntimeException("Failed to download image" + getFailReason().getType(),
getFailReason().getCause());
}
if (getBitmap() == null) {
throw new NullPointerException("Bitmap is null");
}
return getBitmap();
}
public Bitmap getBitmap() {
return bitmap;
}
public boolean isCancelled() {
return cancelled;
}
public FailReason getFailReason() {
return failReason;
}
}

View File

@ -17,8 +17,6 @@ import androidx.core.content.ContextCompat;
import androidx.preference.Preference; import androidx.preference.Preference;
import androidx.preference.PreferenceManager; import androidx.preference.PreferenceManager;
import com.nostra13.universalimageloader.core.ImageLoader;
import org.schabi.newpipe.DownloaderImpl; import org.schabi.newpipe.DownloaderImpl;
import org.schabi.newpipe.NewPipeDatabase; import org.schabi.newpipe.NewPipeDatabase;
import org.schabi.newpipe.R; import org.schabi.newpipe.R;
@ -29,6 +27,7 @@ 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.streams.io.StoredFileHelper; import org.schabi.newpipe.streams.io.StoredFileHelper;
import org.schabi.newpipe.util.NavigationHelper; import org.schabi.newpipe.util.NavigationHelper;
import org.schabi.newpipe.util.PicassoHelper;
import org.schabi.newpipe.util.ZipHelper; import org.schabi.newpipe.util.ZipHelper;
import java.io.File; import java.io.File;
@ -50,7 +49,6 @@ public class ContentSettingsFragment extends BasePreferenceFragment {
private ContentSettingsManager manager; private ContentSettingsManager manager;
private String importExportDataPathKey; private String importExportDataPathKey;
private String thumbnailLoadToggleKey;
private String youtubeRestrictedModeEnabledKey; private String youtubeRestrictedModeEnabledKey;
private Localization initialSelectedLocalization; private Localization initialSelectedLocalization;
@ -69,7 +67,6 @@ public class ContentSettingsFragment extends BasePreferenceFragment {
manager.deleteSettingsFile(); manager.deleteSettingsFile();
importExportDataPathKey = getString(R.string.import_export_data_path); importExportDataPathKey = getString(R.string.import_export_data_path);
thumbnailLoadToggleKey = getString(R.string.download_thumbnail_key);
youtubeRestrictedModeEnabledKey = getString(R.string.youtube_restricted_mode_enabled); youtubeRestrictedModeEnabledKey = getString(R.string.youtube_restricted_mode_enabled);
addPreferencesFromResource(R.xml.content_settings); addPreferencesFromResource(R.xml.content_settings);
@ -112,20 +109,24 @@ public class ContentSettingsFragment extends BasePreferenceFragment {
if (defaultPreferences.getString(getString(R.string.recaptcha_cookies_key), "").isEmpty()) { if (defaultPreferences.getString(getString(R.string.recaptcha_cookies_key), "").isEmpty()) {
clearCookiePref.setVisible(false); clearCookiePref.setVisible(false);
} }
findPreference(getString(R.string.download_thumbnail_key)).setOnPreferenceChangeListener(
(preference, newValue) -> {
PicassoHelper.setShouldLoadImages((Boolean) 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);
}
return true;
});
} }
@Override @Override
public boolean onPreferenceTreeClick(final Preference preference) { public boolean onPreferenceTreeClick(final Preference preference) {
if (preference.getKey().equals(thumbnailLoadToggleKey)) {
final ImageLoader imageLoader = ImageLoader.getInstance();
imageLoader.stop();
imageLoader.clearDiskCache();
imageLoader.clearMemoryCache();
imageLoader.resume();
Toast.makeText(preference.getContext(), R.string.thumbnail_cache_wipe_complete_notice,
Toast.LENGTH_SHORT).show();
}
if (preference.getKey().equals(youtubeRestrictedModeEnabledKey)) { if (preference.getKey().equals(youtubeRestrictedModeEnabledKey)) {
final Context context = getContext(); final Context context = getContext();
if (context != null) { if (context != null) {

View File

@ -14,13 +14,11 @@ import androidx.fragment.app.DialogFragment;
import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import com.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.ImageLoader;
import org.schabi.newpipe.R; import org.schabi.newpipe.R;
import org.schabi.newpipe.database.subscription.SubscriptionEntity; import org.schabi.newpipe.database.subscription.SubscriptionEntity;
import org.schabi.newpipe.error.ErrorActivity; import org.schabi.newpipe.error.ErrorActivity;
import org.schabi.newpipe.local.subscription.SubscriptionManager; import org.schabi.newpipe.local.subscription.SubscriptionManager;
import org.schabi.newpipe.util.PicassoHelper;
import org.schabi.newpipe.util.ThemeHelper; import org.schabi.newpipe.util.ThemeHelper;
import java.util.List; import java.util.List;
@ -54,13 +52,6 @@ import io.reactivex.rxjava3.schedulers.Schedulers;
*/ */
public class SelectChannelFragment extends DialogFragment { public class SelectChannelFragment extends DialogFragment {
/**
* This contains the base display options for images.
*/
private static final DisplayImageOptions DISPLAY_IMAGE_OPTIONS
= new DisplayImageOptions.Builder().cacheInMemory(true).build();
private final ImageLoader imageLoader = ImageLoader.getInstance();
private OnSelectedListener onSelectedListener = null; private OnSelectedListener onSelectedListener = null;
private OnCancelListener onCancelListener = null; private OnCancelListener onCancelListener = null;
@ -199,8 +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));
imageLoader.displayImage(entry.getAvatarUrl(), holder.thumbnailView, PicassoHelper.loadAvatar(entry.getAvatarUrl()).into(holder.thumbnailView);
DISPLAY_IMAGE_OPTIONS);
} }
@Override @Override

View File

@ -14,9 +14,6 @@ import androidx.fragment.app.DialogFragment;
import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import com.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.ImageLoader;
import org.schabi.newpipe.NewPipeDatabase; import org.schabi.newpipe.NewPipeDatabase;
import org.schabi.newpipe.R; import org.schabi.newpipe.R;
import org.schabi.newpipe.database.AppDatabase; import org.schabi.newpipe.database.AppDatabase;
@ -29,6 +26,7 @@ import org.schabi.newpipe.error.ErrorInfo;
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.PicassoHelper;
import java.util.List; import java.util.List;
import java.util.Vector; import java.util.Vector;
@ -38,13 +36,6 @@ import io.reactivex.rxjava3.core.Flowable;
import io.reactivex.rxjava3.disposables.Disposable; import io.reactivex.rxjava3.disposables.Disposable;
public class SelectPlaylistFragment extends DialogFragment { public class SelectPlaylistFragment extends DialogFragment {
/**
* This contains the base display options for images.
*/
private static final DisplayImageOptions DISPLAY_IMAGE_OPTIONS
= new DisplayImageOptions.Builder().cacheInMemory(true).build();
private final ImageLoader imageLoader = ImageLoader.getInstance();
private OnSelectedListener onSelectedListener = null; private OnSelectedListener onSelectedListener = null;
@ -170,16 +161,15 @@ public class SelectPlaylistFragment extends DialogFragment {
holder.titleView.setText(entry.name); holder.titleView.setText(entry.name);
holder.view.setOnClickListener(view -> clickedItem(position)); holder.view.setOnClickListener(view -> clickedItem(position));
imageLoader.displayImage(entry.thumbnailUrl, holder.thumbnailView, PicassoHelper.loadPlaylistThumbnail(entry.thumbnailUrl).into(holder.thumbnailView);
DISPLAY_IMAGE_OPTIONS);
} else if (selectedItem instanceof PlaylistRemoteEntity) { } else if (selectedItem instanceof PlaylistRemoteEntity) {
final PlaylistRemoteEntity entry = ((PlaylistRemoteEntity) selectedItem); 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));
imageLoader.displayImage(entry.getThumbnailUrl(), holder.thumbnailView, PicassoHelper.loadPlaylistThumbnail(entry.getThumbnailUrl())
DISPLAY_IMAGE_OPTIONS); .into(holder.thumbnailView);
} }
} }

View File

@ -1,65 +0,0 @@
package org.schabi.newpipe.util;
import android.graphics.Bitmap;
import com.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.assist.ImageScaleType;
import com.nostra13.universalimageloader.core.display.FadeInBitmapDisplayer;
import org.schabi.newpipe.R;
public final class ImageDisplayConstants {
private static final int BITMAP_FADE_IN_DURATION_MILLIS = 250;
/**
* This constant contains the base display options.
*/
private static final DisplayImageOptions BASE_DISPLAY_IMAGE_OPTIONS =
new DisplayImageOptions.Builder()
.cacheInMemory(true)
.cacheOnDisk(true)
.resetViewBeforeLoading(true)
.bitmapConfig(Bitmap.Config.RGB_565)
.imageScaleType(ImageScaleType.EXACTLY)
.displayer(new FadeInBitmapDisplayer(BITMAP_FADE_IN_DURATION_MILLIS))
.build();
/*//////////////////////////////////////////////////////////////////////////
// DisplayImageOptions default configurations
//////////////////////////////////////////////////////////////////////////*/
public static final DisplayImageOptions DISPLAY_AVATAR_OPTIONS =
new DisplayImageOptions.Builder()
.cloneFrom(BASE_DISPLAY_IMAGE_OPTIONS)
.showImageForEmptyUri(R.drawable.buddy)
.showImageOnFail(R.drawable.buddy)
.build();
public static final DisplayImageOptions DISPLAY_THUMBNAIL_OPTIONS =
new DisplayImageOptions.Builder()
.cloneFrom(BASE_DISPLAY_IMAGE_OPTIONS)
.showImageForEmptyUri(R.drawable.dummy_thumbnail)
.showImageOnFail(R.drawable.dummy_thumbnail)
.build();
public static final DisplayImageOptions DISPLAY_BANNER_OPTIONS =
new DisplayImageOptions.Builder()
.cloneFrom(BASE_DISPLAY_IMAGE_OPTIONS)
.showImageForEmptyUri(R.drawable.channel_banner)
.showImageOnFail(R.drawable.channel_banner)
.build();
public static final DisplayImageOptions DISPLAY_PLAYLIST_OPTIONS =
new DisplayImageOptions.Builder()
.cloneFrom(BASE_DISPLAY_IMAGE_OPTIONS)
.showImageForEmptyUri(R.drawable.dummy_thumbnail_playlist)
.showImageOnFail(R.drawable.dummy_thumbnail_playlist)
.build();
public static final DisplayImageOptions DISPLAY_SEEKBAR_PREVIEW_OPTIONS =
new DisplayImageOptions.Builder()
.cloneFrom(BASE_DISPLAY_IMAGE_OPTIONS)
.build();
private ImageDisplayConstants() { }
}

View File

@ -18,8 +18,6 @@ import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentTransaction; import androidx.fragment.app.FragmentTransaction;
import com.nostra13.universalimageloader.core.ImageLoader;
import org.schabi.newpipe.MainActivity; import org.schabi.newpipe.MainActivity;
import org.schabi.newpipe.NewPipeDatabase; import org.schabi.newpipe.NewPipeDatabase;
import org.schabi.newpipe.R; import org.schabi.newpipe.R;
@ -259,10 +257,9 @@ public final class NavigationHelper {
if (context instanceof Activity) { if (context instanceof Activity) {
new AlertDialog.Builder(context) new AlertDialog.Builder(context)
.setMessage(R.string.no_player_found) .setMessage(R.string.no_player_found)
.setPositiveButton(R.string.install, (dialog, which) -> { .setPositiveButton(R.string.install,
ShareUtils.openUrlInBrowser(context, (dialog, which) -> ShareUtils.openUrlInBrowser(context,
context.getString(R.string.fdroid_vlc_url), false); context.getString(R.string.fdroid_vlc_url), false))
})
.setNegativeButton(R.string.cancel, (dialog, which) .setNegativeButton(R.string.cancel, (dialog, which)
-> Log.i("NavigationHelper", "You unlocked a secret unicorn.")) -> Log.i("NavigationHelper", "You unlocked a secret unicorn."))
.show(); .show();
@ -284,8 +281,6 @@ public final class NavigationHelper {
} }
public static void gotoMainFragment(final FragmentManager fragmentManager) { public static void gotoMainFragment(final FragmentManager fragmentManager) {
ImageLoader.getInstance().clearMemoryCache();
final boolean popped = fragmentManager.popBackStackImmediate(MAIN_FRAGMENT_TAG, 0); final boolean popped = fragmentManager.popBackStackImmediate(MAIN_FRAGMENT_TAG, 0);
if (!popped) { if (!popped) {
openMainFragment(fragmentManager); openMainFragment(fragmentManager);

View File

@ -0,0 +1,110 @@
package org.schabi.newpipe.util;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Bitmap;
import com.squareup.picasso.Cache;
import com.squareup.picasso.LruCache;
import com.squareup.picasso.OkHttp3Downloader;
import com.squareup.picasso.Picasso;
import com.squareup.picasso.RequestCreator;
import org.schabi.newpipe.R;
import java.io.File;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
import okhttp3.OkHttpClient;
import static org.schabi.newpipe.extractor.utils.Utils.isBlank;
public final class PicassoHelper {
private PicassoHelper() {
}
private static Cache picassoCache;
private static OkHttpClient picassoDownloaderClient;
// suppress because terminate() is called in App.onTerminate(), preventing leaks
@SuppressLint("StaticFieldLeak")
private static Picasso picassoInstance;
private static boolean shouldLoadImages;
public static void init(final Context context) {
picassoCache = new LruCache(10 * 1024 * 1024);
picassoDownloaderClient = new OkHttpClient.Builder()
.cache(new okhttp3.Cache(new File(context.getExternalCacheDir(), "picasso"),
50 * 1024 * 1024))
// this should already be the default timeout in OkHttp3, but just to be sure...
.callTimeout(15, TimeUnit.SECONDS)
.build();
picassoInstance = new Picasso.Builder(context)
.memoryCache(picassoCache) // memory cache
.downloader(new OkHttp3Downloader(picassoDownloaderClient)) // disk cache
.defaultBitmapConfig(Bitmap.Config.RGB_565)
.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
picassoDownloaderClient.cache().delete(); // clear disk cache
init(context);
}
public static void cancelTag(final Object tag) {
picassoInstance.cancelTag(tag);
}
public static void setShouldLoadImages(final boolean shouldLoadImages) {
PicassoHelper.shouldLoadImages = shouldLoadImages;
}
public static boolean getShouldLoadImages() {
return shouldLoadImages;
}
public static RequestCreator loadAvatar(final String url) {
return loadImageDefault(url, R.drawable.buddy);
}
public static RequestCreator loadThumbnail(final String url) {
return loadImageDefault(url, R.drawable.dummy_thumbnail);
}
public static RequestCreator loadBanner(final String url) {
return loadImageDefault(url, R.drawable.channel_banner);
}
public static RequestCreator loadPlaylistThumbnail(final String url) {
return loadImageDefault(url, R.drawable.dummy_thumbnail_playlist);
}
public static RequestCreator loadSeekbarThumbnailPreview(final String url) {
return picassoInstance.load(url);
}
private static RequestCreator loadImageDefault(final String url, final int placeholderResId) {
return picassoInstance
.load((!shouldLoadImages || isBlank(url)) ? null : url)
.placeholder(placeholderResId)
.error(placeholderResId);
}
}