1
0
mirror of https://github.com/TeamNewPipe/NewPipe.git synced 2024-11-22 19:12:45 +01:00

Initial work: add support for opening hashtags in plain text descriptions

This commit adds supports for opening hashtags in plain text descriptions, using the same logic as timestamps.
Every hashtag opens a search on the current service with the text in the hashtag.
Also use a better regular expression for parsing timestamps.
This commit is contained in:
TiA4f8R 2021-03-27 18:45:05 +01:00
parent e5df2f65b8
commit 267686fd37
No known key found for this signature in database
GPG Key ID: E6D3E7F5949450DD

View File

@ -14,6 +14,7 @@ import androidx.annotation.NonNull;
import androidx.core.text.HtmlCompat; import androidx.core.text.HtmlCompat;
import org.schabi.newpipe.extractor.StreamingService; import org.schabi.newpipe.extractor.StreamingService;
import org.schabi.newpipe.util.NavigationHelper;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
@ -29,9 +30,9 @@ import static org.schabi.newpipe.util.external_communication.InternalUrlsHandler
public final class TextLinkifier { public final class TextLinkifier {
public static final String TAG = TextLinkifier.class.getSimpleName(); public static final String TAG = TextLinkifier.class.getSimpleName();
private static final Pattern TIMESTAMPS_PATTERN_IN_PLAIN_TEXT = private static final Pattern HASHTAGS_PATTERN = Pattern.compile("(#[A-Za-z0-9_]+)");
Pattern.compile("(?:^|(?![:])\\W)(?:([0-5]?[0-9]):)?([0-5]?[0-9]):" private static final Pattern TIMESTAMPS_PATTERN = Pattern.compile(
+ "([0-5][0-9])(?=$|(?![:])\\W)"); "(?:^|(?!:)\\W)(?:([0-5]?[0-9]):)?([0-5]?[0-9]):([0-5][0-9])(?=$|(?!:)\\W)");
private TextLinkifier() { private TextLinkifier() {
} }
@ -118,6 +119,41 @@ public final class TextLinkifier {
streamingService, contentUrl); streamingService, contentUrl);
} }
/**
* Add click listeners which opens a search on hashtags in a plain text.
* <p>
* This method finds all timestamps in the {@link SpannableStringBuilder} of the description
* using a regular expression, adds for each a {@link ClickableSpan} which opens
* {@link NavigationHelper#openSearch(Context, int, String)} and makes a search on the hashtag,
* in the service of the content.
*
* @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
*/
private static void addClickListenersOnHashtags(final Context context,
final SpannableStringBuilder
spannableDescription,
final StreamingService streamingService) {
final String descriptionText = spannableDescription.toString();
final Matcher hashtagsMatches = HASHTAGS_PATTERN.matcher(descriptionText);
while (hashtagsMatches.find()) {
final int hashtagStart = hashtagsMatches.start(1);
final int hashtagEnd = hashtagsMatches.end(1);
final String parsedHashtag = descriptionText.substring(hashtagStart, hashtagEnd);
spannableDescription.setSpan(new ClickableSpan() {
@Override
public void onClick(@NonNull final View view) {
NavigationHelper.openSearch(context, streamingService.getServiceId(),
parsedHashtag);
}
}, hashtagStart, hashtagEnd, 0);
}
}
/** /**
* Add click listeners which opens the popup player on timestamps in a plain text. * Add click listeners which opens the popup player on timestamps in a plain text.
* <p> * <p>
@ -137,11 +173,11 @@ public final class TextLinkifier {
final String contentUrl, final String contentUrl,
final StreamingService streamingService) { final StreamingService streamingService) {
final String descriptionText = spannableDescription.toString(); final String descriptionText = spannableDescription.toString();
final Matcher timestampMatches = TIMESTAMPS_PATTERN_IN_PLAIN_TEXT.matcher(descriptionText); final Matcher timestampsMatches = TIMESTAMPS_PATTERN.matcher(descriptionText);
while (timestampMatches.find()) { while (timestampsMatches.find()) {
final int timestampStart = timestampMatches.start(2); final int timestampStart = timestampsMatches.start(2);
final int timestampEnd = timestampMatches.end(3); final int timestampEnd = timestampsMatches.end(3);
final String parsedTimestamp = descriptionText.substring(timestampStart, timestampEnd); final String parsedTimestamp = descriptionText.substring(timestampStart, timestampEnd);
final String[] timestampParts = parsedTimestamp.split(":"); final String[] timestampParts = parsedTimestamp.split(":");
final int time; final int time;
@ -178,7 +214,8 @@ public final class TextLinkifier {
* This method will also add click listeners on timestamps in this description, which will play * 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 * the content in the popup player at the time indicated in the timestamp, by using
* {@link TextLinkifier#addClickListenersOnTimestamps(Context, SpannableStringBuilder, String, * {@link TextLinkifier#addClickListenersOnTimestamps(Context, SpannableStringBuilder, String,
* StreamingService)} method. * StreamingService)} method and click listeners on hashtags, which will open a search
* on the current service with the hashtag.
* <p> * <p>
* This method is required in order to intercept links and e.g. show a confirmation dialog * This method is required in order to intercept links and e.g. show a confirmation dialog
* before opening a web link. * before opening a web link.
@ -220,6 +257,7 @@ public final class TextLinkifier {
if (contentUrl != null || streamingService != null) { if (contentUrl != null || streamingService != null) {
addClickListenersOnTimestamps(context, textBlockLinked, contentUrl, addClickListenersOnTimestamps(context, textBlockLinked, contentUrl,
streamingService); streamingService);
addClickListenersOnHashtags(context, textBlockLinked, streamingService);
} }
return textBlockLinked; return textBlockLinked;