From 7045f9711c04a4a0610553f605c8c69a7fd4f21f Mon Sep 17 00:00:00 2001 From: bopol Date: Sun, 2 Feb 2020 16:54:09 +0100 Subject: [PATCH 1/4] fix thumbnail for PeerTube, and description changes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit description: - PeerTube: it's now full description (it cut at 250 characters before), and it displays ok (newlines are ok, but markdown isn't) - MediaCCC: descriptions are now displayed well (newlines added) - YouTube: timestamps in descriptions are clickable and work more PeerTube fixes: thumbnail is now high quality age limit is now handled upload date in «recently added» feed is good now (it was one hour delayed) all fixes come from https://github.com/TeamNewPipe/NewPipeExtractor/pull/239, so it need to be merged before this PR --- app/build.gradle | 2 +- .../fragments/detail/VideoDetailFragment.java | 75 +++++++++++++------ 2 files changed, 53 insertions(+), 24 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index f8fc1565f..0f7ad5f92 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -62,7 +62,7 @@ dependencies { exclude module: 'support-annotations' }) - implementation 'com.github.TeamNewPipe:NewPipeExtractor:ff61e284' + implementation 'com.github.B0pol:NewPipeExtractor:5756df8dc7e89b7383d1d1e07a91c30bdab6f868' testImplementation 'junit:junit:4.12' testImplementation 'org.mockito:mockito-core:2.23.0' 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 f59cfaef0..a297cddf3 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 @@ -2,7 +2,6 @@ package org.schabi.newpipe.fragments.detail; import android.app.Activity; import android.content.Context; -import android.content.DialogInterface; import android.content.Intent; import android.content.SharedPreferences; import android.net.Uri; @@ -18,7 +17,6 @@ import androidx.fragment.app.Fragment; import androidx.core.content.ContextCompat; import androidx.viewpager.widget.ViewPager; import androidx.appcompat.app.ActionBar; -import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AppCompatActivity; import android.text.Html; import android.text.Spanned; @@ -193,6 +191,14 @@ public class VideoDetailFragment private TabLayout tabLayout; private FrameLayout relatedStreamsLayout; + private static final int DESCRIPTION_HTML = 1; + private static final int DESCRIPTION_MARKDOWN = 2; + private static final int DESCRIPTION_PLAIN_TEXT = 3; + + private static final int YOUTUBE_SERVICE_ID = ServiceList.YouTube.getServiceId(); + private static final int MEDIACCC_SERVICE_ID = ServiceList.MediaCCC.getServiceId(); + private static final int PEERTUBE_SERVICE_ID = ServiceList.PeerTube.getServiceId(); + /*////////////////////////////////////////////////////////////////////////*/ @@ -483,7 +489,6 @@ public class VideoDetailFragment videoUploadDateView = rootView.findViewById(R.id.detail_upload_date_view); videoDescriptionView = rootView.findViewById(R.id.detail_description_view); videoDescriptionView.setMovementMethod(LinkMovementMethod.getInstance()); - videoDescriptionView.setAutoLinkMask(Linkify.WEB_URLS); thumbsUpTextView = rootView.findViewById(R.id.detail_thumbs_up_count_view); thumbsUpImageView = rootView.findViewById(R.id.detail_thumbs_up_img_view); @@ -919,28 +924,39 @@ public class VideoDetailFragment return sortedVideoStreams != null ? sortedVideoStreams.get(selectedVideoStreamIndex) : null; } - private void prepareDescription(final String descriptionHtml) { - if (TextUtils.isEmpty(descriptionHtml)) { + private void prepareDescription(final String descriptionText, int descriptionTypeId) { + if (TextUtils.isEmpty(descriptionText)) { return; } - disposables.add(Single.just(descriptionHtml) - .map((@io.reactivex.annotations.NonNull String description) -> { - Spanned parsedDescription; - if (Build.VERSION.SDK_INT >= 24) { - parsedDescription = Html.fromHtml(description, 0); - } else { - //noinspection deprecation - parsedDescription = Html.fromHtml(description); - } - return parsedDescription; - }) - .subscribeOn(Schedulers.computation()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe((@io.reactivex.annotations.NonNull Spanned spanned) -> { - videoDescriptionView.setText(spanned); - videoDescriptionView.setVisibility(View.VISIBLE); - })); + if (descriptionTypeId == DESCRIPTION_PLAIN_TEXT) { + videoDescriptionView.setText(descriptionText, TextView.BufferType.SPANNABLE); + videoDescriptionView.setVisibility(View.VISIBLE); + } else if (descriptionTypeId == DESCRIPTION_MARKDOWN) { + //in the future we would use a library or a good method to show markdown. + //rn, we just remove **bold**, and let plain_text otherwise + videoDescriptionView.setText(descriptionText.replace("**", ""), TextView.BufferType.SPANNABLE); + videoDescriptionView.setVisibility(View.VISIBLE); + } else { + //== DESCRIPTION_HTML + disposables.add(Single.just(descriptionText) + .map((@io.reactivex.annotations.NonNull String description) -> { + Spanned parsedDescription; + if (Build.VERSION.SDK_INT >= 24) { + parsedDescription = Html.fromHtml(description, 0); + } else { + //noinspection deprecation + parsedDescription = Html.fromHtml(description); + } + return parsedDescription; + }) + .subscribeOn(Schedulers.computation()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe((@io.reactivex.annotations.NonNull Spanned spanned) -> { + videoDescriptionView.setText(spanned); + videoDescriptionView.setVisibility(View.VISIBLE); + })); + } } private void setHeightThumbnail() { @@ -1126,7 +1142,20 @@ public class VideoDetailFragment videoUploadDateView.setVisibility(View.GONE); } - prepareDescription(info.getDescription()); + int serviceId = info.getServiceId(); + + if (serviceId != YOUTUBE_SERVICE_ID) { + videoDescriptionView.setAutoLinkMask(Linkify.WEB_URLS); + } + + if (serviceId == PEERTUBE_SERVICE_ID) { + prepareDescription(info.getDescription(), DESCRIPTION_MARKDOWN); + } else if (serviceId == MEDIACCC_SERVICE_ID) { + prepareDescription(info.getDescription(), DESCRIPTION_PLAIN_TEXT); + } else { + prepareDescription(info.getDescription(), DESCRIPTION_HTML); + } + updateProgressInfo(info); animateView(spinnerToolbar, true, 500); From badaff8ebcd6f446a6a4b575adba43d627b4c7c2 Mon Sep 17 00:00:00 2001 From: bopol Date: Thu, 6 Feb 2020 23:54:36 +0100 Subject: [PATCH 2/4] refactor Description --- app/build.gradle | 2 +- .../fragments/detail/VideoDetailFragment.java | 60 +++++++------------ 2 files changed, 23 insertions(+), 39 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 0f7ad5f92..728d380c4 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -62,7 +62,7 @@ dependencies { exclude module: 'support-annotations' }) - implementation 'com.github.B0pol:NewPipeExtractor:5756df8dc7e89b7383d1d1e07a91c30bdab6f868' + implementation 'com.github.B0pol:NewPipeExtractor:11bcc78d9c8eb39e8d61a6f4bc4112025937f087' testImplementation 'junit:junit:4.12' testImplementation 'org.mockito:mockito-core:2.23.0' 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 a297cddf3..c6c8ca04c 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 @@ -56,6 +56,7 @@ import org.schabi.newpipe.extractor.exceptions.ExtractionException; import org.schabi.newpipe.extractor.exceptions.ParsingException; import org.schabi.newpipe.extractor.services.youtube.extractors.YoutubeStreamExtractor; import org.schabi.newpipe.extractor.stream.AudioStream; +import org.schabi.newpipe.extractor.stream.Description; import org.schabi.newpipe.extractor.stream.Stream; import org.schabi.newpipe.extractor.stream.StreamInfo; import org.schabi.newpipe.extractor.stream.StreamType; @@ -191,14 +192,6 @@ public class VideoDetailFragment private TabLayout tabLayout; private FrameLayout relatedStreamsLayout; - private static final int DESCRIPTION_HTML = 1; - private static final int DESCRIPTION_MARKDOWN = 2; - private static final int DESCRIPTION_PLAIN_TEXT = 3; - - private static final int YOUTUBE_SERVICE_ID = ServiceList.YouTube.getServiceId(); - private static final int MEDIACCC_SERVICE_ID = ServiceList.MediaCCC.getServiceId(); - private static final int PEERTUBE_SERVICE_ID = ServiceList.PeerTube.getServiceId(); - /*////////////////////////////////////////////////////////////////////////*/ @@ -924,29 +917,24 @@ public class VideoDetailFragment return sortedVideoStreams != null ? sortedVideoStreams.get(selectedVideoStreamIndex) : null; } - private void prepareDescription(final String descriptionText, int descriptionTypeId) { - if (TextUtils.isEmpty(descriptionText)) { + private void prepareDescription(Description description) { + if (TextUtils.isEmpty(description.getContent()) || description == Description.emptyDescription) { return; } - if (descriptionTypeId == DESCRIPTION_PLAIN_TEXT) { - videoDescriptionView.setText(descriptionText, TextView.BufferType.SPANNABLE); - videoDescriptionView.setVisibility(View.VISIBLE); - } else if (descriptionTypeId == DESCRIPTION_MARKDOWN) { - //in the future we would use a library or a good method to show markdown. - //rn, we just remove **bold**, and let plain_text otherwise - videoDescriptionView.setText(descriptionText.replace("**", ""), TextView.BufferType.SPANNABLE); - videoDescriptionView.setVisibility(View.VISIBLE); - } else { - //== DESCRIPTION_HTML - disposables.add(Single.just(descriptionText) - .map((@io.reactivex.annotations.NonNull String description) -> { + if (description.getType() != Description.HTML) { + videoDescriptionView.setAutoLinkMask(Linkify.WEB_URLS); + } + + if (description.getType() == Description.HTML) { + disposables.add(Single.just(description.getContent()) + .map((@io.reactivex.annotations.NonNull String descriptionText) -> { Spanned parsedDescription; if (Build.VERSION.SDK_INT >= 24) { - parsedDescription = Html.fromHtml(description, 0); + parsedDescription = Html.fromHtml(descriptionText, 0); } else { //noinspection deprecation - parsedDescription = Html.fromHtml(description); + parsedDescription = Html.fromHtml(descriptionText); } return parsedDescription; }) @@ -956,6 +944,15 @@ public class VideoDetailFragment videoDescriptionView.setText(spanned); videoDescriptionView.setVisibility(View.VISIBLE); })); + } else if (description.getType() == Description.MARKDOWN) { + //in the future we would use a library or a good method to show markdown. + //rn, we just remove **bold**, and let PLAIN_TEXT otherwise + videoDescriptionView.setText(description.getContent().replace("**", ""), TextView.BufferType.SPANNABLE); + videoDescriptionView.setVisibility(View.VISIBLE); + } else { + //== Description.PLAIN_TEXT + videoDescriptionView.setText(description.getContent(), TextView.BufferType.SPANNABLE); + videoDescriptionView.setVisibility(View.VISIBLE); } } @@ -1142,20 +1139,7 @@ public class VideoDetailFragment videoUploadDateView.setVisibility(View.GONE); } - int serviceId = info.getServiceId(); - - if (serviceId != YOUTUBE_SERVICE_ID) { - videoDescriptionView.setAutoLinkMask(Linkify.WEB_URLS); - } - - if (serviceId == PEERTUBE_SERVICE_ID) { - prepareDescription(info.getDescription(), DESCRIPTION_MARKDOWN); - } else if (serviceId == MEDIACCC_SERVICE_ID) { - prepareDescription(info.getDescription(), DESCRIPTION_PLAIN_TEXT); - } else { - prepareDescription(info.getDescription(), DESCRIPTION_HTML); - } - + prepareDescription(info.getDescription()); updateProgressInfo(info); animateView(spinnerToolbar, true, 500); From 2d62fa401d63551785859b0d909f8414e94ba191 Mon Sep 17 00:00:00 2001 From: bopol Date: Sat, 8 Feb 2020 09:56:37 +0100 Subject: [PATCH 3/4] real markdown support for descriptions and update third-party licences in about page --- app/build.gradle | 4 ++++ .../org/schabi/newpipe/about/AboutActivity.java | 16 +++++++++------- .../fragments/detail/VideoDetailFragment.java | 14 +++++++------- 3 files changed, 20 insertions(+), 14 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 728d380c4..65ab78ffa 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -53,6 +53,7 @@ ext { okHttpLibVersion = '3.12.6' icepickLibVersion = '3.2.0' stethoLibVersion = '1.5.0' + markwonVersion = '4.2.1' } dependencies { @@ -108,4 +109,7 @@ dependencies { implementation "com.squareup.okhttp3:okhttp:${okHttpLibVersion}" debugImplementation "com.facebook.stetho:stetho-okhttp3:${stethoLibVersion}" + + implementation "io.noties.markwon:core:${markwonVersion}" + implementation "io.noties.markwon:linkify:${markwonVersion}" } diff --git a/app/src/main/java/org/schabi/newpipe/about/AboutActivity.java b/app/src/main/java/org/schabi/newpipe/about/AboutActivity.java index 9e23d9d3d..edfc54375 100644 --- a/app/src/main/java/org/schabi/newpipe/about/AboutActivity.java +++ b/app/src/main/java/org/schabi/newpipe/about/AboutActivity.java @@ -32,18 +32,20 @@ public class AboutActivity extends AppCompatActivity { * List of all software components */ private static final SoftwareComponent[] SOFTWARE_COMPONENTS = new SoftwareComponent[]{ - new SoftwareComponent("Giga Get", "2014", "Peter Cai", "https://github.com/PaperAirplane-Dev-Team/GigaGet", StandardLicenses.GPL2), - new SoftwareComponent("NewPipe Extractor", "2017", "Christian Schabesberger", "https://github.com/TeamNewPipe/NewPipeExtractor", StandardLicenses.GPL3), + new SoftwareComponent("Giga Get", "2014 - 2015", "Peter Cai", "https://github.com/PaperAirplane-Dev-Team/GigaGet", StandardLicenses.GPL2), + new SoftwareComponent("NewPipe Extractor", "2017 - 2020", "Christian Schabesberger", "https://github.com/TeamNewPipe/NewPipeExtractor", StandardLicenses.GPL3), new SoftwareComponent("Jsoup", "2017", "Jonathan Hedley", "https://github.com/jhy/jsoup", StandardLicenses.MIT), new SoftwareComponent("Rhino", "2015", "Mozilla", "https://www.mozilla.org/rhino/", StandardLicenses.MPL2), new SoftwareComponent("ACRA", "2013", "Kevin Gaudin", "http://www.acra.ch", StandardLicenses.APACHE2), new SoftwareComponent("Universal Image Loader", "2011 - 2015", "Sergey Tarasevich", "https://github.com/nostra13/Android-Universal-Image-Loader", StandardLicenses.APACHE2), - new SoftwareComponent("CircleImageView", "2014 - 2017", "Henning Dodenhof", "https://github.com/hdodenhof/CircleImageView", StandardLicenses.APACHE2), + new SoftwareComponent("CircleImageView", "2014 - 2020", "Henning Dodenhof", "https://github.com/hdodenhof/CircleImageView", StandardLicenses.APACHE2), new SoftwareComponent("NoNonsense-FilePicker", "2016", "Jonas Kalderstam", "https://github.com/spacecowboy/NoNonsense-FilePicker", StandardLicenses.MPL2), - new SoftwareComponent("ExoPlayer", "2014-2017", "Google Inc", "https://github.com/google/ExoPlayer", StandardLicenses.APACHE2), - new SoftwareComponent("RxAndroid", "2015", "The RxAndroid authors", "https://github.com/ReactiveX/RxAndroid", StandardLicenses.APACHE2), - new SoftwareComponent("RxJava", "2016-present", "RxJava Contributors", "https://github.com/ReactiveX/RxJava", StandardLicenses.APACHE2), - new SoftwareComponent("RxBinding", "2015", "Jake Wharton", "https://github.com/JakeWharton/RxBinding", StandardLicenses.APACHE2) + new SoftwareComponent("ExoPlayer", "2014 - 2020", "Google Inc", "https://github.com/google/ExoPlayer", StandardLicenses.APACHE2), + new SoftwareComponent("RxAndroid", "2015 - 2018", "The RxAndroid authors", "https://github.com/ReactiveX/RxAndroid", StandardLicenses.APACHE2), + new SoftwareComponent("RxJava", "2016 - 2020", "RxJava Contributors", "https://github.com/ReactiveX/RxJava", StandardLicenses.APACHE2), + new SoftwareComponent("RxBinding", "2015 - 2018", "Jake Wharton", "https://github.com/JakeWharton/RxBinding", StandardLicenses.APACHE2), + new SoftwareComponent("PrettyTime", "2012 - 2020", "Lincoln Baxter, III", "https://github.com/ocpsoft/prettytime", StandardLicenses.APACHE2), + new SoftwareComponent("Markwon", "2017 - 2020", "Noties", "https://github.com/noties/Markwon", StandardLicenses.APACHE2) }; /** 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 c6c8ca04c..3c594bdfa 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 @@ -95,6 +95,8 @@ import java.util.List; import java.util.concurrent.TimeUnit; import icepick.State; +import io.noties.markwon.Markwon; +import io.noties.markwon.linkify.LinkifyPlugin; import io.reactivex.Single; import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.disposables.CompositeDisposable; @@ -922,10 +924,6 @@ public class VideoDetailFragment return; } - if (description.getType() != Description.HTML) { - videoDescriptionView.setAutoLinkMask(Linkify.WEB_URLS); - } - if (description.getType() == Description.HTML) { disposables.add(Single.just(description.getContent()) .map((@io.reactivex.annotations.NonNull String descriptionText) -> { @@ -945,12 +943,14 @@ public class VideoDetailFragment videoDescriptionView.setVisibility(View.VISIBLE); })); } else if (description.getType() == Description.MARKDOWN) { - //in the future we would use a library or a good method to show markdown. - //rn, we just remove **bold**, and let PLAIN_TEXT otherwise - videoDescriptionView.setText(description.getContent().replace("**", ""), TextView.BufferType.SPANNABLE); + final Markwon markwon = Markwon.builder(getContext()) + .usePlugin(LinkifyPlugin.create()) + .build(); + markwon.setMarkdown(videoDescriptionView, description.getContent()); videoDescriptionView.setVisibility(View.VISIBLE); } else { //== Description.PLAIN_TEXT + videoDescriptionView.setAutoLinkMask(Linkify.WEB_URLS); videoDescriptionView.setText(description.getContent(), TextView.BufferType.SPANNABLE); videoDescriptionView.setVisibility(View.VISIBLE); } From 3f3d1bfccf9be4182bd2872358263d3c904e447a Mon Sep 17 00:00:00 2001 From: bopol Date: Sun, 9 Feb 2020 00:00:14 +0100 Subject: [PATCH 4/4] update extractor version --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index 65ab78ffa..5da8c9ff0 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -63,7 +63,7 @@ dependencies { exclude module: 'support-annotations' }) - implementation 'com.github.B0pol:NewPipeExtractor:11bcc78d9c8eb39e8d61a6f4bc4112025937f087' + implementation 'com.github.TeamNewPipe:NewPipeExtractor:9112a10' testImplementation 'junit:junit:4.12' testImplementation 'org.mockito:mockito-core:2.23.0'