Skip to content

Commit 5736410

Browse files
committed
Migrate from Picasso to Coil
Based on changes from refactor Signed-off-by: Aayush Gupta <aayushgupta219@gmail.com>
1 parent 273b09a commit 5736410

35 files changed

Lines changed: 432 additions & 512 deletions

app/build.gradle.kts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -272,7 +272,8 @@ dependencies {
272272
implementation(libs.lisawray.groupie.viewbinding)
273273

274274
// Image loading
275-
implementation(libs.squareup.picasso)
275+
implementation(libs.coil.compose)
276+
implementation(libs.coil.network.okhttp)
276277

277278
// Markdown library for Android
278279
implementation(libs.noties.markwon.core)

app/src/main/java/org/schabi/newpipe/App.kt

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,19 @@
11
package org.schabi.newpipe
22

3+
import android.app.ActivityManager
34
import android.app.Application
45
import android.content.Context
56
import android.util.Log
67
import androidx.core.app.NotificationChannelCompat
78
import androidx.core.app.NotificationManagerCompat
9+
import androidx.core.content.getSystemService
810
import androidx.preference.PreferenceManager
11+
import coil3.ImageLoader
12+
import coil3.SingletonImageLoader
13+
import coil3.network.okhttp.OkHttpNetworkFetcherFactory
14+
import coil3.request.allowRgb565
15+
import coil3.request.crossfade
16+
import coil3.util.DebugLogger
917
import com.jakewharton.processphoenix.ProcessPhoenix
1018
import io.reactivex.rxjava3.exceptions.CompositeException
1119
import io.reactivex.rxjava3.exceptions.MissingBackpressureException
@@ -29,9 +37,8 @@ import org.schabi.newpipe.util.BridgeStateSaverInitializer
2937
import org.schabi.newpipe.util.Localization
3038
import org.schabi.newpipe.util.ServiceHelper
3139
import org.schabi.newpipe.util.StateSaver
32-
import org.schabi.newpipe.util.image.ImageStrategy.setPreferredImageQuality
33-
import org.schabi.newpipe.util.image.PicassoHelper
34-
import org.schabi.newpipe.util.image.PreferredImageQuality.Companion.fromPreferenceKey
40+
import org.schabi.newpipe.util.image.ImageStrategy
41+
import org.schabi.newpipe.util.image.PreferredImageQuality
3542
import org.schabi.newpipe.util.potoken.PoTokenProviderImpl
3643

3744
/*
@@ -51,7 +58,9 @@ import org.schabi.newpipe.util.potoken.PoTokenProviderImpl
5158
* You should have received a copy of the GNU General Public License
5259
* along with NewPipe. If not, see <http://www.gnu.org/licenses/>.
5360
*/
54-
open class App : Application() {
61+
open class App :
62+
Application(),
63+
SingletonImageLoader.Factory {
5564
var isFirstRun = false
5665
private set
5766
var notificationsRequested = false
@@ -102,30 +111,29 @@ open class App : Application() {
102111

103112
// Initialize image loader
104113
val prefs = PreferenceManager.getDefaultSharedPreferences(this)
105-
PicassoHelper.init(this)
106-
setPreferredImageQuality(
107-
fromPreferenceKey(
114+
ImageStrategy.setPreferredImageQuality(
115+
PreferredImageQuality.fromPreferenceKey(
108116
this,
109117
prefs.getString(
110118
getString(R.string.image_quality_key),
111119
getString(R.string.image_quality_default)
112120
)
113121
)
114122
)
115-
PicassoHelper.setIndicatorsEnabled(
116-
MainActivity.DEBUG &&
117-
prefs.getBoolean(getString(R.string.show_image_indicators_key), false)
118-
)
119123

120124
configureRxJavaErrorHandler()
121125

122126
YoutubeStreamExtractor.setPoTokenProvider(PoTokenProviderImpl)
123127
}
124128

125-
override fun onTerminate() {
126-
super.onTerminate()
127-
PicassoHelper.terminate()
128-
}
129+
override fun newImageLoader(context: Context): ImageLoader = ImageLoader
130+
.Builder(this)
131+
.logger(if (BuildConfig.DEBUG) DebugLogger() else null)
132+
.allowRgb565(getSystemService<ActivityManager>()!!.isLowRamDevice)
133+
.crossfade(true)
134+
.components {
135+
add(OkHttpNetworkFetcherFactory(callFactory = DownloaderImpl.getInstance().client))
136+
}.build()
129137

130138
protected open fun getDownloader(): Downloader {
131139
val downloader = DownloaderImpl.init(null)

app/src/main/java/org/schabi/newpipe/DownloaderImpl.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,11 @@ private DownloaderImpl(final OkHttpClient.Builder builder) {
4848
this.mCookies = new HashMap<>();
4949
}
5050

51+
@NonNull
52+
public OkHttpClient getClient() {
53+
return client;
54+
}
55+
5156
/**
5257
* It's recommended to call exactly once in the entire lifetime of the application.
5358
*

app/src/main/java/org/schabi/newpipe/about/AboutActivity.kt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -207,10 +207,10 @@ class AboutActivity : AppCompatActivity() {
207207
StandardLicenses.APACHE2
208208
),
209209
SoftwareComponent(
210-
"Picasso",
211-
"2013",
212-
"Square, Inc.",
213-
"https://square.github.io/picasso/",
210+
"Coil",
211+
"2023",
212+
"Coil Contributors",
213+
"https://coil-kt.github.io/coil/",
214214
StandardLicenses.APACHE2
215215
),
216216
SoftwareComponent(

app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@
118118
import org.schabi.newpipe.util.ThemeHelper;
119119
import org.schabi.newpipe.util.external_communication.KoreUtils;
120120
import org.schabi.newpipe.util.external_communication.ShareUtils;
121-
import org.schabi.newpipe.util.image.PicassoHelper;
121+
import org.schabi.newpipe.util.image.CoilHelper;
122122

123123
import java.util.ArrayList;
124124
import java.util.Iterator;
@@ -129,6 +129,7 @@
129129
import java.util.concurrent.TimeUnit;
130130
import java.util.function.Consumer;
131131

132+
import coil3.util.CoilUtils;
132133
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
133134
import io.reactivex.rxjava3.disposables.CompositeDisposable;
134135
import io.reactivex.rxjava3.disposables.Disposable;
@@ -160,8 +161,6 @@ public final class VideoDetailFragment
160161
private static final String DESCRIPTION_TAB_TAG = "DESCRIPTION TAB";
161162
private static final String EMPTY_TAB_TAG = "EMPTY TAB";
162163

163-
private static final String PICASSO_VIDEO_DETAILS_TAG = "PICASSO_VIDEO_DETAILS_TAG";
164-
165164
// tabs
166165
private boolean showComments;
167166
private boolean showRelatedItems;
@@ -1499,7 +1498,10 @@ public void showLoading() {
14991498
}
15001499
}
15011500

1502-
PicassoHelper.cancelTag(PICASSO_VIDEO_DETAILS_TAG);
1501+
CoilUtils.dispose(binding.detailThumbnailImageView);
1502+
CoilUtils.dispose(binding.detailSubChannelThumbnailView);
1503+
CoilUtils.dispose(binding.overlayThumbnail);
1504+
CoilUtils.dispose(binding.detailUploaderThumbnailView);
15031505
binding.detailThumbnailImageView.setImageBitmap(null);
15041506
binding.detailSubChannelThumbnailView.setImageBitmap(null);
15051507
}
@@ -1590,8 +1592,8 @@ public void handleResult(@NonNull final StreamInfo info) {
15901592
binding.detailSecondaryControlPanel.setVisibility(View.GONE);
15911593

15921594
checkUpdateProgressInfo(info);
1593-
PicassoHelper.loadDetailsThumbnail(info.getThumbnails()).tag(PICASSO_VIDEO_DETAILS_TAG)
1594-
.into(binding.detailThumbnailImageView);
1595+
CoilHelper.INSTANCE.loadDetailsThumbnail(binding.detailThumbnailImageView,
1596+
info.getThumbnails());
15951597
showMetaInfoInTextView(info.getMetaInfo(), binding.detailMetaInfoTextView,
15961598
binding.detailMetaInfoSeparator, disposables);
15971599

@@ -1641,8 +1643,8 @@ private void displayUploaderAsSubChannel(final StreamInfo info) {
16411643
binding.detailUploaderTextView.setVisibility(View.GONE);
16421644
}
16431645

1644-
PicassoHelper.loadAvatar(info.getUploaderAvatars()).tag(PICASSO_VIDEO_DETAILS_TAG)
1645-
.into(binding.detailSubChannelThumbnailView);
1646+
CoilHelper.INSTANCE.loadAvatar(binding.detailSubChannelThumbnailView,
1647+
info.getUploaderAvatars());
16461648
binding.detailSubChannelThumbnailView.setVisibility(View.VISIBLE);
16471649
binding.detailUploaderThumbnailView.setVisibility(View.GONE);
16481650
}
@@ -1673,11 +1675,11 @@ private void displayBothUploaderAndSubChannel(final StreamInfo info) {
16731675
binding.detailUploaderTextView.setVisibility(View.GONE);
16741676
}
16751677

1676-
PicassoHelper.loadAvatar(info.getSubChannelAvatars()).tag(PICASSO_VIDEO_DETAILS_TAG)
1677-
.into(binding.detailSubChannelThumbnailView);
1678+
CoilHelper.INSTANCE.loadAvatar(binding.detailSubChannelThumbnailView,
1679+
info.getSubChannelAvatars());
16781680
binding.detailSubChannelThumbnailView.setVisibility(View.VISIBLE);
1679-
PicassoHelper.loadAvatar(info.getUploaderAvatars()).tag(PICASSO_VIDEO_DETAILS_TAG)
1680-
.into(binding.detailUploaderThumbnailView);
1681+
CoilHelper.INSTANCE.loadAvatar(binding.detailUploaderThumbnailView,
1682+
info.getUploaderAvatars());
16811683
binding.detailUploaderThumbnailView.setVisibility(View.VISIBLE);
16821684
}
16831685

@@ -2435,8 +2437,7 @@ private void updateOverlayData(@Nullable final String overlayTitle,
24352437
binding.overlayTitleTextView.setText(isEmpty(overlayTitle) ? "" : overlayTitle);
24362438
binding.overlayChannelTextView.setText(isEmpty(uploader) ? "" : uploader);
24372439
binding.overlayThumbnail.setImageDrawable(null);
2438-
PicassoHelper.loadDetailsThumbnail(thumbnails).tag(PICASSO_VIDEO_DETAILS_TAG)
2439-
.into(binding.overlayThumbnail);
2440+
CoilHelper.INSTANCE.loadDetailsThumbnail(binding.overlayThumbnail, thumbnails);
24402441
}
24412442

24422443
private void setOverlayPlayPauseImage(final boolean playerIsPlaying) {

app/src/main/java/org/schabi/newpipe/fragments/list/channel/ChannelFragment.java

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -53,13 +53,14 @@
5353
import org.schabi.newpipe.util.StateSaver;
5454
import org.schabi.newpipe.util.ThemeHelper;
5555
import org.schabi.newpipe.util.external_communication.ShareUtils;
56+
import org.schabi.newpipe.util.image.CoilHelper;
5657
import org.schabi.newpipe.util.image.ImageStrategy;
57-
import org.schabi.newpipe.util.image.PicassoHelper;
5858

5959
import java.util.List;
6060
import java.util.Queue;
6161
import java.util.concurrent.TimeUnit;
6262

63+
import coil3.util.CoilUtils;
6364
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
6465
import io.reactivex.rxjava3.core.Observable;
6566
import io.reactivex.rxjava3.disposables.CompositeDisposable;
@@ -73,7 +74,6 @@ public class ChannelFragment extends BaseStateFragment<ChannelInfo>
7374
implements StateSaver.WriteRead {
7475

7576
private static final int BUTTON_DEBOUNCE_INTERVAL = 100;
76-
private static final String PICASSO_CHANNEL_TAG = "PICASSO_CHANNEL_TAG";
7777

7878
@State
7979
protected int serviceId = Constants.NO_SERVICE_ID;
@@ -578,7 +578,9 @@ private void runWorker(final boolean forceLoad) {
578578
@Override
579579
public void showLoading() {
580580
super.showLoading();
581-
PicassoHelper.cancelTag(PICASSO_CHANNEL_TAG);
581+
CoilUtils.dispose(binding.channelAvatarView);
582+
CoilUtils.dispose(binding.channelBannerImage);
583+
CoilUtils.dispose(binding.subChannelAvatarView);
582584
animate(binding.channelSubscribeButton, false, 100);
583585
}
584586

@@ -589,17 +591,15 @@ public void handleResult(@NonNull final ChannelInfo result) {
589591
setInitialData(result.getServiceId(), result.getOriginalUrl(), result.getName());
590592

591593
if (ImageStrategy.shouldLoadImages() && !result.getBanners().isEmpty()) {
592-
PicassoHelper.loadBanner(result.getBanners()).tag(PICASSO_CHANNEL_TAG)
593-
.into(binding.channelBannerImage);
594+
CoilHelper.INSTANCE.loadBanner(binding.channelBannerImage, result.getBanners());
594595
} else {
595596
// do not waste space for the banner, if the user disabled images or there is not one
596597
binding.channelBannerImage.setImageDrawable(null);
597598
}
598599

599-
PicassoHelper.loadAvatar(result.getAvatars()).tag(PICASSO_CHANNEL_TAG)
600-
.into(binding.channelAvatarView);
601-
PicassoHelper.loadAvatar(result.getParentChannelAvatars()).tag(PICASSO_CHANNEL_TAG)
602-
.into(binding.subChannelAvatarView);
600+
CoilHelper.INSTANCE.loadAvatar(binding.channelAvatarView, result.getAvatars());
601+
CoilHelper.INSTANCE.loadAvatar(binding.subChannelAvatarView,
602+
result.getParentChannelAvatars());
603603

604604
binding.channelTitleView.setText(result.getName());
605605
binding.channelSubscriberView.setVisibility(View.VISIBLE);

app/src/main/java/org/schabi/newpipe/fragments/list/comments/CommentRepliesFragment.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@
2525
import org.schabi.newpipe.util.ExtractorHelper;
2626
import org.schabi.newpipe.util.Localization;
2727
import org.schabi.newpipe.util.NavigationHelper;
28+
import org.schabi.newpipe.util.image.CoilHelper;
2829
import org.schabi.newpipe.util.image.ImageStrategy;
29-
import org.schabi.newpipe.util.image.PicassoHelper;
3030
import org.schabi.newpipe.util.text.TextLinkifier;
3131
import org.schabi.newpipe.util.text.LongPressLinkMovementMethod;
3232

@@ -84,7 +84,7 @@ protected Supplier<View> getListHeaderSupplier() {
8484
final CommentsInfoItem item = commentsInfoItem;
8585

8686
// load the author avatar
87-
PicassoHelper.loadAvatar(item.getUploaderAvatars()).into(binding.authorAvatar);
87+
CoilHelper.INSTANCE.loadAvatar(binding.authorAvatar, item.getUploaderAvatars());
8888
binding.authorAvatar.setVisibility(ImageStrategy.shouldLoadImages()
8989
? View.VISIBLE : View.GONE);
9090

app/src/main/java/org/schabi/newpipe/fragments/list/playlist/PlaylistFragment.java

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@
5353
import org.schabi.newpipe.util.NavigationHelper;
5454
import org.schabi.newpipe.util.PlayButtonHelper;
5555
import org.schabi.newpipe.util.external_communication.ShareUtils;
56-
import org.schabi.newpipe.util.image.PicassoHelper;
56+
import org.schabi.newpipe.util.image.CoilHelper;
5757
import org.schabi.newpipe.util.text.TextEllipsizer;
5858

5959
import java.util.ArrayList;
@@ -62,6 +62,7 @@
6262
import java.util.function.Supplier;
6363
import java.util.stream.Collectors;
6464

65+
import coil3.util.CoilUtils;
6566
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
6667
import io.reactivex.rxjava3.core.Flowable;
6768
import io.reactivex.rxjava3.core.Single;
@@ -71,8 +72,6 @@
7172
public class PlaylistFragment extends BaseListInfoFragment<StreamInfoItem, PlaylistInfo>
7273
implements PlaylistControlViewHolder {
7374

74-
private static final String PICASSO_PLAYLIST_TAG = "PICASSO_PLAYLIST_TAG";
75-
7675
private CompositeDisposable disposables;
7776
private Subscription bookmarkReactor;
7877
private AtomicBoolean isBookmarkButtonReady;
@@ -271,7 +270,7 @@ public void showLoading() {
271270
animate(headerBinding.getRoot(), false, 200);
272271
animateHideRecyclerViewAllowingScrolling(itemsList);
273272

274-
PicassoHelper.cancelTag(PICASSO_PLAYLIST_TAG);
273+
CoilUtils.dispose(headerBinding.uploaderAvatarView);
275274
animate(headerBinding.uploaderLayout, false, 200);
276275
}
277276

@@ -322,8 +321,8 @@ public void handleResult(@NonNull final PlaylistInfo result) {
322321
R.drawable.ic_radio)
323322
);
324323
} else {
325-
PicassoHelper.loadAvatar(result.getUploaderAvatars()).tag(PICASSO_PLAYLIST_TAG)
326-
.into(headerBinding.uploaderAvatarView);
324+
CoilHelper.INSTANCE.loadAvatar(headerBinding.uploaderAvatarView,
325+
result.getUploaderAvatars());
327326
}
328327

329328
streamCount = result.getStreamCount();

0 commit comments

Comments
 (0)