Skip to content

Commit 89576ad

Browse files
authored
Merge branch 'refactor' into history_cache_compose
2 parents 4c5cb31 + 2836191 commit 89576ad

File tree

121 files changed

+1309
-1008
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

121 files changed

+1309
-1008
lines changed

app/build.gradle

+12-8
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ plugins {
1010
id "checkstyle"
1111
id "org.sonarqube" version "4.0.0.2929"
1212
id "dagger.hilt.android.plugin"
13+
id "org.jetbrains.kotlin.plugin.compose" version "${kotlin_version}"
1314
}
1415

1516
android {
@@ -105,10 +106,6 @@ android {
105106
'META-INF/COPYRIGHT']
106107
}
107108
}
108-
109-
composeOptions {
110-
kotlinCompilerExtensionVersion = "1.5.3"
111-
}
112109
}
113110

114111
ext {
@@ -270,8 +267,7 @@ dependencies {
270267
implementation "com.github.lisawray.groupie:groupie-viewbinding:${groupieVersion}"
271268

272269
// Image loading
273-
//noinspection GradleDependency --> 2.8 is the last version, not 2.71828!
274-
implementation "com.squareup.picasso:picasso:2.8"
270+
implementation 'io.coil-kt:coil-compose:2.7.0'
275271

276272
// Markdown library for Android
277273
implementation "io.noties.markwon:core:${markwonVersion}"
@@ -293,10 +289,18 @@ dependencies {
293289
implementation "org.ocpsoft.prettytime:prettytime:5.0.8.Final"
294290

295291
// Jetpack Compose
296-
implementation(platform('androidx.compose:compose-bom:2024.02.01'))
297-
implementation 'androidx.compose.material3:material3'
292+
implementation(platform('androidx.compose:compose-bom:2024.06.00'))
293+
implementation 'androidx.compose.material3:material3:1.3.0-beta05'
294+
implementation 'androidx.compose.material3.adaptive:adaptive:1.0.0-beta04'
298295
implementation 'androidx.activity:activity-compose'
299296
implementation 'androidx.compose.ui:ui-tooling-preview'
297+
implementation 'androidx.compose.ui:ui-text:1.7.0-beta07' // Needed for parsing HTML to AnnotatedString
298+
implementation 'androidx.lifecycle:lifecycle-viewmodel-compose'
299+
implementation 'androidx.paging:paging-compose:3.3.2'
300+
implementation 'com.github.nanihadesuka:LazyColumnScrollbar:2.2.0'
301+
302+
// Coroutines interop
303+
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-rx3:1.8.1'
300304

301305
// hilt
302306
implementation("androidx.hilt:hilt-navigation-compose:${hiltVersion}")

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

+15-11
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package org.schabi.newpipe;
22

3+
import android.app.ActivityManager;
34
import android.app.Application;
45
import android.content.Context;
56
import android.content.SharedPreferences;
@@ -8,6 +9,7 @@
89
import androidx.annotation.NonNull;
910
import androidx.core.app.NotificationChannelCompat;
1011
import androidx.core.app.NotificationManagerCompat;
12+
import androidx.core.content.ContextCompat;
1113
import androidx.preference.PreferenceManager;
1214

1315
import com.jakewharton.processphoenix.ProcessPhoenix;
@@ -20,19 +22,20 @@
2022
import org.schabi.newpipe.ktx.ExceptionUtils;
2123
import org.schabi.newpipe.settings.NewPipeSettings;
2224
import org.schabi.newpipe.util.Localization;
23-
import org.schabi.newpipe.util.image.ImageStrategy;
24-
import org.schabi.newpipe.util.image.PicassoHelper;
2525
import org.schabi.newpipe.util.ServiceHelper;
2626
import org.schabi.newpipe.util.StateSaver;
27+
import org.schabi.newpipe.util.image.ImageStrategy;
2728
import org.schabi.newpipe.util.image.PreferredImageQuality;
2829

2930
import java.io.IOException;
3031
import java.io.InterruptedIOException;
3132
import java.net.SocketException;
3233
import java.util.List;
3334
import java.util.Objects;
34-
3535
import dagger.hilt.android.HiltAndroidApp;
36+
import coil.ImageLoader;
37+
import coil.ImageLoaderFactory;
38+
import coil.util.DebugLogger;
3639
import io.reactivex.rxjava3.exceptions.CompositeException;
3740
import io.reactivex.rxjava3.exceptions.MissingBackpressureException;
3841
import io.reactivex.rxjava3.exceptions.OnErrorNotImplementedException;
@@ -57,9 +60,8 @@
5760
* You should have received a copy of the GNU General Public License
5861
* along with NewPipe. If not, see <http://www.gnu.org/licenses/>.
5962
*/
60-
6163
@HiltAndroidApp
62-
public class App extends Application {
64+
public class App extends Application implements ImageLoaderFactory {
6365
public static final String PACKAGE_NAME = BuildConfig.APPLICATION_ID;
6466
private static final String TAG = App.class.toString();
6567

@@ -110,20 +112,22 @@ public void onCreate() {
110112

111113
// Initialize image loader
112114
final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
113-
PicassoHelper.init(this);
114115
ImageStrategy.setPreferredImageQuality(PreferredImageQuality.fromPreferenceKey(this,
115116
prefs.getString(getString(R.string.image_quality_key),
116117
getString(R.string.image_quality_default))));
117-
PicassoHelper.setIndicatorsEnabled(MainActivity.DEBUG
118-
&& prefs.getBoolean(getString(R.string.show_image_indicators_key), false));
119118

120119
configureRxJavaErrorHandler();
121120
}
122121

122+
@NonNull
123123
@Override
124-
public void onTerminate() {
125-
super.onTerminate();
126-
PicassoHelper.terminate();
124+
public ImageLoader newImageLoader() {
125+
return new ImageLoader.Builder(this)
126+
.allowRgb565(ContextCompat.getSystemService(this, ActivityManager.class)
127+
.isLowRamDevice())
128+
.logger(BuildConfig.DEBUG ? new DebugLogger() : null)
129+
.crossfade(true)
130+
.build();
127131
}
128132

129133
protected Downloader getDownloader() {

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

+2-2
Original file line numberDiff line numberDiff line change
@@ -167,8 +167,8 @@ class AboutActivity : AppCompatActivity() {
167167
"https://square.github.io/okhttp/", StandardLicenses.APACHE2
168168
),
169169
SoftwareComponent(
170-
"Picasso", "2013", "Square, Inc.",
171-
"https://square.github.io/picasso/", StandardLicenses.APACHE2
170+
"Coil", "2023", "Coil Contributors",
171+
"https://coil-kt.github.io/coil/", StandardLicenses.APACHE2
172172
),
173173
SoftwareComponent(
174174
"PrettyTime", "2012 - 2020", "Lincoln Baxter, III",

app/src/main/java/org/schabi/newpipe/database/stream/dao/StreamDAO.kt

+2-1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import androidx.room.Query
88
import androidx.room.Transaction
99
import io.reactivex.rxjava3.core.Completable
1010
import io.reactivex.rxjava3.core.Flowable
11+
import io.reactivex.rxjava3.core.Maybe
1112
import org.schabi.newpipe.database.BasicDAO
1213
import org.schabi.newpipe.database.stream.model.StreamEntity
1314
import org.schabi.newpipe.database.stream.model.StreamEntity.Companion.STREAM_ID
@@ -27,7 +28,7 @@ abstract class StreamDAO : BasicDAO<StreamEntity> {
2728
abstract override fun listByService(serviceId: Int): Flowable<List<StreamEntity>>
2829

2930
@Query("SELECT * FROM streams WHERE url = :url AND service_id = :serviceId")
30-
abstract fun getStream(serviceId: Long, url: String): Flowable<List<StreamEntity>>
31+
abstract fun getStream(serviceId: Long, url: String): Maybe<StreamEntity>
3132

3233
@Query("UPDATE streams SET uploader_url = :uploaderUrl WHERE url = :url AND service_id = :serviceId")
3334
abstract fun setUploaderUrl(serviceId: Long, url: String, uploaderUrl: String): Completable

app/src/main/java/org/schabi/newpipe/database/stream/dao/StreamStateDAO.java

+5-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
package org.schabi.newpipe.database.stream.dao;
22

3+
import static org.schabi.newpipe.database.stream.model.StreamStateEntity.JOIN_STREAM_ID;
4+
import static org.schabi.newpipe.database.stream.model.StreamStateEntity.STREAM_STATE_TABLE;
5+
36
import androidx.room.Dao;
47
import androidx.room.Insert;
58
import androidx.room.OnConflictStrategy;
@@ -12,9 +15,7 @@
1215
import java.util.List;
1316

1417
import io.reactivex.rxjava3.core.Flowable;
15-
16-
import static org.schabi.newpipe.database.stream.model.StreamStateEntity.JOIN_STREAM_ID;
17-
import static org.schabi.newpipe.database.stream.model.StreamStateEntity.STREAM_STATE_TABLE;
18+
import io.reactivex.rxjava3.core.Maybe;
1819

1920
@Dao
2021
public interface StreamStateDAO extends BasicDAO<StreamStateEntity> {
@@ -32,7 +33,7 @@ default Flowable<List<StreamStateEntity>> listByService(final int serviceId) {
3233
}
3334

3435
@Query("SELECT * FROM " + STREAM_STATE_TABLE + " WHERE " + JOIN_STREAM_ID + " = :streamId")
35-
Flowable<List<StreamStateEntity>> getState(long streamId);
36+
Maybe<StreamStateEntity> getState(long streamId);
3637

3738
@Query("DELETE FROM " + STREAM_STATE_TABLE + " WHERE " + JOIN_STREAM_ID + " = :streamId")
3839
int deleteState(long streamId);

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

+16-14
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@
116116
import org.schabi.newpipe.util.ThemeHelper;
117117
import org.schabi.newpipe.util.external_communication.KoreUtils;
118118
import org.schabi.newpipe.util.external_communication.ShareUtils;
119-
import org.schabi.newpipe.util.image.PicassoHelper;
119+
import org.schabi.newpipe.util.image.CoilHelper;
120120

121121
import java.util.ArrayList;
122122
import java.util.Iterator;
@@ -127,6 +127,7 @@
127127
import java.util.concurrent.TimeUnit;
128128
import java.util.function.Consumer;
129129

130+
import coil.util.CoilUtils;
130131
import icepick.State;
131132
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
132133
import io.reactivex.rxjava3.disposables.CompositeDisposable;
@@ -159,8 +160,6 @@ public final class VideoDetailFragment
159160
private static final String DESCRIPTION_TAB_TAG = "DESCRIPTION TAB";
160161
private static final String EMPTY_TAB_TAG = "EMPTY TAB";
161162

162-
private static final String PICASSO_VIDEO_DETAILS_TAG = "PICASSO_VIDEO_DETAILS_TAG";
163-
164163
// tabs
165164
private boolean showComments;
166165
private boolean showRelatedItems;
@@ -1471,7 +1470,11 @@ public void showLoading() {
14711470
}
14721471
}
14731472

1474-
PicassoHelper.cancelTag(PICASSO_VIDEO_DETAILS_TAG);
1473+
CoilUtils.dispose(binding.detailThumbnailImageView);
1474+
CoilUtils.dispose(binding.detailSubChannelThumbnailView);
1475+
CoilUtils.dispose(binding.overlayThumbnail);
1476+
CoilUtils.dispose(binding.detailUploaderThumbnailView);
1477+
14751478
binding.detailThumbnailImageView.setImageBitmap(null);
14761479
binding.detailSubChannelThumbnailView.setImageBitmap(null);
14771480
}
@@ -1562,8 +1565,8 @@ public void handleResult(@NonNull final StreamInfo info) {
15621565
binding.detailSecondaryControlPanel.setVisibility(View.GONE);
15631566

15641567
checkUpdateProgressInfo(info);
1565-
PicassoHelper.loadDetailsThumbnail(info.getThumbnails()).tag(PICASSO_VIDEO_DETAILS_TAG)
1566-
.into(binding.detailThumbnailImageView);
1568+
CoilHelper.INSTANCE.loadDetailsThumbnail(binding.detailThumbnailImageView,
1569+
info.getThumbnails());
15671570
showMetaInfoInTextView(info.getMetaInfo(), binding.detailMetaInfoTextView,
15681571
binding.detailMetaInfoSeparator, disposables);
15691572

@@ -1613,8 +1616,8 @@ private void displayUploaderAsSubChannel(final StreamInfo info) {
16131616
binding.detailUploaderTextView.setVisibility(View.GONE);
16141617
}
16151618

1616-
PicassoHelper.loadAvatar(info.getUploaderAvatars()).tag(PICASSO_VIDEO_DETAILS_TAG)
1617-
.into(binding.detailSubChannelThumbnailView);
1619+
CoilHelper.INSTANCE.loadAvatar(binding.detailSubChannelThumbnailView,
1620+
info.getUploaderAvatars());
16181621
binding.detailSubChannelThumbnailView.setVisibility(View.VISIBLE);
16191622
binding.detailUploaderThumbnailView.setVisibility(View.GONE);
16201623
}
@@ -1645,11 +1648,11 @@ private void displayBothUploaderAndSubChannel(final StreamInfo info) {
16451648
binding.detailUploaderTextView.setVisibility(View.GONE);
16461649
}
16471650

1648-
PicassoHelper.loadAvatar(info.getSubChannelAvatars()).tag(PICASSO_VIDEO_DETAILS_TAG)
1649-
.into(binding.detailSubChannelThumbnailView);
1651+
CoilHelper.INSTANCE.loadAvatar(binding.detailSubChannelThumbnailView,
1652+
info.getSubChannelAvatars());
16501653
binding.detailSubChannelThumbnailView.setVisibility(View.VISIBLE);
1651-
PicassoHelper.loadAvatar(info.getUploaderAvatars()).tag(PICASSO_VIDEO_DETAILS_TAG)
1652-
.into(binding.detailUploaderThumbnailView);
1654+
CoilHelper.INSTANCE.loadAvatar(binding.detailUploaderThumbnailView,
1655+
info.getUploaderAvatars());
16531656
binding.detailUploaderThumbnailView.setVisibility(View.VISIBLE);
16541657
}
16551658

@@ -2403,8 +2406,7 @@ private void updateOverlayData(@Nullable final String overlayTitle,
24032406
binding.overlayTitleTextView.setText(isEmpty(overlayTitle) ? "" : overlayTitle);
24042407
binding.overlayChannelTextView.setText(isEmpty(uploader) ? "" : uploader);
24052408
binding.overlayThumbnail.setImageDrawable(null);
2406-
PicassoHelper.loadDetailsThumbnail(thumbnails).tag(PICASSO_VIDEO_DETAILS_TAG)
2407-
.into(binding.overlayThumbnail);
2409+
CoilHelper.INSTANCE.loadDetailsThumbnail(binding.overlayThumbnail, thumbnails);
24082410
}
24092411

24102412
private void setOverlayPlayPauseImage(final boolean playerIsPlaying) {

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

+10-10
Original file line numberDiff line numberDiff line change
@@ -50,15 +50,16 @@
5050
import org.schabi.newpipe.util.Localization;
5151
import org.schabi.newpipe.util.NavigationHelper;
5252
import org.schabi.newpipe.util.StateSaver;
53-
import org.schabi.newpipe.util.image.ImageStrategy;
54-
import org.schabi.newpipe.util.image.PicassoHelper;
5553
import org.schabi.newpipe.util.ThemeHelper;
5654
import org.schabi.newpipe.util.external_communication.ShareUtils;
55+
import org.schabi.newpipe.util.image.CoilHelper;
56+
import org.schabi.newpipe.util.image.ImageStrategy;
5757

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

62+
import coil.util.CoilUtils;
6263
import icepick.State;
6364
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
6465
import io.reactivex.rxjava3.core.Observable;
@@ -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;
@@ -576,7 +576,9 @@ private void runWorker(final boolean forceLoad) {
576576
@Override
577577
public void showLoading() {
578578
super.showLoading();
579-
PicassoHelper.cancelTag(PICASSO_CHANNEL_TAG);
579+
CoilUtils.dispose(binding.channelAvatarView);
580+
CoilUtils.dispose(binding.channelBannerImage);
581+
CoilUtils.dispose(binding.subChannelAvatarView);
580582
animate(binding.channelSubscribeButton, false, 100);
581583
}
582584

@@ -587,17 +589,15 @@ public void handleResult(@NonNull final ChannelInfo result) {
587589
setInitialData(result.getServiceId(), result.getOriginalUrl(), result.getName());
588590

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

597-
PicassoHelper.loadAvatar(result.getAvatars()).tag(PICASSO_CHANNEL_TAG)
598-
.into(binding.channelAvatarView);
599-
PicassoHelper.loadAvatar(result.getParentChannelAvatars()).tag(PICASSO_CHANNEL_TAG)
600-
.into(binding.subChannelAvatarView);
598+
CoilHelper.INSTANCE.loadAvatar(binding.channelAvatarView, result.getAvatars());
599+
CoilHelper.INSTANCE.loadAvatar(binding.subChannelAvatarView,
600+
result.getParentChannelAvatars());
601601

602602
binding.channelTitleView.setText(result.getName());
603603
binding.channelSubscriberView.setVisibility(View.VISIBLE);

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

+2-2
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@
2323
import org.schabi.newpipe.util.ExtractorHelper;
2424
import org.schabi.newpipe.util.Localization;
2525
import org.schabi.newpipe.util.NavigationHelper;
26+
import org.schabi.newpipe.util.image.CoilHelper;
2627
import org.schabi.newpipe.util.image.ImageStrategy;
27-
import org.schabi.newpipe.util.image.PicassoHelper;
2828
import org.schabi.newpipe.util.text.TextLinkifier;
2929

3030
import java.util.Queue;
@@ -82,7 +82,7 @@ protected Supplier<View> getListHeaderSupplier() {
8282
final CommentsInfoItem item = commentsInfoItem;
8383

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

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

+5-6
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 coil.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;
@@ -276,7 +275,7 @@ public void showLoading() {
276275
animate(headerBinding.getRoot(), false, 200);
277276
animateHideRecyclerViewAllowingScrolling(itemsList);
278277

279-
PicassoHelper.cancelTag(PICASSO_PLAYLIST_TAG);
278+
CoilUtils.dispose(headerBinding.uploaderAvatarView);
280279
animate(headerBinding.uploaderLayout, false, 200);
281280
}
282281

@@ -327,8 +326,8 @@ public void handleResult(@NonNull final PlaylistInfo result) {
327326
R.drawable.ic_radio)
328327
);
329328
} else {
330-
PicassoHelper.loadAvatar(result.getUploaderAvatars()).tag(PICASSO_PLAYLIST_TAG)
331-
.into(headerBinding.uploaderAvatarView);
329+
CoilHelper.INSTANCE.loadAvatar(headerBinding.uploaderAvatarView,
330+
result.getUploaderAvatars());
332331
}
333332

334333
streamCount = result.getStreamCount();

0 commit comments

Comments
 (0)