mirror of
https://github.com/TeamNewPipe/NewPipe
synced 2026-02-10 04:00:16 +00:00
Compare commits
33 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6214ae33f3 | ||
|
|
37cef825a2 | ||
|
|
dab8e056e9 | ||
|
|
020dbdc82a | ||
|
|
5d7934249f | ||
|
|
d6be966db3 | ||
|
|
56a043669a | ||
|
|
85abc58158 | ||
|
|
955844b3e1 | ||
|
|
e74907561e | ||
|
|
1554f77762 | ||
|
|
118def08b4 | ||
|
|
725cb70cbd | ||
|
|
5525d206dc | ||
|
|
83f9646eec | ||
|
|
85d43fe45e | ||
|
|
8d6e68d6f4 | ||
|
|
07fe1e758a | ||
|
|
15b5cef6c2 | ||
|
|
ae60f7d7eb | ||
|
|
739b6ae57b | ||
|
|
cc33b685a5 | ||
|
|
d051e8ecc8 | ||
|
|
51e62f09ba | ||
|
|
8a2c47bc12 | ||
|
|
a7aad63bbb | ||
|
|
fd192b4f3f | ||
|
|
19e94bd30c | ||
|
|
7758a27694 | ||
|
|
a3301dcfb1 | ||
|
|
d045b27cea | ||
|
|
4f70235ee8 | ||
|
|
54f9bcb03e |
2
.github/workflows/backport-pr.yml
vendored
2
.github/workflows/backport-pr.yml
vendored
@@ -22,7 +22,7 @@ jobs:
|
||||
github.event.comment.author_association == 'MEMBER'
|
||||
)
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v6
|
||||
- name: Get backport metadata
|
||||
# the target branch is the first argument after `/backport`
|
||||
env:
|
||||
|
||||
2
.github/workflows/ci.yml
vendored
2
.github/workflows/ci.yml
vendored
@@ -38,7 +38,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: gradle/actions/wrapper-validation@v4
|
||||
- uses: gradle/actions/wrapper-validation@v5
|
||||
|
||||
- name: create and checkout branch
|
||||
# push events already checked out the branch
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import com.android.build.api.dsl.ApplicationExtension
|
||||
|
||||
plugins {
|
||||
alias(libs.plugins.android.application)
|
||||
alias(libs.plugins.jetbrains.kotlin.android)
|
||||
@@ -32,7 +34,7 @@ kotlin {
|
||||
}
|
||||
}
|
||||
|
||||
android {
|
||||
configure<ApplicationExtension> {
|
||||
compileSdk = 36
|
||||
namespace = "org.schabi.newpipe"
|
||||
|
||||
@@ -78,7 +80,10 @@ android {
|
||||
}
|
||||
isMinifyEnabled = true
|
||||
isShrinkResources = false // disabled to fix F-Droid"s reproducible build
|
||||
proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro")
|
||||
proguardFiles(
|
||||
getDefaultProguardFile("proguard-android-optimize.txt"),
|
||||
"proguard-rules.pro"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,7 +105,7 @@ android {
|
||||
|
||||
sourceSets {
|
||||
getByName("androidTest") {
|
||||
assets.srcDir("$projectDir/schemas")
|
||||
assets.directories += "$projectDir/schemas"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -111,6 +116,7 @@ android {
|
||||
buildFeatures {
|
||||
viewBinding = true
|
||||
buildConfig = true
|
||||
resValues = true
|
||||
}
|
||||
|
||||
packaging {
|
||||
|
||||
5
app/proguard-rules.pro
vendored
5
app/proguard-rules.pro
vendored
@@ -39,3 +39,8 @@
|
||||
|
||||
## For some reason NotificationModeConfigFragment wasn't kept (only referenced in a preference xml)
|
||||
-keep class org.schabi.newpipe.settings.notifications.** { *; }
|
||||
|
||||
# Prevent R8 from stripping or renaming Protobuf internal fields
|
||||
-keepclassmembers class * extends com.google.protobuf.GeneratedMessageLite {
|
||||
<fields>;
|
||||
}
|
||||
|
||||
@@ -92,7 +92,7 @@ class AboutActivity : AppCompatActivity() {
|
||||
return when (position) {
|
||||
posAbout -> AboutFragment()
|
||||
posLicense -> LicenseFragment.newInstance(SOFTWARE_COMPONENTS)
|
||||
else -> throw IllegalArgumentException("Unknown position for ViewPager2")
|
||||
else -> error("Unknown position for ViewPager2")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -105,7 +105,7 @@ class AboutActivity : AppCompatActivity() {
|
||||
return when (position) {
|
||||
posAbout -> R.string.tab_about
|
||||
posLicense -> R.string.tab_licenses
|
||||
else -> throw IllegalArgumentException("Unknown position for ViewPager2")
|
||||
else -> error("Unknown position for ViewPager2")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,7 +87,7 @@ abstract class StreamDAO : BasicDAO<StreamEntity> {
|
||||
|
||||
private fun compareAndUpdateStream(newerStream: StreamEntity) {
|
||||
val existentMinimalStream = getMinimalStreamForCompare(newerStream.serviceId, newerStream.url)
|
||||
?: throw IllegalStateException("Stream cannot be null just after insertion.")
|
||||
?: error("Stream cannot be null just after insertion.")
|
||||
newerStream.uid = existentMinimalStream.uid
|
||||
|
||||
if (!StreamTypeUtil.isLiveStream(newerStream.streamType)) {
|
||||
|
||||
@@ -100,7 +100,7 @@ abstract class SubscriptionDAO : BasicDAO<SubscriptionEntity> {
|
||||
entity.uid = uidFromInsert
|
||||
} else {
|
||||
val subscriptionIdFromDb = getSubscriptionIdInternal(entity.serviceId, entity.url!!)
|
||||
?: throw IllegalStateException("Subscription cannot be null just after insertion.")
|
||||
?: error("Subscription cannot be null just after insertion.")
|
||||
entity.uid = subscriptionIdFromDb
|
||||
|
||||
update(entity)
|
||||
|
||||
@@ -1,131 +0,0 @@
|
||||
package org.schabi.newpipe.info_list;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import org.schabi.newpipe.extractor.InfoItem;
|
||||
import org.schabi.newpipe.extractor.channel.ChannelInfoItem;
|
||||
import org.schabi.newpipe.extractor.comments.CommentsInfoItem;
|
||||
import org.schabi.newpipe.extractor.playlist.PlaylistInfoItem;
|
||||
import org.schabi.newpipe.extractor.stream.StreamInfoItem;
|
||||
import org.schabi.newpipe.info_list.holder.ChannelInfoItemHolder;
|
||||
import org.schabi.newpipe.info_list.holder.ChannelMiniInfoItemHolder;
|
||||
import org.schabi.newpipe.info_list.holder.CommentInfoItemHolder;
|
||||
import org.schabi.newpipe.info_list.holder.InfoItemHolder;
|
||||
import org.schabi.newpipe.info_list.holder.PlaylistInfoItemHolder;
|
||||
import org.schabi.newpipe.info_list.holder.PlaylistMiniInfoItemHolder;
|
||||
import org.schabi.newpipe.info_list.holder.StreamInfoItemHolder;
|
||||
import org.schabi.newpipe.info_list.holder.StreamMiniInfoItemHolder;
|
||||
import org.schabi.newpipe.local.history.HistoryRecordManager;
|
||||
import org.schabi.newpipe.util.OnClickGesture;
|
||||
|
||||
/*
|
||||
* Created by Christian Schabesberger on 26.09.16.
|
||||
* <p>
|
||||
* Copyright (C) Christian Schabesberger 2016 <chris.schabesberger@mailbox.org>
|
||||
* InfoItemBuilder.java is part of NewPipe.
|
||||
* </p>
|
||||
* <p>
|
||||
* NewPipe is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
* </p>
|
||||
* <p>
|
||||
* NewPipe is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
* </p>
|
||||
* <p>
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with NewPipe. If not, see <http://www.gnu.org/licenses/>.
|
||||
* </p>
|
||||
*/
|
||||
|
||||
public class InfoItemBuilder {
|
||||
private final Context context;
|
||||
|
||||
private OnClickGesture<StreamInfoItem> onStreamSelectedListener;
|
||||
private OnClickGesture<ChannelInfoItem> onChannelSelectedListener;
|
||||
private OnClickGesture<PlaylistInfoItem> onPlaylistSelectedListener;
|
||||
private OnClickGesture<CommentsInfoItem> onCommentsSelectedListener;
|
||||
|
||||
public InfoItemBuilder(final Context context) {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
public View buildView(@NonNull final ViewGroup parent, @NonNull final InfoItem infoItem,
|
||||
final HistoryRecordManager historyRecordManager) {
|
||||
return buildView(parent, infoItem, historyRecordManager, false);
|
||||
}
|
||||
|
||||
public View buildView(@NonNull final ViewGroup parent, @NonNull final InfoItem infoItem,
|
||||
final HistoryRecordManager historyRecordManager,
|
||||
final boolean useMiniVariant) {
|
||||
final InfoItemHolder holder =
|
||||
holderFromInfoType(parent, infoItem.getInfoType(), useMiniVariant);
|
||||
holder.updateFromItem(infoItem, historyRecordManager);
|
||||
return holder.itemView;
|
||||
}
|
||||
|
||||
private InfoItemHolder holderFromInfoType(@NonNull final ViewGroup parent,
|
||||
@NonNull final InfoItem.InfoType infoType,
|
||||
final boolean useMiniVariant) {
|
||||
switch (infoType) {
|
||||
case STREAM:
|
||||
return useMiniVariant ? new StreamMiniInfoItemHolder(this, parent)
|
||||
: new StreamInfoItemHolder(this, parent);
|
||||
case CHANNEL:
|
||||
return useMiniVariant ? new ChannelMiniInfoItemHolder(this, parent)
|
||||
: new ChannelInfoItemHolder(this, parent);
|
||||
case PLAYLIST:
|
||||
return useMiniVariant ? new PlaylistMiniInfoItemHolder(this, parent)
|
||||
: new PlaylistInfoItemHolder(this, parent);
|
||||
case COMMENT:
|
||||
return new CommentInfoItemHolder(this, parent);
|
||||
default:
|
||||
throw new RuntimeException("InfoType not expected = " + infoType.name());
|
||||
}
|
||||
}
|
||||
|
||||
public Context getContext() {
|
||||
return context;
|
||||
}
|
||||
|
||||
public OnClickGesture<StreamInfoItem> getOnStreamSelectedListener() {
|
||||
return onStreamSelectedListener;
|
||||
}
|
||||
|
||||
public void setOnStreamSelectedListener(final OnClickGesture<StreamInfoItem> listener) {
|
||||
this.onStreamSelectedListener = listener;
|
||||
}
|
||||
|
||||
public OnClickGesture<ChannelInfoItem> getOnChannelSelectedListener() {
|
||||
return onChannelSelectedListener;
|
||||
}
|
||||
|
||||
public void setOnChannelSelectedListener(final OnClickGesture<ChannelInfoItem> listener) {
|
||||
this.onChannelSelectedListener = listener;
|
||||
}
|
||||
|
||||
public OnClickGesture<PlaylistInfoItem> getOnPlaylistSelectedListener() {
|
||||
return onPlaylistSelectedListener;
|
||||
}
|
||||
|
||||
public void setOnPlaylistSelectedListener(final OnClickGesture<PlaylistInfoItem> listener) {
|
||||
this.onPlaylistSelectedListener = listener;
|
||||
}
|
||||
|
||||
public OnClickGesture<CommentsInfoItem> getOnCommentsSelectedListener() {
|
||||
return onCommentsSelectedListener;
|
||||
}
|
||||
|
||||
public void setOnCommentsSelectedListener(
|
||||
final OnClickGesture<CommentsInfoItem> onCommentsSelectedListener) {
|
||||
this.onCommentsSelectedListener = onCommentsSelectedListener;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2016-2026 NewPipe contributors <https://newpipe.net>
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
package org.schabi.newpipe.info_list
|
||||
|
||||
import android.content.Context
|
||||
import org.schabi.newpipe.extractor.channel.ChannelInfoItem
|
||||
import org.schabi.newpipe.extractor.comments.CommentsInfoItem
|
||||
import org.schabi.newpipe.extractor.playlist.PlaylistInfoItem
|
||||
import org.schabi.newpipe.extractor.stream.StreamInfoItem
|
||||
import org.schabi.newpipe.util.OnClickGesture
|
||||
|
||||
class InfoItemBuilder(val context: Context) {
|
||||
var onStreamSelectedListener: OnClickGesture<StreamInfoItem>? = null
|
||||
var onChannelSelectedListener: OnClickGesture<ChannelInfoItem>? = null
|
||||
var onPlaylistSelectedListener: OnClickGesture<PlaylistInfoItem>? = null
|
||||
var onCommentsSelectedListener: OnClickGesture<CommentsInfoItem>? = null
|
||||
}
|
||||
@@ -111,7 +111,8 @@ class FeedLoadManager(private val context: Context) {
|
||||
broadcastProgress()
|
||||
}
|
||||
.observeOn(Schedulers.io())
|
||||
.flatMap { Flowable.fromIterable(it) }
|
||||
// Randomize user subscription ordering to attempt to resist fingerprinting
|
||||
.flatMap { Flowable.fromIterable(it.shuffled()) }
|
||||
.takeWhile { !cancelSignal.get() }
|
||||
.doOnNext { subscriptionEntity ->
|
||||
// throttle YouTube extractions once every BATCH_SIZE to avoid being rate limited
|
||||
|
||||
@@ -22,7 +22,7 @@ internal fun infoItemTypeToString(type: InfoType): String {
|
||||
InfoType.STREAM -> ID_STREAM
|
||||
InfoType.PLAYLIST -> ID_PLAYLIST
|
||||
InfoType.CHANNEL -> ID_CHANNEL
|
||||
else -> throw IllegalStateException("Unexpected value: $type")
|
||||
else -> error("Unexpected value: $type")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ internal fun infoItemTypeFromString(type: String): InfoType {
|
||||
ID_STREAM -> InfoType.STREAM
|
||||
ID_PLAYLIST -> InfoType.PLAYLIST
|
||||
ID_CHANNEL -> InfoType.CHANNEL
|
||||
else -> throw IllegalStateException("Unexpected value: $type")
|
||||
else -> error("Unexpected value: $type")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -82,11 +82,11 @@ internal class PackageValidator(context: Context) {
|
||||
|
||||
// Build the caller info for the rest of the checks here.
|
||||
val callerPackageInfo = buildCallerInfo(callingPackage)
|
||||
?: throw IllegalStateException("Caller wasn't found in the system?")
|
||||
?: error("Caller wasn't found in the system?")
|
||||
|
||||
// Verify that things aren't ... broken. (This test should always pass.)
|
||||
if (callerPackageInfo.uid != callingUid) {
|
||||
throw IllegalStateException("Caller's package UID doesn't match caller's actual UID?")
|
||||
check(callerPackageInfo.uid == callingUid) {
|
||||
"Caller's package UID doesn't match caller's actual UID?"
|
||||
}
|
||||
|
||||
val callerSignature = callerPackageInfo.signature
|
||||
@@ -202,7 +202,7 @@ internal class PackageValidator(context: Context) {
|
||||
*/
|
||||
private fun getSystemSignature(): String = getPackageInfo(ANDROID_PLATFORM)?.let { platformInfo ->
|
||||
getSignature(platformInfo)
|
||||
} ?: throw IllegalStateException("Platform signature not found")
|
||||
} ?: error("Platform signature not found")
|
||||
|
||||
/**
|
||||
* Creates a SHA-256 signature given a certificate byte array.
|
||||
|
||||
@@ -9,8 +9,9 @@ import com.grack.nanojson.JsonParserException;
|
||||
import com.grack.nanojson.JsonStringWriter;
|
||||
import com.grack.nanojson.JsonWriter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Class to get a JSON representation of a list of tabs, and the other way around.
|
||||
@@ -44,39 +45,25 @@ public final class TabsJsonHelper {
|
||||
return getDefaultTabs();
|
||||
}
|
||||
|
||||
final List<Tab> returnTabs = new ArrayList<>();
|
||||
|
||||
final JsonObject outerJsonObject;
|
||||
try {
|
||||
outerJsonObject = JsonParser.object().from(tabsJson);
|
||||
final JsonObject outerJsonObject = JsonParser.object().from(tabsJson);
|
||||
|
||||
if (!outerJsonObject.has(JSON_TABS_ARRAY_KEY)) {
|
||||
throw new InvalidJsonException("JSON doesn't contain \"" + JSON_TABS_ARRAY_KEY
|
||||
+ "\" array");
|
||||
}
|
||||
|
||||
final JsonArray tabsArray = outerJsonObject.getArray(JSON_TABS_ARRAY_KEY);
|
||||
final JsonArray tabsArray = outerJsonObject.getArray(JSON_TABS_ARRAY_KEY, null);
|
||||
|
||||
for (final Object o : tabsArray) {
|
||||
if (!(o instanceof JsonObject)) {
|
||||
continue;
|
||||
}
|
||||
final var returnTabs = tabsArray.streamAsJsonObjects()
|
||||
.map(Tab::from)
|
||||
.filter(Objects::nonNull)
|
||||
.collect(Collectors.toUnmodifiableList());
|
||||
|
||||
final Tab tab = Tab.from((JsonObject) o);
|
||||
|
||||
if (tab != null) {
|
||||
returnTabs.add(tab);
|
||||
}
|
||||
}
|
||||
return returnTabs.isEmpty() ? getDefaultTabs() : returnTabs;
|
||||
} catch (final JsonParserException e) {
|
||||
throw new InvalidJsonException(e);
|
||||
}
|
||||
|
||||
if (returnTabs.isEmpty()) {
|
||||
return getDefaultTabs();
|
||||
}
|
||||
|
||||
return returnTabs;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
android.enableJetifier=false
|
||||
android.nonFinalResIds=false
|
||||
android.nonTransitiveRClass=true
|
||||
android.useAndroidX=true
|
||||
org.gradle.jvmargs=-Xmx2048M --add-opens jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED
|
||||
systemProp.file.encoding=utf-8
|
||||
|
||||
@@ -23,8 +23,8 @@ groupie = "2.10.1"
|
||||
jsoup = "1.22.1"
|
||||
junit = "4.13.2"
|
||||
junit-ext = "1.3.0"
|
||||
kotlin = "2.2.21"
|
||||
ksp = "2.3.4"
|
||||
kotlin = "2.3.0"
|
||||
ksp = "2.3.5"
|
||||
ktlint = "1.8.0"
|
||||
leakcanary = "2.14"
|
||||
lifecycle = "2.9.4" # Newer versions require minSdk >= 23
|
||||
|
||||
Reference in New Issue
Block a user