From ce0a41e32d73db07990b0eb541c0d23f99709b78 Mon Sep 17 00:00:00 2001 From: Isira Seneviratne Date: Wed, 27 May 2026 06:28:11 +0530 Subject: [PATCH 1/5] Handle Description conversion to record class --- .../fragments/detail/BaseDescriptionFragment.java | 8 +++----- .../fragments/detail/DescriptionFragment.java | 6 +++--- .../list/channel/ChannelAboutFragment.java | 4 ++-- .../fragments/list/playlist/PlaylistFragment.java | 12 ++++++------ .../ui/components/common/DescriptionText.kt | 2 +- .../newpipe/ui/components/video/comment/Comment.kt | 8 ++++---- .../video/comment/CommentRepliesDialog.kt | 4 ++-- .../video/comment/CommentRepliesHeader.kt | 2 +- .../ui/components/video/comment/CommentSection.kt | 4 ++-- .../org/schabi/newpipe/util/ExtractorHelper.java | 2 +- .../schabi/newpipe/util/text/TextLinkifier.java | 14 +++++++------- 11 files changed, 32 insertions(+), 34 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/fragments/detail/BaseDescriptionFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/detail/BaseDescriptionFragment.java index bd174a12155..89b8f97c134 100644 --- a/app/src/main/java/org/schabi/newpipe/fragments/detail/BaseDescriptionFragment.java +++ b/app/src/main/java/org/schabi/newpipe/fragments/detail/BaseDescriptionFragment.java @@ -1,6 +1,5 @@ package org.schabi.newpipe.fragments.detail; -import static android.text.TextUtils.isEmpty; import static org.schabi.newpipe.extractor.utils.Utils.isBlank; import static org.schabi.newpipe.util.text.TextLinkifier.SET_LINK_MOVEMENT_METHOD; @@ -66,7 +65,7 @@ public void onDestroy() { * Get the description to display. * @return description object, if available */ - @Nullable + @NonNull protected abstract Description getDescription(); /** @@ -105,8 +104,7 @@ public void onDestroy() { private void setupDescription() { final Description description = getDescription(); - if (description == null || isEmpty(description.getContent()) - || description == Description.EMPTY_DESCRIPTION) { + if (description.equals(Description.EMPTY_DESCRIPTION)) { binding.detailDescriptionView.setVisibility(View.GONE); binding.detailSelectDescriptionButton.setVisibility(View.GONE); return; @@ -138,7 +136,7 @@ private void enableDescriptionSelection() { private void disableDescriptionSelection() { // show description content again, otherwise some links are not clickable final Description description = getDescription(); - if (description != null) { + if (!description.equals(Description.EMPTY_DESCRIPTION)) { TextLinkifier.fromDescription(binding.detailDescriptionView, description, HtmlCompat.FROM_HTML_MODE_LEGACY, getService(), getStreamUrl(), diff --git a/app/src/main/java/org/schabi/newpipe/fragments/detail/DescriptionFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/detail/DescriptionFragment.java index 2b0d22a32ed..c8fae1d5033 100644 --- a/app/src/main/java/org/schabi/newpipe/fragments/detail/DescriptionFragment.java +++ b/app/src/main/java/org/schabi/newpipe/fragments/detail/DescriptionFragment.java @@ -8,7 +8,6 @@ import android.widget.LinearLayout; import androidx.annotation.NonNull; -import androidx.annotation.Nullable; import androidx.annotation.StringRes; import com.evernote.android.state.State; @@ -35,10 +34,11 @@ public DescriptionFragment() { } - @Nullable + @NonNull @Override protected Description getDescription() { - return streamInfo.getDescription(); + final var description = streamInfo.getDescription(); + return description != null ? description : Description.EMPTY_DESCRIPTION; } @NonNull diff --git a/app/src/main/java/org/schabi/newpipe/fragments/list/channel/ChannelAboutFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/list/channel/ChannelAboutFragment.java index e3a39813904..f0efe409ad0 100644 --- a/app/src/main/java/org/schabi/newpipe/fragments/list/channel/ChannelAboutFragment.java +++ b/app/src/main/java/org/schabi/newpipe/fragments/list/channel/ChannelAboutFragment.java @@ -40,10 +40,10 @@ protected void initViews(final View rootView, final Bundle savedInstanceState) { binding.constraintLayout.setPadding(0, DeviceUtils.dpToPx(8, requireContext()), 0, 0); } - @Nullable + @NonNull @Override protected Description getDescription() { - return new Description(channelInfo.getDescription(), Description.PLAIN_TEXT); + return Description.of(channelInfo.getDescription(), Description.Type.PLAIN_TEXT); } @NonNull diff --git a/app/src/main/java/org/schabi/newpipe/fragments/list/playlist/PlaylistFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/list/playlist/PlaylistFragment.java index 8f0c3ac98e6..db002453785 100644 --- a/app/src/main/java/org/schabi/newpipe/fragments/list/playlist/PlaylistFragment.java +++ b/app/src/main/java/org/schabi/newpipe/fragments/list/playlist/PlaylistFragment.java @@ -1,6 +1,5 @@ package org.schabi.newpipe.fragments.list.playlist; -import static org.schabi.newpipe.extractor.utils.Utils.isBlank; import static org.schabi.newpipe.ktx.ViewUtils.animate; import static org.schabi.newpipe.ktx.ViewUtils.animateHideRecyclerViewAllowingScrolling; import static org.schabi.newpipe.util.ServiceHelper.getServiceById; @@ -58,6 +57,7 @@ import java.util.ArrayList; import java.util.List; +import java.util.Optional; import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.Supplier; import java.util.stream.Collectors; @@ -328,11 +328,11 @@ public void handleResult(@NonNull final PlaylistInfo result) { streamCount = result.getStreamCount(); setStreamCountAndOverallDuration(result.getRelatedItems(), !result.hasNextPage()); - final Description description = result.getDescription(); - if (description != null && description != Description.EMPTY_DESCRIPTION - && !isBlank(description.getContent())) { - final TextEllipsizer ellipsizer = new TextEllipsizer( - headerBinding.playlistDescription, 5, getServiceById(result.getServiceId())); + final var description = Optional.ofNullable(result.getDescription()) + .orElse(Description.EMPTY_DESCRIPTION); + if (!description.equals(Description.EMPTY_DESCRIPTION)) { + final var ellipsizer = new TextEllipsizer(headerBinding.playlistDescription, 5, + getServiceById(result.getServiceId())); ellipsizer.setStateChangeListener(isEllipsized -> headerBinding.playlistDescriptionReadMore.setText( Boolean.TRUE.equals(isEllipsized) ? R.string.show_more : R.string.show_less diff --git a/app/src/main/java/org/schabi/newpipe/ui/components/common/DescriptionText.kt b/app/src/main/java/org/schabi/newpipe/ui/components/common/DescriptionText.kt index 40c5903c5e8..69472b2ced7 100644 --- a/app/src/main/java/org/schabi/newpipe/ui/components/common/DescriptionText.kt +++ b/app/src/main/java/org/schabi/newpipe/ui/components/common/DescriptionText.kt @@ -35,7 +35,7 @@ fun DescriptionText( fun rememberParsedDescription(description: Description): AnnotatedString { // TODO: Handle links and hashtags, Markdown. return remember(description) { - if (description.type == Description.HTML) { + if (description.type == Description.Type.HTML) { val styles = TextLinkStyles(SpanStyle(textDecoration = TextDecoration.Underline)) AnnotatedString.fromHtml(description.content, styles) } else { diff --git a/app/src/main/java/org/schabi/newpipe/ui/components/video/comment/Comment.kt b/app/src/main/java/org/schabi/newpipe/ui/components/video/comment/Comment.kt index 8864f8253df..69c82f78b66 100644 --- a/app/src/main/java/org/schabi/newpipe/ui/components/video/comment/Comment.kt +++ b/app/src/main/java/org/schabi/newpipe/ui/components/video/comment/Comment.kt @@ -219,7 +219,7 @@ fun CommentsInfoItem( private class CommentPreviewProvider : CollectionPreviewParameterProvider( listOf( CommentsInfoItem( - commentText = Description("Hello world!\n\nThis line should be hidden by default.", Description.PLAIN_TEXT), + commentText = Description("Hello world!\n\nThis line should be hidden by default.", Description.Type.PLAIN_TEXT), uploaderName = "Test", likeCount = 100, isPinned = false, @@ -228,7 +228,7 @@ private class CommentPreviewProvider : CollectionPreviewParameterProvider
This line should be hidden by default.", Description.HTML), + commentText = Description("Hello world, long long long text lorem ipsum dolor sit amet!

This line should be hidden by default.", Description.Type.HTML), uploaderName = "Test", likeCount = 92847, isPinned = true, @@ -237,7 +237,7 @@ private class CommentPreviewProvider : CollectionPreviewParameterProvider
This line should be hidden by default.", Description.HTML), + commentText = Description("Hello world, long long long text lorem ipsum dolor sit amet!

This line should be hidden by default.", Description.Type.HTML), uploaderName = "Test really long long long long lorem ipsum dolor sit amet consectetur", likeCount = 92847, isPinned = true, @@ -246,7 +246,7 @@ private class CommentPreviewProvider : CollectionPreviewParameterProvider @Composable fun CommentRepliesHeaderPreview() { val comment = CommentsInfoItem( - commentText = Description(LoremIpsum(50).values.first(), Description.PLAIN_TEXT), + commentText = Description(LoremIpsum(50).values.first(), Description.Type.PLAIN_TEXT), uploaderName = "Test really long lorem ipsum dolor sit", likeCount = 1000, isPinned = true, diff --git a/app/src/main/java/org/schabi/newpipe/ui/components/video/comment/CommentSection.kt b/app/src/main/java/org/schabi/newpipe/ui/components/video/comment/CommentSection.kt index b26457d1e29..e3df2603e3a 100644 --- a/app/src/main/java/org/schabi/newpipe/ui/components/video/comment/CommentSection.kt +++ b/app/src/main/java/org/schabi/newpipe/ui/components/video/comment/CommentSection.kt @@ -219,7 +219,7 @@ private fun CommentSectionSuccessPreview() { CommentsInfoItem( commentText = Description( "Comment 1\n\nThis line should be hidden by default.", - Description.PLAIN_TEXT + Description.Type.PLAIN_TEXT ), uploaderName = "Test", replies = Page(""), @@ -227,7 +227,7 @@ private fun CommentSectionSuccessPreview() { ) ) + (2..10).map { CommentsInfoItem( - commentText = Description("Comment $it", Description.PLAIN_TEXT), + commentText = Description("Comment $it", Description.Type.PLAIN_TEXT), uploaderName = "Test" ) } diff --git a/app/src/main/java/org/schabi/newpipe/util/ExtractorHelper.java b/app/src/main/java/org/schabi/newpipe/util/ExtractorHelper.java index 83f2332ed87..09f6e13126e 100644 --- a/app/src/main/java/org/schabi/newpipe/util/ExtractorHelper.java +++ b/app/src/main/java/org/schabi/newpipe/util/ExtractorHelper.java @@ -286,7 +286,7 @@ public static void showMetaInfoInTextView(@Nullable final List metaInf .append(Localization.DOT_SEPARATOR); } - String content = metaInfo.getContent().getContent().trim(); + String content = metaInfo.getContent().content().trim(); if (content.endsWith(".")) { content = content.substring(0, content.length() - 1); // remove . at end } diff --git a/app/src/main/java/org/schabi/newpipe/util/text/TextLinkifier.java b/app/src/main/java/org/schabi/newpipe/util/text/TextLinkifier.java index 4221da39841..efdd1daa002 100644 --- a/app/src/main/java/org/schabi/newpipe/util/text/TextLinkifier.java +++ b/app/src/main/java/org/schabi/newpipe/util/text/TextLinkifier.java @@ -67,17 +67,17 @@ public static void fromDescription(@NonNull final TextView textView, @Nullable final String relatedStreamUrl, @NonNull final CompositeDisposable disposables, @Nullable final Consumer onCompletion) { - switch (description.getType()) { - case Description.HTML: - TextLinkifier.fromHtml(textView, description.getContent(), htmlCompatFlag, + switch (description.type()) { + case Description.Type.HTML: + TextLinkifier.fromHtml(textView, description.content(), htmlCompatFlag, relatedInfoService, relatedStreamUrl, disposables, onCompletion); break; - case Description.MARKDOWN: - TextLinkifier.fromMarkdown(textView, description.getContent(), + case Description.Type.MARKDOWN: + TextLinkifier.fromMarkdown(textView, description.content(), relatedInfoService, relatedStreamUrl, disposables, onCompletion); break; - case Description.PLAIN_TEXT: default: - TextLinkifier.fromPlainText(textView, description.getContent(), + case Description.Type.PLAIN_TEXT: default: + TextLinkifier.fromPlainText(textView, description.content(), relatedInfoService, relatedStreamUrl, disposables, onCompletion); break; } From 96481628a61daacf78cfedc4bdd3aa6160a37ae1 Mon Sep 17 00:00:00 2001 From: Isira Seneviratne Date: Wed, 27 May 2026 07:55:30 +0530 Subject: [PATCH 2/5] Add commit hash --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 777459e64e1..5f646c3241f 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -66,7 +66,7 @@ teamnewpipe-nanojson = "e9d656ddb49a412a5a0a5d5ef20ca7ef09549996" # the corresponding commit hash, since JitPack sometimes deletes artifacts. # If there’s already a git hash, just add more of it to the end (or remove a letter) # to cause jitpack to regenerate the artifact. -teamnewpipe-newpipe-extractor = "1512cf3222b0c5d87a249e6ac231b98090c42623" +teamnewpipe-newpipe-extractor = "70661defa1d18117b98a4c35b9918c75dfb91e64" webkit = "1.15.0" work = "2.11.2" From 420bcc528e5a70466904db86f2e2f354b7427f46 Mon Sep 17 00:00:00 2001 From: Isira Seneviratne Date: Wed, 27 May 2026 08:14:07 +0530 Subject: [PATCH 3/5] Use Optional --- .../newpipe/fragments/detail/BaseDescriptionFragment.java | 7 ++++--- .../newpipe/fragments/detail/DescriptionFragment.java | 6 +++--- .../fragments/list/channel/ChannelAboutFragment.java | 6 ++++-- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/fragments/detail/BaseDescriptionFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/detail/BaseDescriptionFragment.java index 89b8f97c134..486622819d7 100644 --- a/app/src/main/java/org/schabi/newpipe/fragments/detail/BaseDescriptionFragment.java +++ b/app/src/main/java/org/schabi/newpipe/fragments/detail/BaseDescriptionFragment.java @@ -37,6 +37,7 @@ import org.schabi.newpipe.util.text.TextLinkifier; import java.util.List; +import java.util.Optional; import io.reactivex.rxjava3.disposables.CompositeDisposable; @@ -66,7 +67,7 @@ public void onDestroy() { * @return description object, if available */ @NonNull - protected abstract Description getDescription(); + protected abstract Optional getDescription(); /** * Get the streaming service. Used for generating description links. @@ -103,7 +104,7 @@ public void onDestroy() { protected abstract void setupMetadata(LayoutInflater inflater, LinearLayout layout); private void setupDescription() { - final Description description = getDescription(); + final var description = getDescription().orElse(Description.EMPTY_DESCRIPTION); if (description.equals(Description.EMPTY_DESCRIPTION)) { binding.detailDescriptionView.setVisibility(View.GONE); binding.detailSelectDescriptionButton.setVisibility(View.GONE); @@ -135,7 +136,7 @@ private void enableDescriptionSelection() { private void disableDescriptionSelection() { // show description content again, otherwise some links are not clickable - final Description description = getDescription(); + final var description = getDescription().orElse(Description.EMPTY_DESCRIPTION); if (!description.equals(Description.EMPTY_DESCRIPTION)) { TextLinkifier.fromDescription(binding.detailDescriptionView, description, HtmlCompat.FROM_HTML_MODE_LEGACY, diff --git a/app/src/main/java/org/schabi/newpipe/fragments/detail/DescriptionFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/detail/DescriptionFragment.java index c8fae1d5033..4675e9ac54f 100644 --- a/app/src/main/java/org/schabi/newpipe/fragments/detail/DescriptionFragment.java +++ b/app/src/main/java/org/schabi/newpipe/fragments/detail/DescriptionFragment.java @@ -19,6 +19,7 @@ import org.schabi.newpipe.util.Localization; import java.util.List; +import java.util.Optional; public class DescriptionFragment extends BaseDescriptionFragment { @@ -36,9 +37,8 @@ public DescriptionFragment() { @NonNull @Override - protected Description getDescription() { - final var description = streamInfo.getDescription(); - return description != null ? description : Description.EMPTY_DESCRIPTION; + protected Optional getDescription() { + return Optional.ofNullable(streamInfo.getDescription()); } @NonNull diff --git a/app/src/main/java/org/schabi/newpipe/fragments/list/channel/ChannelAboutFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/list/channel/ChannelAboutFragment.java index f0efe409ad0..4dfd72e217a 100644 --- a/app/src/main/java/org/schabi/newpipe/fragments/list/channel/ChannelAboutFragment.java +++ b/app/src/main/java/org/schabi/newpipe/fragments/list/channel/ChannelAboutFragment.java @@ -21,6 +21,7 @@ import org.schabi.newpipe.util.Localization; import java.util.List; +import java.util.Optional; public class ChannelAboutFragment extends BaseDescriptionFragment { @State @@ -42,8 +43,9 @@ protected void initViews(final View rootView, final Bundle savedInstanceState) { @NonNull @Override - protected Description getDescription() { - return Description.of(channelInfo.getDescription(), Description.Type.PLAIN_TEXT); + protected Optional getDescription() { + final var description = Description.of(channelInfo.getDescription(), Description.Type.PLAIN_TEXT); + return Optional.of(description); } @NonNull From d759e86c2c61b39b1349305340ceca0a854d414e Mon Sep 17 00:00:00 2001 From: Isira Seneviratne Date: Wed, 27 May 2026 08:14:19 +0530 Subject: [PATCH 4/5] Fix test --- .../video/comment/CommentSectionInstrumentedTest.kt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/src/androidTest/java/org/schabi/newpipe/ui/components/video/comment/CommentSectionInstrumentedTest.kt b/app/src/androidTest/java/org/schabi/newpipe/ui/components/video/comment/CommentSectionInstrumentedTest.kt index 78088f4a217..f47882ce803 100644 --- a/app/src/androidTest/java/org/schabi/newpipe/ui/components/video/comment/CommentSectionInstrumentedTest.kt +++ b/app/src/androidTest/java/org/schabi/newpipe/ui/components/video/comment/CommentSectionInstrumentedTest.kt @@ -89,7 +89,7 @@ class CommentSectionInstrumentedTest { fun commentListLoadsAndScrolls() { val comments = (1..25).map { index -> CommentsInfoItem( - commentText = Description("Comment $index", Description.PLAIN_TEXT), + commentText = Description("Comment $index", Description.Type.PLAIN_TEXT), uploaderName = "Uploader $index", replies = Page(""), replyCount = 0 @@ -135,7 +135,7 @@ class CommentSectionInstrumentedTest { .performClick() val recoveredComment = CommentsInfoItem( - commentText = Description("Recovered comment", Description.PLAIN_TEXT), + commentText = Description("Recovered comment", Description.Type.PLAIN_TEXT), uploaderName = "Uploader", replies = Page(""), replyCount = 0 @@ -181,7 +181,7 @@ class CommentSectionInstrumentedTest { .performClick() val recoveredComment = CommentsInfoItem( - commentText = Description("Recovered comment", Description.PLAIN_TEXT), + commentText = Description("Recovered comment", Description.Type.PLAIN_TEXT), uploaderName = "Uploader", replies = Page(""), replyCount = 0 @@ -226,7 +226,7 @@ class CommentSectionInstrumentedTest { .performClick() val firstComment = CommentsInfoItem( - commentText = Description("First comment", Description.PLAIN_TEXT), + commentText = Description("First comment", Description.Type.PLAIN_TEXT), uploaderName = "Uploader", replies = Page(""), replyCount = 0 From 1f5349ec5eb2d510e33f66f440f7140a6585d6d6 Mon Sep 17 00:00:00 2001 From: Isira Seneviratne Date: Wed, 27 May 2026 09:01:33 +0530 Subject: [PATCH 5/5] Fix checkstyle --- .../newpipe/fragments/list/channel/ChannelAboutFragment.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/fragments/list/channel/ChannelAboutFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/list/channel/ChannelAboutFragment.java index 4dfd72e217a..e29d3ba3a11 100644 --- a/app/src/main/java/org/schabi/newpipe/fragments/list/channel/ChannelAboutFragment.java +++ b/app/src/main/java/org/schabi/newpipe/fragments/list/channel/ChannelAboutFragment.java @@ -44,8 +44,8 @@ protected void initViews(final View rootView, final Bundle savedInstanceState) { @NonNull @Override protected Optional getDescription() { - final var description = Description.of(channelInfo.getDescription(), Description.Type.PLAIN_TEXT); - return Optional.of(description); + final String description = channelInfo.getDescription(); + return Optional.of(Description.of(description, Description.Type.PLAIN_TEXT)); } @NonNull