Skip to content

Commit 6762993

Browse files
authored
Merge pull request #10470 from TeamNewPipe/release-0.26.0
Release 0.26.0
2 parents 1e8efa7 + 9aff49b commit 6762993

File tree

328 files changed

+9799
-3570
lines changed

Some content is hidden

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

328 files changed

+9799
-3570
lines changed

.github/ISSUE_TEMPLATE/bug_report.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ body:
1414
attributes:
1515
label: "Checklist"
1616
options:
17-
- label: "I am able to reproduce the bug with the [latest version](https://github.com/TeamNewPipe/NewPipe/releases/latest)."
17+
- label: "I am able to reproduce the bug with the latest version given here: [CLICK THIS LINK](https://github.com/TeamNewPipe/NewPipe/releases/latest)."
1818
required: true
1919
- label: "I made sure that there are *no existing issues* - [open](https://github.com/TeamNewPipe/NewPipe/issues) or [closed](https://github.com/TeamNewPipe/NewPipe/issues?q=is%3Aissue+is%3Aclosed) - which I could contribute my information to."
2020
required: true
+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Add 'size/small' label to any changes with less than 50 lines
2+
size/small:
3+
max: 49
4+
5+
# Add 'size/medium' label to any changes between 50 and 249 lines
6+
size/medium:
7+
min: 50
8+
max: 249
9+
10+
# Add 'size/large' label to any changes between 250 and 749 lines
11+
size/large:
12+
min: 250
13+
max: 749
14+
15+
# Add 'size/giant' label to any changes for more than 749 lines
16+
size/giant:
17+
min: 750

.github/workflows/image-minimizer.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ module.exports = async ({github, context}) => {
8686
});
8787
}
8888

89-
// Asnyc replace function from https://stackoverflow.com/a/48032528
89+
// Async replace function from https://stackoverflow.com/a/48032528
9090
async function replaceAsync(str, regex, asyncFn) {
9191
const promises = [];
9292
str.replace(regex, (match, ...args) => {
@@ -138,7 +138,7 @@ module.exports = async ({github, context}) => {
138138
if (shouldModify) {
139139
wasMatchModified = true;
140140
console.log(`Modifying match '${match}'`);
141-
return `<img alt="${g1}" src="${g2}" width=${Math.min(600, (IMG_MAX_HEIGHT_PX * probeAspectRatio).toFixed(0))} />`;
141+
return `<img alt="${g1}" src="${g2}" width=${Math.min(600, Math.floor(IMG_MAX_HEIGHT_PX * probeAspectRatio))} />`;
142142
}
143143

144144
console.log(`Match '${match}' is ok/will not be modified`);

.github/workflows/pr-labeler.yml

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
name: "PR size labeler"
2+
on: [pull_request]
3+
permissions:
4+
contents: read
5+
pull-requests: write
6+
7+
jobs:
8+
changed-lines-count-labeler:
9+
runs-on: ubuntu-latest
10+
name: Automatically labelling pull requests based on the changed lines count
11+
permissions:
12+
pull-requests: write
13+
steps:
14+
- name: Set a label
15+
uses: TeamNewPipe/changed-lines-count-labeler@main
16+
with:
17+
repo-token: ${{ secrets.GITHUB_TOKEN }}
18+
configuration-path: .github/changed-lines-count-labeler.yml

README.md

+2-12
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,14 @@
1313
<a href="https://github.com/TeamNewPipe/NewPipe/actions" alt="Build Status"><img src="https://github.com/TeamNewPipe/NewPipe/workflows/CI/badge.svg?branch=dev&event=push"></a>
1414
<a href="https://hosted.weblate.org/engage/newpipe/" alt="Translation Status"><img src="https://hosted.weblate.org/widgets/newpipe/-/svg-badge.svg"></a>
1515
<a href="https://web.libera.chat/#newpipe" alt="IRC channel: #newpipe"><img src="https://img.shields.io/badge/IRC%20chat-%23newpipe-brightgreen.svg"></a>
16-
<a href="https://www.bountysource.com/teams/newpipe" alt="Bountysource bounties"><img src="https://img.shields.io/bountysource/team/newpipe/activity.svg?colorB=cd201f"></a>
16+
<a href="https://matrix.to/#/#newpipe:libera.chat" alt="Matrix channel: #newpipe"><img src="https://img.shields.io/badge/Matrix%20chat-%23newpipe-blue"></a>
1717
</p>
1818
<hr>
1919
<p align="center"><a href="#screenshots">Screenshots</a> &bull; <a href="#supported-services">Supported Services</a> &bull; <a href="#description">Description</a> &bull; <a href="#features">Features</a> &bull; <a href="#installation-and-updates">Installation and updates</a> &bull; <a href="#contribution">Contribution</a> &bull; <a href="#donate">Donate</a> &bull; <a href="#license">License</a></p>
2020
<p align="center"><a href="https://newpipe.net">Website</a> &bull; <a href="https://newpipe.net/blog/">Blog</a> &bull; <a href="https://newpipe.net/FAQ/">FAQ</a> &bull; <a href="https://newpipe.net/press/">Press</a></p>
2121
<hr>
2222

23-
*Read this document in other languages: [Deutsch](doc/README.de.md), [English](README.md), [Español](doc/README.es.md), [Français](doc/README.fr.md), [हिन्दी](doc/README.hi.md), [Italiano](doc/README.it.md), [한국어](doc/README.ko.md), [Português Brasil](doc/README.pt_BR.md), [Polski](doc/README.pl.md), [ਪੰਜਾਬੀ ](doc/README.pa.md), [日本語](doc/README.ja.md), [Română](doc/README.ro.md), [Soomaali](doc/README.so.md), [Türkçe](doc/README.tr.md), [正體中文](doc/README.zh_TW.md), [অসমীয়া](doc/README.asm.md)*
23+
*Read this document in other languages: [Deutsch](doc/README.de.md), [English](README.md), [Español](doc/README.es.md), [Français](doc/README.fr.md), [हिन्दी](doc/README.hi.md), [Italiano](doc/README.it.md), [한국어](doc/README.ko.md), [Português Brasil](doc/README.pt_BR.md), [Polski](doc/README.pl.md), [ਪੰਜਾਬੀ ](doc/README.pa.md), [日本語](doc/README.ja.md), [Română](doc/README.ro.md), [Soomaali](doc/README.so.md), [Türkçe](doc/README.tr.md), [正體中文](doc/README.zh_TW.md), [অসমীয়া](doc/README.asm.md), [Српски](doc/README.sr.md)*
2424

2525
<b>WARNING: THIS APP IS IN BETA, SO YOU MAY ENCOUNTER BUGS. IF YOU DO, OPEN AN ISSUE IN OUR GITHUB REPOSITORY BY FILLING OUT THE ISSUE TEMPLATE.</b>
2626

@@ -126,16 +126,6 @@ If you like NewPipe, you're welcome to send a donation. We prefer Liberapay, as
126126
<td><a href="https://liberapay.com/TeamNewPipe/"><img src="assets/liberapay_qr_code.png" alt="Visit NewPipe at liberapay.com" width="100px"></a></td>
127127
<td><a href="https://liberapay.com/TeamNewPipe/donate"><img src="assets/liberapay_donate_button.svg" alt="Donate via Liberapay" height="35px"></a></td>
128128
</tr>
129-
<tr>
130-
<td><img src="https://bitcoin.org/img/icons/logotop.svg" alt="Bitcoin"></td>
131-
<td><img src="assets/bitcoin_qr_code.png" alt="Bitcoin QR code" width="100px"></td>
132-
<td><samp>16A9J59ahMRqkLSZjhYj33n9j3fMztFxnh</samp></td>
133-
</tr>
134-
<tr>
135-
<td><a href="https://www.bountysource.com/teams/newpipe"><img src="https://upload.wikimedia.org/wikipedia/commons/thumb/2/22/Bountysource.png/320px-Bountysource.png" alt="Bountysource" width="190px"></a></td>
136-
<td><a href="https://www.bountysource.com/teams/newpipe"><img src="assets/bountysource_qr_code.png" alt="Visit NewPipe at bountysource.com" width="100px"></a></td>
137-
<td><a href="https://www.bountysource.com/teams/newpipe/issues"><img src="https://img.shields.io/bountysource/team/newpipe/activity.svg?colorB=cd201f" height="30px" alt="Check out how many bounties you can earn."></a></td>
138-
</tr>
139129
</table>
140130

141131
## Privacy Policy

app/build.gradle

+7-10
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ android {
2020
resValue "string", "app_name", "NewPipe"
2121
minSdk 21
2222
targetSdk 33
23-
versionCode 994
24-
versionName "0.25.2"
23+
versionCode 995
24+
versionName "0.26.0"
2525

2626
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
2727

@@ -50,9 +50,6 @@ android {
5050
}
5151
}
5252

53-
// Keep the release build type at the end of the list to override 'archivesBaseName' of
54-
// debug build. This seems to be a Gradle bug, therefore
55-
// TODO: update Gradle version
5653
release {
5754
if (System.properties.containsKey('packageSuffix')) {
5855
applicationIdSuffix System.getProperty('packageSuffix')
@@ -115,7 +112,7 @@ ext {
115112

116113
icepickVersion = '3.2.0'
117114
exoPlayerVersion = '2.18.7'
118-
googleAutoServiceVersion = '1.0.1'
115+
googleAutoServiceVersion = '1.1.1'
119116
groupieVersion = '2.10.1'
120117
markwonVersion = '4.6.2'
121118

@@ -192,23 +189,23 @@ sonar {
192189

193190
dependencies {
194191
/** Desugaring **/
195-
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.0.3'
192+
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs_nio:2.0.3'
196193

197194
/** NewPipe libraries **/
198195
// You can use a local version by uncommenting a few lines in settings.gradle
199196
// Or you can use a commit you pushed to GitHub by just replacing TeamNewPipe with your GitHub
200197
// name and the commit hash with the commit hash of the (pushed) commit you want to test
201198
// This works thanks to JitPack: https://jitpack.io/
202199
implementation 'com.github.TeamNewPipe:nanojson:1d9e1aea9049fc9f85e68b43ba39fe7be1c1f751'
203-
implementation 'com.github.TeamNewPipe:NewPipeExtractor:v0.22.7'
200+
implementation 'com.github.TeamNewPipe:NewPipeExtractor:v0.23.1'
204201
implementation 'com.github.TeamNewPipe:NoNonsense-FilePicker:5.0.0'
205202

206203
/** Checkstyle **/
207204
checkstyle "com.puppycrawl.tools:checkstyle:${checkstyleVersion}"
208205
ktlint 'com.pinterest:ktlint:0.45.2'
209206

210207
/** Kotlin **/
211-
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:${kotlin_version}"
208+
implementation "org.jetbrains.kotlin:kotlin-stdlib:${kotlin_version}"
212209

213210
/** AndroidX **/
214211
implementation 'androidx.appcompat:appcompat:1.5.1'
@@ -232,7 +229,7 @@ dependencies {
232229
implementation 'androidx.viewpager2:viewpager2:1.1.0-beta01'
233230
implementation "androidx.work:work-runtime-ktx:${androidxWorkVersion}"
234231
implementation "androidx.work:work-rxjava3:${androidxWorkVersion}"
235-
implementation 'com.google.android.material:material:1.6.1'
232+
implementation 'com.google.android.material:material:1.9.0'
236233

237234
/** Third-party libraries **/
238235
// Instance state boilerplate elimination
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
package org.schabi.newpipe.database
2+
3+
import android.content.Context
4+
import androidx.room.Room
5+
import androidx.test.core.app.ApplicationProvider
6+
import io.reactivex.rxjava3.core.Single
7+
import org.junit.After
8+
import org.junit.Assert.assertEquals
9+
import org.junit.Assert.assertNotNull
10+
import org.junit.Before
11+
import org.junit.Test
12+
import org.schabi.newpipe.database.feed.dao.FeedDAO
13+
import org.schabi.newpipe.database.feed.model.FeedEntity
14+
import org.schabi.newpipe.database.feed.model.FeedGroupEntity
15+
import org.schabi.newpipe.database.stream.StreamWithState
16+
import org.schabi.newpipe.database.stream.dao.StreamDAO
17+
import org.schabi.newpipe.database.stream.model.StreamEntity
18+
import org.schabi.newpipe.database.subscription.SubscriptionDAO
19+
import org.schabi.newpipe.database.subscription.SubscriptionEntity
20+
import org.schabi.newpipe.extractor.ServiceList
21+
import org.schabi.newpipe.extractor.channel.ChannelInfo
22+
import org.schabi.newpipe.extractor.stream.StreamType
23+
import java.io.IOException
24+
import java.time.OffsetDateTime
25+
import kotlin.streams.toList
26+
27+
class FeedDAOTest {
28+
private lateinit var db: AppDatabase
29+
private lateinit var feedDAO: FeedDAO
30+
private lateinit var streamDAO: StreamDAO
31+
private lateinit var subscriptionDAO: SubscriptionDAO
32+
33+
private val serviceId = ServiceList.YouTube.serviceId
34+
35+
private val stream1 = StreamEntity(1, serviceId, "https://youtube.com/watch?v=1", "stream 1", StreamType.VIDEO_STREAM, 1000, "channel-1", "https://youtube.com/channel/1", "https://i.ytimg.com/vi/1/hqdefault.jpg", 100, "2023-01-01", OffsetDateTime.parse("2023-01-01T00:00:00Z"))
36+
private val stream2 = StreamEntity(2, serviceId, "https://youtube.com/watch?v=2", "stream 2", StreamType.VIDEO_STREAM, 1000, "channel-1", "https://youtube.com/channel/1", "https://i.ytimg.com/vi/1/hqdefault.jpg", 100, "2023-01-02", OffsetDateTime.parse("2023-01-02T00:00:00Z"))
37+
private val stream3 = StreamEntity(3, serviceId, "https://youtube.com/watch?v=3", "stream 3", StreamType.LIVE_STREAM, 1000, "channel-1", "https://youtube.com/channel/1", "https://i.ytimg.com/vi/1/hqdefault.jpg", 100, "2023-01-03", OffsetDateTime.parse("2023-01-03T00:00:00Z"))
38+
private val stream4 = StreamEntity(4, serviceId, "https://youtube.com/watch?v=4", "stream 4", StreamType.VIDEO_STREAM, 1000, "channel-2", "https://youtube.com/channel/2", "https://i.ytimg.com/vi/1/hqdefault.jpg", 100, "2023-08-10", OffsetDateTime.parse("2023-08-10T00:00:00Z"))
39+
private val stream5 = StreamEntity(5, serviceId, "https://youtube.com/watch?v=5", "stream 5", StreamType.VIDEO_STREAM, 1000, "channel-2", "https://youtube.com/channel/2", "https://i.ytimg.com/vi/1/hqdefault.jpg", 100, "2023-08-20", OffsetDateTime.parse("2023-08-20T00:00:00Z"))
40+
private val stream6 = StreamEntity(6, serviceId, "https://youtube.com/watch?v=6", "stream 6", StreamType.VIDEO_STREAM, 1000, "channel-3", "https://youtube.com/channel/3", "https://i.ytimg.com/vi/1/hqdefault.jpg", 100, "2023-09-01", OffsetDateTime.parse("2023-09-01T00:00:00Z"))
41+
private val stream7 = StreamEntity(7, serviceId, "https://youtube.com/watch?v=7", "stream 7", StreamType.VIDEO_STREAM, 1000, "channel-4", "https://youtube.com/channel/4", "https://i.ytimg.com/vi/1/hqdefault.jpg", 100, "2023-08-10", OffsetDateTime.parse("2023-08-10T00:00:00Z"))
42+
43+
private val allStreams = listOf(
44+
stream1, stream2, stream3, stream4, stream5, stream6, stream7
45+
)
46+
47+
@Before
48+
fun createDb() {
49+
val context = ApplicationProvider.getApplicationContext<Context>()
50+
db = Room.inMemoryDatabaseBuilder(
51+
context, AppDatabase::class.java
52+
).build()
53+
feedDAO = db.feedDAO()
54+
streamDAO = db.streamDAO()
55+
subscriptionDAO = db.subscriptionDAO()
56+
}
57+
58+
@After
59+
@Throws(IOException::class)
60+
fun closeDb() {
61+
db.close()
62+
}
63+
64+
@Test
65+
fun testUnlinkStreamsOlderThan_KeepOne() {
66+
setupUnlinkDelete("2023-08-15T00:00:00Z")
67+
val streams = feedDAO.getStreams(
68+
FeedGroupEntity.GROUP_ALL_ID, includePlayed = true, includePartiallyPlayed = true, null
69+
)
70+
.blockingGet()
71+
val allowedStreams = listOf(stream3, stream5, stream6, stream7)
72+
assertEqual(streams, allowedStreams)
73+
}
74+
75+
@Test
76+
fun testUnlinkStreamsOlderThan_KeepMultiple() {
77+
setupUnlinkDelete("2023-08-01T00:00:00Z")
78+
val streams = feedDAO.getStreams(
79+
FeedGroupEntity.GROUP_ALL_ID, includePlayed = true, includePartiallyPlayed = true, null
80+
)
81+
.blockingGet()
82+
val allowedStreams = listOf(stream3, stream4, stream5, stream6, stream7)
83+
assertEqual(streams, allowedStreams)
84+
}
85+
86+
private fun assertEqual(streams: List<StreamWithState>?, allowedStreams: List<StreamEntity>) {
87+
assertNotNull(streams)
88+
assertEquals(allowedStreams, streams!!.stream().map { it.stream }.toList().sortedBy { it.uid })
89+
}
90+
91+
private fun setupUnlinkDelete(time: String) {
92+
clearAndFillTables()
93+
Single.fromCallable {
94+
feedDAO.unlinkStreamsOlderThan(OffsetDateTime.parse(time))
95+
}.blockingSubscribe()
96+
Single.fromCallable {
97+
streamDAO.deleteOrphans()
98+
}.blockingSubscribe()
99+
}
100+
101+
private fun clearAndFillTables() {
102+
db.clearAllTables()
103+
streamDAO.insertAll(allStreams)
104+
subscriptionDAO.insertAll(
105+
listOf(
106+
SubscriptionEntity.from(ChannelInfo(serviceId, "1", "https://youtube.com/channel/1", "https://youtube.com/channel/1", "channel-1")),
107+
SubscriptionEntity.from(ChannelInfo(serviceId, "2", "https://youtube.com/channel/2", "https://youtube.com/channel/2", "channel-2")),
108+
SubscriptionEntity.from(ChannelInfo(serviceId, "3", "https://youtube.com/channel/3", "https://youtube.com/channel/3", "channel-3")),
109+
SubscriptionEntity.from(ChannelInfo(serviceId, "4", "https://youtube.com/channel/4", "https://youtube.com/channel/4", "channel-4")),
110+
)
111+
)
112+
feedDAO.insertAll(
113+
listOf(
114+
FeedEntity(1, 1),
115+
FeedEntity(2, 1),
116+
FeedEntity(3, 1),
117+
FeedEntity(4, 2),
118+
FeedEntity(5, 2),
119+
FeedEntity(6, 3),
120+
FeedEntity(7, 4),
121+
)
122+
)
123+
}
124+
}

app/src/androidTest/java/org/schabi/newpipe/local/subscription/SubscriptionManagerTest.java

+2-39
Original file line numberDiff line numberDiff line change
@@ -10,19 +10,13 @@
1010
import org.junit.Test;
1111
import org.schabi.newpipe.database.AppDatabase;
1212
import org.schabi.newpipe.database.feed.model.FeedGroupEntity;
13-
import org.schabi.newpipe.database.stream.model.StreamEntity;
1413
import org.schabi.newpipe.database.subscription.SubscriptionEntity;
1514
import org.schabi.newpipe.extractor.channel.ChannelInfo;
1615
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
17-
import org.schabi.newpipe.extractor.localization.DateWrapper;
18-
import org.schabi.newpipe.extractor.stream.StreamInfoItem;
19-
import org.schabi.newpipe.extractor.stream.StreamType;
2016
import org.schabi.newpipe.testUtil.TestDatabase;
2117
import org.schabi.newpipe.testUtil.TrampolineSchedulerRule;
2218

2319
import java.io.IOException;
24-
import java.time.OffsetDateTime;
25-
import java.util.Comparator;
2620
import java.util.List;
2721

2822
public class SubscriptionManagerTest {
@@ -58,7 +52,7 @@ public void testInsert() throws ExtractionException, IOException {
5852
final ChannelInfo info = ChannelInfo.getInfo("https://www.youtube.com/c/3blue1brown");
5953
final SubscriptionEntity subscription = SubscriptionEntity.from(info);
6054

61-
manager.insertSubscription(subscription, info);
55+
manager.insertSubscription(subscription);
6256
final SubscriptionEntity readSubscription = getAssertOneSubscriptionEntity();
6357

6458
// the uid has changed, since the uid is chosen upon inserting, but the rest should match
@@ -76,7 +70,7 @@ public void testUpdateNotificationMode() throws ExtractionException, IOException
7670
final SubscriptionEntity subscription = SubscriptionEntity.from(info);
7771
subscription.setNotificationMode(0);
7872

79-
manager.insertSubscription(subscription, info);
73+
manager.insertSubscription(subscription);
8074
manager.updateNotificationMode(subscription.getServiceId(), subscription.getUrl(), 1)
8175
.blockingAwait();
8276
final SubscriptionEntity anotherSubscription = getAssertOneSubscriptionEntity();
@@ -85,35 +79,4 @@ public void testUpdateNotificationMode() throws ExtractionException, IOException
8579
assertEquals(subscription.getUrl(), anotherSubscription.getUrl());
8680
assertEquals(1, anotherSubscription.getNotificationMode());
8781
}
88-
89-
@Test
90-
public void testRememberRecentStreams() throws ExtractionException, IOException {
91-
final ChannelInfo info = ChannelInfo.getInfo("https://www.youtube.com/c/Polyphia");
92-
final List<StreamInfoItem> relatedItems = List.of(
93-
new StreamInfoItem(0, "a", "b", StreamType.VIDEO_STREAM),
94-
new StreamInfoItem(1, "c", "d", StreamType.AUDIO_STREAM),
95-
new StreamInfoItem(2, "e", "f", StreamType.AUDIO_LIVE_STREAM),
96-
new StreamInfoItem(3, "g", "h", StreamType.LIVE_STREAM));
97-
relatedItems.forEach(item -> {
98-
// these two fields must be non-null for the insert to succeed
99-
item.setUploaderUrl(info.getUrl());
100-
item.setUploaderName(info.getName());
101-
// the upload date must not be too much in the past for the item to actually be inserted
102-
item.setUploadDate(new DateWrapper(OffsetDateTime.now()));
103-
});
104-
info.setRelatedItems(relatedItems);
105-
final SubscriptionEntity subscription = SubscriptionEntity.from(info);
106-
107-
manager.insertSubscription(subscription, info);
108-
final List<StreamEntity> streams = database.streamDAO().getAll().blockingFirst();
109-
110-
assertEquals(4, streams.size());
111-
streams.sort(Comparator.comparing(StreamEntity::getServiceId));
112-
for (int i = 0; i < 4; i++) {
113-
assertEquals(relatedItems.get(0).getServiceId(), streams.get(0).getServiceId());
114-
assertEquals(relatedItems.get(0).getUrl(), streams.get(0).getUrl());
115-
assertEquals(relatedItems.get(0).getName(), streams.get(0).getTitle());
116-
assertEquals(relatedItems.get(0).getStreamType(), streams.get(0).getStreamType());
117-
}
118-
}
11982
}

0 commit comments

Comments
 (0)