diff --git a/.gitignore b/.gitignore
index 1352b6917..3eafd4728 100644
--- a/.gitignore
+++ b/.gitignore
@@ -18,3 +18,5 @@ app/release/
bin/
.vscode/
*.code-workspace
+/key.properties
+/upload-keystore
diff --git a/README.md b/README.md
index 8ea216b3a..ffc350456 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,5 @@
-Extended NewPipe
+XPipe (Extended NewPipe)
A libre lightweight streaming front-end for Android.
diff --git a/app/build.gradle b/app/build.gradle
index 051414ba0..a15d7d818 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -11,13 +11,19 @@ plugins {
id "org.sonarqube" version "4.0.0.2929"
}
+def keystoreProperties = new Properties()
+def keystorePropertiesFile = rootProject.file('key.properties')
+if (keystorePropertiesFile.exists()) {
+ keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
+}
+
android {
compileSdk 33
namespace 'org.schabi.newpipe'
defaultConfig {
- applicationId "org.schabi.newpipe"
- resValue "string", "app_name", "NewPipe"
+ applicationId "org.schabi.xnewpipe"
+ resValue "string", "app_name", "XPipe"
minSdk 21
targetSdk 33
versionCode 994
@@ -32,6 +38,15 @@ android {
}
}
+ signingConfigs {
+ release {
+ keyAlias keystoreProperties['keyAlias']
+ keyPassword keystoreProperties['keyPassword']
+ storeFile keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : null
+ storePassword keystoreProperties['storePassword']
+ }
+ }
+
buildTypes {
debug {
debuggable true
@@ -60,6 +75,7 @@ android {
shrinkResources false // disabled to fix F-Droid's reproducible build
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
archivesBaseName = 'app'
+ signingConfig = signingConfigs.release
}
}
diff --git a/app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java
index 686e102f1..ee874701c 100644
--- a/app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java
+++ b/app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java
@@ -484,6 +484,8 @@ public final class VideoDetailFragment
binding.detailControlsShare.setOnClickListener(makeOnClickListener(info ->
ShareUtils.shareText(requireContext(), info.getName(), info.getUrl(),
info.getThumbnailUrl())));
+ binding.detailControlsOpenInYoutube.setOnClickListener(makeOnClickListener(info ->
+ ShareUtils.openUrlInYoutube(requireContext(), info.getUrl())));
binding.detailControlsOpenInBrowser.setOnClickListener(makeOnClickListener(info ->
ShareUtils.openUrlInBrowser(requireContext(), info.getUrl())));
binding.detailControlsPlayWithKodi.setOnClickListener(makeOnClickListener(info ->
diff --git a/app/src/main/java/org/schabi/newpipe/local/feed/FeedFragment.kt b/app/src/main/java/org/schabi/newpipe/local/feed/FeedFragment.kt
index 4f153dcf8..93b206181 100644
--- a/app/src/main/java/org/schabi/newpipe/local/feed/FeedFragment.kt
+++ b/app/src/main/java/org/schabi/newpipe/local/feed/FeedFragment.kt
@@ -92,7 +92,10 @@ class FeedFragment : BaseStateFragment() {
private val disposables = CompositeDisposable()
private lateinit var viewModel: FeedViewModel
- @State @JvmField var listState: Parcelable? = null
+
+ @State
+ @JvmField
+ var listState: Parcelable? = null
private var groupId = FeedGroupEntity.GROUP_ALL_ID
private var groupName = ""
@@ -126,7 +129,11 @@ class FeedFragment : BaseStateFragment() {
.registerOnSharedPreferenceChangeListener(onSettingsChangeListener)
}
- override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
return inflater.inflate(R.layout.fragment_feed, container, false)
}
@@ -183,10 +190,12 @@ class FeedFragment : BaseStateFragment() {
private fun setupListViewMode() {
// does everything needed to setup the layouts for grid or list modes
- groupAdapter.spanCount = if (shouldUseGridLayout(context)) getGridSpanCountStreams(context) else 1
- feedBinding.itemsList.layoutManager = GridLayoutManager(requireContext(), groupAdapter.spanCount).apply {
- spanSizeLookup = groupAdapter.spanSizeLookup
- }
+ groupAdapter.spanCount =
+ if (shouldUseGridLayout(context)) getGridSpanCountStreams(context) else 1
+ feedBinding.itemsList.layoutManager =
+ GridLayoutManager(requireContext(), groupAdapter.spanCount).apply {
+ spanSizeLookup = groupAdapter.spanSizeLookup
+ }
}
override fun initListeners() {
@@ -228,7 +237,10 @@ class FeedFragment : BaseStateFragment() {
.setMessage(R.string.feed_use_dedicated_fetch_method_help_text)
.setNeutralButton(enableDisableButtonText) { _, _ ->
sharedPreferences.edit {
- putBoolean(getString(R.string.feed_use_dedicated_fetch_method_key), !usingDedicatedMethod)
+ putBoolean(
+ getString(R.string.feed_use_dedicated_fetch_method_key),
+ !usingDedicatedMethod
+ )
}
}
.setPositiveButton(resources.getString(R.string.ok), null)
@@ -436,6 +448,11 @@ class FeedFragment : BaseStateFragment() {
showEmptyState()
} else {
hideLoading()
+ if (oldestSubscriptionUpdate == null || OffsetDateTime.now().minusHours(1)
+ .isAfter(oldestSubscriptionUpdate)
+ ) {
+ reloadContent()
+ }
}
}
@@ -665,7 +682,10 @@ class FeedFragment : BaseStateFragment() {
const val KEY_GROUP_NAME = "ARG_GROUP_NAME"
@JvmStatic
- fun newInstance(groupId: Long = FeedGroupEntity.GROUP_ALL_ID, groupName: String? = null): FeedFragment {
+ fun newInstance(
+ groupId: Long = FeedGroupEntity.GROUP_ALL_ID,
+ groupName: String? = null
+ ): FeedFragment {
val feedFragment = FeedFragment()
feedFragment.arguments = bundleOf(KEY_GROUP_ID to groupId, KEY_GROUP_NAME to groupName)
return feedFragment
diff --git a/app/src/main/java/org/schabi/newpipe/util/external_communication/ShareUtils.java b/app/src/main/java/org/schabi/newpipe/util/external_communication/ShareUtils.java
index 118b77026..458ea284f 100644
--- a/app/src/main/java/org/schabi/newpipe/util/external_communication/ShareUtils.java
+++ b/app/src/main/java/org/schabi/newpipe/util/external_communication/ShareUtils.java
@@ -58,6 +58,11 @@ public final class ShareUtils {
}
}
+ public static void openUrlInYoutube(@NonNull final Context context, @NonNull final String url) {
+ final Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
+ tryOpenIntentInApp(context, intent);
+ }
+
/**
* Open the url with the system default browser. If no browser is set as default, falls back to
* {@link #openAppChooser(Context, Intent, boolean)}.
@@ -198,9 +203,9 @@ public final class ShareUtils {
final ClipData.Item item = new ClipData.Item(intent.getData());
final String[] mimeTypes;
if (intent.getType() != null) {
- mimeTypes = new String[] {intent.getType()};
+ mimeTypes = new String[]{intent.getType()};
} else {
- mimeTypes = new String[] {};
+ mimeTypes = new String[]{};
}
targetClipData = new ClipData(null, mimeTypes, item);
}
@@ -370,9 +375,9 @@ public final class ShareUtils {
fileOutputStream.close();
final ClipData clipData = ClipData.newUri(applicationContext.getContentResolver(), "",
- FileProvider.getUriForFile(applicationContext,
- BuildConfig.APPLICATION_ID + ".provider",
- thumbnailPreviewFile));
+ FileProvider.getUriForFile(applicationContext,
+ BuildConfig.APPLICATION_ID + ".provider",
+ thumbnailPreviewFile));
if (DEBUG) {
Log.d(TAG, "ClipData successfully generated for Android share sheet: " + clipData);
diff --git a/app/src/main/res/layout/fragment_video_detail.xml b/app/src/main/res/layout/fragment_video_detail.xml
index 9aaf6d8d6..dcbd19f68 100644
--- a/app/src/main/res/layout/fragment_video_detail.xml
+++ b/app/src/main/res/layout/fragment_video_detail.xml
@@ -482,6 +482,7 @@
android:paddingHorizontal="@dimen/detail_control_padding"
android:paddingBottom="@dimen/detail_control_padding"
android:visibility="gone"
+ tools:background="@color/white"
tools:visibility="visible">
+
+
@color/black
@color/black
- #CD201F
+ #000000
#999999
#6C6C6C
diff --git a/app/src/main/res/values/colors_services.xml b/app/src/main/res/values/colors_services.xml
index f3487810a..04c5e055c 100644
--- a/app/src/main/res/values/colors_services.xml
+++ b/app/src/main/res/values/colors_services.xml
@@ -1,10 +1,10 @@
- #e53935
+ #000000
#000000
- #992722
+ #000000
#FFFFFF
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index e6fb35a16..e61ce232e 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -811,4 +811,5 @@
About
Channel tabs
What tabs are shown on the channel pages
+ Open in Youtube
\ No newline at end of file
diff --git a/gradle.properties b/gradle.properties
index 7b138b24e..7a28a2301 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -3,5 +3,5 @@ android.enableJetifier=false
android.nonFinalResIds=false
android.nonTransitiveRClass=false
android.useAndroidX=true
-org.gradle.jvmargs=-Xmx2048M --add-opens jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED
+org.gradle.jvmargs=-Xmx2048M --illegal-access=permit --add-opens jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED
systemProp.file.encoding=utf-8