mirror of
				https://github.com/TeamNewPipe/NewPipe
				synced 2025-10-31 15:23:00 +00:00 
			
		
		
		
	Improve text linkifier function parameters
This commit is contained in:
		| @@ -16,9 +16,9 @@ import org.schabi.newpipe.BuildConfig | ||||
| import org.schabi.newpipe.R | ||||
| import org.schabi.newpipe.databinding.ActivityAboutBinding | ||||
| import org.schabi.newpipe.databinding.FragmentAboutBinding | ||||
| import org.schabi.newpipe.util.external_communication.ShareUtils | ||||
| import org.schabi.newpipe.util.Localization | ||||
| import org.schabi.newpipe.util.ThemeHelper | ||||
| import org.schabi.newpipe.util.external_communication.ShareUtils | ||||
|  | ||||
| class AboutActivity : AppCompatActivity() { | ||||
|     override fun onCreate(savedInstanceState: Bundle?) { | ||||
|   | ||||
| @@ -19,7 +19,6 @@ import org.schabi.newpipe.R; | ||||
| import org.schabi.newpipe.databinding.FragmentDescriptionBinding; | ||||
| import org.schabi.newpipe.databinding.ItemMetadataBinding; | ||||
| import org.schabi.newpipe.databinding.ItemMetadataTagsBinding; | ||||
| import org.schabi.newpipe.extractor.StreamingService; | ||||
| import org.schabi.newpipe.extractor.stream.Description; | ||||
| import org.schabi.newpipe.extractor.stream.StreamInfo; | ||||
| import org.schabi.newpipe.util.Localization; | ||||
| @@ -132,24 +131,19 @@ public class DescriptionFragment extends BaseFragment { | ||||
|  | ||||
|     private void loadDescriptionContent() { | ||||
|         final Description description = streamInfo.getDescription(); | ||||
|         final String contentUrl = streamInfo.getUrl(); | ||||
|         final StreamingService service = streamInfo.getService(); | ||||
|  | ||||
|         switch (description.getType()) { | ||||
|             case Description.HTML: | ||||
|                 descriptionDisposable = TextLinkifier.createLinksFromHtmlBlock(requireContext(), | ||||
|                         description.getContent(), binding.detailDescriptionView, | ||||
|                         service, contentUrl, HtmlCompat.FROM_HTML_MODE_LEGACY); | ||||
|                 descriptionDisposable = TextLinkifier.createLinksFromHtmlBlock( | ||||
|                         binding.detailDescriptionView, description.getContent(), | ||||
|                         HtmlCompat.FROM_HTML_MODE_LEGACY, streamInfo); | ||||
|                 break; | ||||
|             case Description.MARKDOWN: | ||||
|                 descriptionDisposable = TextLinkifier.createLinksFromMarkdownText(requireContext(), | ||||
|                         description.getContent(), binding.detailDescriptionView, | ||||
|                         service, contentUrl); | ||||
|                 descriptionDisposable = TextLinkifier.createLinksFromMarkdownText( | ||||
|                         binding.detailDescriptionView, description.getContent(), streamInfo); | ||||
|                 break; | ||||
|             case Description.PLAIN_TEXT: default: | ||||
|                 descriptionDisposable = TextLinkifier.createLinksFromPlainText(requireContext(), | ||||
|                         description.getContent(), binding.detailDescriptionView, | ||||
|                         service, contentUrl); | ||||
|                 descriptionDisposable = TextLinkifier.createLinksFromPlainText( | ||||
|                         binding.detailDescriptionView, description.getContent(), streamInfo); | ||||
|                 break; | ||||
|         } | ||||
|     } | ||||
| @@ -204,8 +198,7 @@ public class DescriptionFragment extends BaseFragment { | ||||
|         }); | ||||
|  | ||||
|         if (linkifyContent) { | ||||
|             TextLinkifier.createLinksFromPlainText(requireContext(), | ||||
|                     content, itemBinding.metadataContentView, null, null); | ||||
|             TextLinkifier.createLinksFromPlainText(itemBinding.metadataContentView, content, null); | ||||
|         } else { | ||||
|             itemBinding.metadataContentView.setText(content); | ||||
|         } | ||||
|   | ||||
| @@ -311,9 +311,9 @@ public final class ExtractorHelper { | ||||
|             } | ||||
|  | ||||
|             metaInfoSeparator.setVisibility(View.VISIBLE); | ||||
|             return TextLinkifier.createLinksFromHtmlBlock(context, stringBuilder.toString(), | ||||
|                     metaInfoTextView, null, null, | ||||
|                     HtmlCompat.FROM_HTML_SEPARATOR_LINE_BREAK_HEADING); | ||||
|             return TextLinkifier.createLinksFromHtmlBlock(metaInfoTextView, | ||||
|                     stringBuilder.toString(), HtmlCompat.FROM_HTML_SEPARATOR_LINE_BREAK_HEADING, | ||||
|                     null); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -11,9 +11,10 @@ import android.view.View; | ||||
| import android.widget.TextView; | ||||
|  | ||||
| import androidx.annotation.NonNull; | ||||
| import androidx.annotation.Nullable; | ||||
| import androidx.core.text.HtmlCompat; | ||||
|  | ||||
| import org.schabi.newpipe.extractor.StreamingService; | ||||
| import org.schabi.newpipe.extractor.Info; | ||||
| import org.schabi.newpipe.util.NavigationHelper; | ||||
|  | ||||
| import java.util.regex.Matcher; | ||||
| @@ -42,85 +43,74 @@ public final class TextLinkifier { | ||||
|      * Create web links for contents with an HTML description. | ||||
|      * <p> | ||||
|      * This will call | ||||
|      * {@link TextLinkifier#changeIntentsOfDescriptionLinks(Context, CharSequence, TextView, | ||||
|      * StreamingService, String)} | ||||
|      * {@link TextLinkifier#changeIntentsOfDescriptionLinks(TextView, CharSequence, Info)} | ||||
|      * after having linked the URLs with {@link HtmlCompat#fromHtml(String, int)}. | ||||
|      * | ||||
|      * @param context          the context to use | ||||
|      * @param htmlBlock        the htmlBlock to be linked | ||||
|      * @param textView         the TextView to set the htmlBlock linked | ||||
|      * @param streamingService the {@link StreamingService} of the content | ||||
|      * @param contentUrl       the URL of the content | ||||
|      * @param htmlCompatFlag   the int flag to be set when {@link HtmlCompat#fromHtml(String, int)} | ||||
|      *                         will be called | ||||
|      * @param textView       the TextView to set the htmlBlock linked | ||||
|      * @param htmlBlock      the htmlBlock to be linked | ||||
|      * @param htmlCompatFlag the int flag to be set when {@link HtmlCompat#fromHtml(String, int)} | ||||
|      *                       will be called | ||||
|      * @param relatedInfo    if given, handle timestamps to open the stream in the popup player at | ||||
|      *                       the specific time, and hashtags to search for the term in the correct | ||||
|      *                       service | ||||
|      * @return a disposable to be stored somewhere and disposed when activity/fragment is destroyed | ||||
|      */ | ||||
|     @NonNull | ||||
|     public static Disposable createLinksFromHtmlBlock(final Context context, | ||||
|     public static Disposable createLinksFromHtmlBlock(@NonNull final TextView textView, | ||||
|                                                       final String htmlBlock, | ||||
|                                                       final TextView textView, | ||||
|                                                       final StreamingService streamingService, | ||||
|                                                       final String contentUrl, | ||||
|                                                       final int htmlCompatFlag) { | ||||
|         return changeIntentsOfDescriptionLinks(context, | ||||
|                 HtmlCompat.fromHtml(htmlBlock, htmlCompatFlag), textView, streamingService, | ||||
|                 contentUrl); | ||||
|                                                       final int htmlCompatFlag, | ||||
|                                                       @Nullable final Info relatedInfo) { | ||||
|         return changeIntentsOfDescriptionLinks( | ||||
|                 textView, HtmlCompat.fromHtml(htmlBlock, htmlCompatFlag), relatedInfo); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Create web links for contents with a plain text description. | ||||
|      * <p> | ||||
|      * This will call | ||||
|      * {@link TextLinkifier#changeIntentsOfDescriptionLinks(Context, CharSequence, TextView, | ||||
|      * StreamingService, String)} | ||||
|      * {@link TextLinkifier#changeIntentsOfDescriptionLinks(TextView, CharSequence, Info)} | ||||
|      * after having linked the URLs with {@link TextView#setAutoLinkMask(int)} and | ||||
|      * {@link TextView#setText(CharSequence, TextView.BufferType)}. | ||||
|      * | ||||
|      * @param context          the context to use | ||||
|      * @param plainTextBlock   the block of plain text to be linked | ||||
|      * @param textView         the TextView to set the plain text block linked | ||||
|      * @param streamingService the {@link StreamingService} of the content | ||||
|      * @param contentUrl       the URL of the content | ||||
|      * @param textView       the TextView to set the plain text block linked | ||||
|      * @param plainTextBlock the block of plain text to be linked | ||||
|      * @param relatedInfo    if given, handle timestamps to open the stream in the popup player at | ||||
|      *                       the specific time, and hashtags to search for the term in the correct | ||||
|      *                       service | ||||
|      * @return a disposable to be stored somewhere and disposed when activity/fragment is destroyed | ||||
|      */ | ||||
|     @NonNull | ||||
|     public static Disposable createLinksFromPlainText(final Context context, | ||||
|     public static Disposable createLinksFromPlainText(@NonNull final TextView textView, | ||||
|                                                       final String plainTextBlock, | ||||
|                                                       @NonNull final TextView textView, | ||||
|                                                       final StreamingService streamingService, | ||||
|                                                       final String contentUrl) { | ||||
|                                                       @Nullable final Info relatedInfo) { | ||||
|         textView.setAutoLinkMask(Linkify.WEB_URLS); | ||||
|         textView.setText(plainTextBlock, TextView.BufferType.SPANNABLE); | ||||
|         return changeIntentsOfDescriptionLinks(context, textView.getText(), textView, | ||||
|                 streamingService, contentUrl); | ||||
|         return changeIntentsOfDescriptionLinks(textView, textView.getText(), relatedInfo); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Create web links for contents with a markdown description. | ||||
|      * <p> | ||||
|      * This will call | ||||
|      * {@link TextLinkifier#changeIntentsOfDescriptionLinks(Context, CharSequence, TextView, | ||||
|      * StreamingService, String)} | ||||
|      * {@link TextLinkifier#changeIntentsOfDescriptionLinks(TextView, CharSequence, Info)} | ||||
|      * after creating an {@link Markwon} object and using | ||||
|      * {@link Markwon#setMarkdown(TextView, String)}. | ||||
|      * | ||||
|      * @param context          the context to use | ||||
|      * @param markdownBlock    the block of markdown text to be linked | ||||
|      * @param textView         the TextView to set the plain text block linked | ||||
|      * @param streamingService the {@link StreamingService} of the content | ||||
|      * @param contentUrl       the URL of the content | ||||
|      * @param textView      the TextView to set the plain text block linked | ||||
|      * @param markdownBlock the block of markdown text to be linked | ||||
|      * @param relatedInfo   if given, handle timestamps to open the stream in the popup player at | ||||
|      *                      the specific time, and hashtags to search for the term in the correct | ||||
|      *                      service | ||||
|      * @return a disposable to be stored somewhere and disposed when activity/fragment is destroyed | ||||
|      */ | ||||
|     @NonNull | ||||
|     public static Disposable createLinksFromMarkdownText(final Context context, | ||||
|     public static Disposable createLinksFromMarkdownText(@NonNull final TextView textView, | ||||
|                                                          final String markdownBlock, | ||||
|                                                          final TextView textView, | ||||
|                                                          final StreamingService streamingService, | ||||
|                                                          final String contentUrl) { | ||||
|         final Markwon markwon = Markwon.builder(context).usePlugin(LinkifyPlugin.create()).build(); | ||||
|                                                          @Nullable final Info relatedInfo) { | ||||
|         final Markwon markwon = Markwon.builder(textView.getContext()) | ||||
|                 .usePlugin(LinkifyPlugin.create()).build(); | ||||
|         markwon.setMarkdown(textView, markdownBlock); | ||||
|         return changeIntentsOfDescriptionLinks(context, textView.getText(), textView, | ||||
|                 streamingService, contentUrl); | ||||
|         return changeIntentsOfDescriptionLinks(textView, textView.getText(), relatedInfo); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -134,12 +124,12 @@ public final class TextLinkifier { | ||||
|      * @param context              the context to use | ||||
|      * @param spannableDescription the SpannableStringBuilder with the text of the | ||||
|      *                             content description | ||||
|      * @param streamingService     the {@link StreamingService} of the content | ||||
|      * @param relatedInfo          used to search for the term in the correct service | ||||
|      */ | ||||
|     private static void addClickListenersOnHashtags(final Context context, | ||||
|                                                     @NonNull final SpannableStringBuilder | ||||
|                                                             spannableDescription, | ||||
|                                                     final StreamingService streamingService) { | ||||
|                                                     final Info relatedInfo) { | ||||
|         final String descriptionText = spannableDescription.toString(); | ||||
|         final Matcher hashtagsMatches = HASHTAGS_PATTERN.matcher(descriptionText); | ||||
|  | ||||
| @@ -155,7 +145,7 @@ public final class TextLinkifier { | ||||
|                 spannableDescription.setSpan(new ClickableSpan() { | ||||
|                     @Override | ||||
|                     public void onClick(@NonNull final View view) { | ||||
|                         NavigationHelper.openSearch(context, streamingService.getServiceId(), | ||||
|                         NavigationHelper.openSearch(context, relatedInfo.getServiceId(), | ||||
|                                 parsedHashtag); | ||||
|                     } | ||||
|                 }, hashtagStart, hashtagEnd, 0); | ||||
| @@ -173,14 +163,12 @@ public final class TextLinkifier { | ||||
|      * @param context              the context to use | ||||
|      * @param spannableDescription the SpannableStringBuilder with the text of the | ||||
|      *                             content description | ||||
|      * @param contentUrl           the URL of the content | ||||
|      * @param streamingService     the {@link StreamingService} of the content | ||||
|      * @param relatedInfo          what to open in the popup player when timestamps are clicked | ||||
|      */ | ||||
|     private static void addClickListenersOnTimestamps(final Context context, | ||||
|                                                       @NonNull final SpannableStringBuilder | ||||
|                                                               spannableDescription, | ||||
|                                                       final String contentUrl, | ||||
|                                                       final StreamingService streamingService) { | ||||
|                                                       final Info relatedInfo) { | ||||
|         final String descriptionText = spannableDescription.toString(); | ||||
|         final Matcher timestampsMatches = TIMESTAMPS_PATTERN.matcher(descriptionText); | ||||
|  | ||||
| @@ -189,14 +177,14 @@ public final class TextLinkifier { | ||||
|             final int timestampEnd = timestampsMatches.end(3); | ||||
|             final String parsedTimestamp = descriptionText.substring(timestampStart, timestampEnd); | ||||
|             final String[] timestampParts = parsedTimestamp.split(":"); | ||||
|             final int time; | ||||
|  | ||||
|             final int seconds; | ||||
|             if (timestampParts.length == 3) { // timestamp format: XX:XX:XX | ||||
|                 time = Integer.parseInt(timestampParts[0]) * 3600 // hours | ||||
|                 seconds = Integer.parseInt(timestampParts[0]) * 3600 // hours | ||||
|                         + Integer.parseInt(timestampParts[1]) * 60 // minutes | ||||
|                         + Integer.parseInt(timestampParts[2]); // seconds | ||||
|             } else if (timestampParts.length == 2) { // timestamp format: XX:XX | ||||
|                 time = Integer.parseInt(timestampParts[0]) * 60 // minutes | ||||
|                 seconds = Integer.parseInt(timestampParts[0]) * 60 // minutes | ||||
|                         + Integer.parseInt(timestampParts[1]); // seconds | ||||
|             } else { | ||||
|                 continue; | ||||
| @@ -205,8 +193,8 @@ public final class TextLinkifier { | ||||
|             spannableDescription.setSpan(new ClickableSpan() { | ||||
|                 @Override | ||||
|                 public void onClick(@NonNull final View view) { | ||||
|                     playOnPopup(new CompositeDisposable(), context, contentUrl, streamingService, | ||||
|                             time); | ||||
|                     playOnPopup(new CompositeDisposable(), context, relatedInfo.getUrl(), | ||||
|                             relatedInfo.getService(), seconds); | ||||
|                 } | ||||
|             }, timestampStart, timestampEnd, 0); | ||||
|         } | ||||
| @@ -221,28 +209,28 @@ public final class TextLinkifier { | ||||
|      * with {@link ShareUtils#openUrlInBrowser(Context, String, boolean)}. | ||||
|      * This method will also add click listeners on timestamps in this description, which will play | ||||
|      * the content in the popup player at the time indicated in the timestamp, by using | ||||
|      * {@link TextLinkifier#addClickListenersOnTimestamps(Context, SpannableStringBuilder, String, | ||||
|      * StreamingService)} method and click listeners on hashtags, which will open a search | ||||
|      * on the current service with the hashtag. | ||||
|      * {@link TextLinkifier#addClickListenersOnTimestamps(Context, SpannableStringBuilder, Info)} | ||||
|      * method and click listeners on hashtags, by using | ||||
|      * {@link TextLinkifier#addClickListenersOnHashtags(Context, SpannableStringBuilder, Info)}, | ||||
|      * which will open a search on the current service with the hashtag. | ||||
|      * <p> | ||||
|      * This method is required in order to intercept links and e.g. show a confirmation dialog | ||||
|      * before opening a web link. | ||||
|      * | ||||
|      * @param context          the context to use | ||||
|      * @param chars            the CharSequence to be parsed | ||||
|      * @param textView         the TextView in which the converted CharSequence will be applied | ||||
|      * @param streamingService the {@link StreamingService} of the content | ||||
|      * @param contentUrl       the URL of the content | ||||
|      * @param textView    the TextView in which the converted CharSequence will be applied | ||||
|      * @param chars       the CharSequence to be parsed | ||||
|      * @param relatedInfo if given, handle timestamps to open the stream in the popup player at | ||||
|      *                    the specific time, and hashtags to search for the term in the correct | ||||
|      *                    service | ||||
|      * @return a disposable to be stored somewhere and disposed when activity/fragment is destroyed | ||||
|      */ | ||||
|     @NonNull | ||||
|     private static Disposable changeIntentsOfDescriptionLinks(final Context context, | ||||
|     private static Disposable changeIntentsOfDescriptionLinks(final TextView textView, | ||||
|                                                               final CharSequence chars, | ||||
|                                                               final TextView textView, | ||||
|                                                               final StreamingService | ||||
|                                                                       streamingService, | ||||
|                                                               final String contentUrl) { | ||||
|                                                               @Nullable final Info relatedInfo) { | ||||
|         return Single.fromCallable(() -> { | ||||
|             final Context context = textView.getContext(); | ||||
|  | ||||
|             // add custom click actions on web links | ||||
|             final SpannableStringBuilder textBlockLinked = new SpannableStringBuilder(chars); | ||||
|             final URLSpan[] urls = textBlockLinked.getSpans(0, chars.length(), URLSpan.class); | ||||
| @@ -264,11 +252,10 @@ public final class TextLinkifier { | ||||
|             } | ||||
|  | ||||
|             // add click actions on plain text timestamps only for description of contents, | ||||
|             // unneeded for metainfo TextViews | ||||
|             if (contentUrl != null || streamingService != null) { | ||||
|                 addClickListenersOnTimestamps(context, textBlockLinked, contentUrl, | ||||
|                         streamingService); | ||||
|                 addClickListenersOnHashtags(context, textBlockLinked, streamingService); | ||||
|             // unneeded for meta-info or other TextViews | ||||
|             if (relatedInfo != null) { | ||||
|                 addClickListenersOnTimestamps(context, textBlockLinked, relatedInfo); | ||||
|                 addClickListenersOnHashtags(context, textBlockLinked, relatedInfo); | ||||
|             } | ||||
|  | ||||
|             return textBlockLinked; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Stypox
					Stypox