mirror of
				https://github.com/TeamNewPipe/NewPipe
				synced 2025-10-30 23:03:00 +00:00 
			
		
		
		
	Replace UniversalImageLoader with Picasso
This commit is contained in:
		| @@ -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}" | ||||||
|   | |||||||
| @@ -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. | ||||||
|   | |||||||
| @@ -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; | ||||||
|   | |||||||
| @@ -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 { | ||||||
|   | |||||||
| @@ -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); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @@ -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) { | ||||||
|   | |||||||
| @@ -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) { | ||||||
|   | |||||||
| @@ -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 | ||||||
|   | |||||||
| @@ -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; | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -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) { | ||||||
|   | |||||||
| @@ -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) { | ||||||
|   | |||||||
| @@ -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); | ||||||
|   | |||||||
| @@ -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) { | ||||||
|   | |||||||
| @@ -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) { | ||||||
|   | |||||||
| @@ -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; | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -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 = | ||||||
|   | |||||||
| @@ -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); | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -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) { | ||||||
|   | |||||||
| @@ -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) { | ||||||
|   | |||||||
| @@ -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); | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -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) } | ||||||
|   | |||||||
| @@ -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 | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -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 | ||||||
|  |  | ||||||
|  |  | ||||||
|   | |||||||
| @@ -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) { | ||||||
|   | |||||||
| @@ -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, | ||||||
|   | |||||||
| @@ -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; |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @@ -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) { | ||||||
|   | |||||||
| @@ -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 | ||||||
|   | |||||||
| @@ -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); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -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() { } |  | ||||||
| } |  | ||||||
| @@ -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); | ||||||
|   | |||||||
							
								
								
									
										110
									
								
								app/src/main/java/org/schabi/newpipe/util/PicassoHelper.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										110
									
								
								app/src/main/java/org/schabi/newpipe/util/PicassoHelper.java
									
									
									
									
									
										Normal 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); | ||||||
|  |     } | ||||||
|  | } | ||||||
		Reference in New Issue
	
	Block a user
	 Stypox
					Stypox