mirror of
https://github.com/TeamNewPipe/NewPipe
synced 2024-12-23 08:30:44 +00:00
Use better pattern for matching timestamp in text and some reworks
Also extracted overhead code into ``TimestampExtractor``
This commit is contained in:
parent
1d61bb58f5
commit
9f8b2264a2
@ -25,10 +25,10 @@ import org.schabi.newpipe.util.DeviceUtils;
|
||||
import org.schabi.newpipe.util.ImageDisplayConstants;
|
||||
import org.schabi.newpipe.util.Localization;
|
||||
import org.schabi.newpipe.util.NavigationHelper;
|
||||
import org.schabi.newpipe.util.external_communication.TimestampExtractor;
|
||||
import org.schabi.newpipe.util.external_communication.ShareUtils;
|
||||
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import de.hdodenhof.circleimageview.CircleImageView;
|
||||
|
||||
@ -37,7 +37,7 @@ public class CommentsMiniInfoItemHolder extends InfoItemHolder {
|
||||
|
||||
private static final int COMMENT_DEFAULT_LINES = 2;
|
||||
private static final int COMMENT_EXPANDED_LINES = 1000;
|
||||
private static final Pattern PATTERN = Pattern.compile("(\\d+:)?(\\d+)?:(\\d+)");
|
||||
|
||||
private final String downloadThumbnailKey;
|
||||
private final int commentHorizontalPadding;
|
||||
private final int commentVerticalPadding;
|
||||
@ -57,20 +57,16 @@ public class CommentsMiniInfoItemHolder extends InfoItemHolder {
|
||||
@Override
|
||||
public String transformUrl(final Matcher match, final String url) {
|
||||
try {
|
||||
int timestamp = 0;
|
||||
final String hours = match.group(1);
|
||||
final String minutes = match.group(2);
|
||||
final String seconds = match.group(3);
|
||||
if (hours != null) {
|
||||
timestamp += (Integer.parseInt(hours.replace(":", "")) * 3600);
|
||||
final TimestampExtractor.TimestampMatchDTO timestampMatchDTO =
|
||||
TimestampExtractor.getTimestampFromMatcher(match, commentText);
|
||||
|
||||
if (timestampMatchDTO == null) {
|
||||
return url;
|
||||
}
|
||||
if (minutes != null) {
|
||||
timestamp += (Integer.parseInt(minutes.replace(":", "")) * 60);
|
||||
}
|
||||
if (seconds != null) {
|
||||
timestamp += (Integer.parseInt(seconds));
|
||||
}
|
||||
return streamUrl + url.replace(match.group(0), "#timestamp=" + timestamp);
|
||||
|
||||
return streamUrl + url.replace(
|
||||
match.group(0),
|
||||
"#timestamp=" + timestampMatchDTO.seconds());
|
||||
} catch (final Exception ex) {
|
||||
Log.e(TAG, "Unable to process url='" + url + "' as timestampLink", ex);
|
||||
return url;
|
||||
@ -262,7 +258,14 @@ public class CommentsMiniInfoItemHolder extends InfoItemHolder {
|
||||
}
|
||||
|
||||
private void linkify() {
|
||||
Linkify.addLinks(itemContentView, Linkify.WEB_URLS);
|
||||
Linkify.addLinks(itemContentView, PATTERN, null, null, timestampLink);
|
||||
Linkify.addLinks(
|
||||
itemContentView,
|
||||
Linkify.WEB_URLS);
|
||||
Linkify.addLinks(
|
||||
itemContentView,
|
||||
TimestampExtractor.TIMESTAMPS_PATTERN,
|
||||
null,
|
||||
null,
|
||||
timestampLink);
|
||||
}
|
||||
}
|
||||
|
@ -32,9 +32,8 @@ import static org.schabi.newpipe.util.external_communication.InternalUrlsHandler
|
||||
|
||||
public final class TextLinkifier {
|
||||
public static final String TAG = TextLinkifier.class.getSimpleName();
|
||||
|
||||
private static final Pattern HASHTAGS_PATTERN = Pattern.compile("(#[A-Za-z0-9_]+)");
|
||||
private static final Pattern TIMESTAMPS_PATTERN = Pattern.compile(
|
||||
"(?:^|(?!:)\\W)(?:([0-5]?[0-9]):)?([0-5]?[0-9]):([0-5][0-9])(?=$|(?!:)\\W)");
|
||||
|
||||
private TextLinkifier() {
|
||||
}
|
||||
@ -174,33 +173,34 @@ public final class TextLinkifier {
|
||||
final Info relatedInfo,
|
||||
final CompositeDisposable disposables) {
|
||||
final String descriptionText = spannableDescription.toString();
|
||||
final Matcher timestampsMatches = TIMESTAMPS_PATTERN.matcher(descriptionText);
|
||||
final Matcher timestampsMatches =
|
||||
TimestampExtractor.TIMESTAMPS_PATTERN.matcher(descriptionText);
|
||||
|
||||
while (timestampsMatches.find()) {
|
||||
final int timestampStart = timestampsMatches.start(2);
|
||||
final int timestampEnd = timestampsMatches.end(3);
|
||||
final String parsedTimestamp = descriptionText.substring(timestampStart, timestampEnd);
|
||||
final String[] timestampParts = parsedTimestamp.split(":");
|
||||
final TimestampExtractor.TimestampMatchDTO timestampMatchDTO =
|
||||
TimestampExtractor.getTimestampFromMatcher(
|
||||
timestampsMatches,
|
||||
descriptionText);
|
||||
|
||||
final int seconds;
|
||||
if (timestampParts.length == 3) { // timestamp format: XX:XX:XX
|
||||
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
|
||||
seconds = Integer.parseInt(timestampParts[0]) * 60 // minutes
|
||||
+ Integer.parseInt(timestampParts[1]); // seconds
|
||||
} else {
|
||||
if (timestampMatchDTO == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
spannableDescription.setSpan(new ClickableSpan() {
|
||||
@Override
|
||||
public void onClick(@NonNull final View view) {
|
||||
playOnPopup(context, relatedInfo.getUrl(), relatedInfo.getService(), seconds,
|
||||
disposables);
|
||||
}
|
||||
}, timestampStart, timestampEnd, 0);
|
||||
spannableDescription.setSpan(
|
||||
new ClickableSpan() {
|
||||
@Override
|
||||
public void onClick(@NonNull final View view) {
|
||||
playOnPopup(
|
||||
context,
|
||||
relatedInfo.getUrl(),
|
||||
relatedInfo.getService(),
|
||||
timestampMatchDTO.seconds(),
|
||||
disposables);
|
||||
}
|
||||
},
|
||||
timestampMatchDTO.timestampStart(),
|
||||
timestampMatchDTO.timestampEnd(),
|
||||
0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,78 @@
|
||||
package org.schabi.newpipe.util.external_communication;
|
||||
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Extracts timestamps.
|
||||
*/
|
||||
public final class TimestampExtractor {
|
||||
public static final Pattern TIMESTAMPS_PATTERN = Pattern.compile(
|
||||
"(?:^|(?!:)\\W)(?:([0-5]?[0-9]):)?([0-5]?[0-9]):([0-5][0-9])(?=$|(?!:)\\W)");
|
||||
|
||||
private TimestampExtractor() {
|
||||
// No impl pls
|
||||
}
|
||||
|
||||
/**
|
||||
* Get's a single timestamp from a matcher.
|
||||
*
|
||||
* @param timestampMatches The matcher which was created using {@link #TIMESTAMPS_PATTERN}
|
||||
* @param baseText The text where the pattern was applied to / where the matcher is based upon
|
||||
* @return If a match occurred: a {@link TimestampMatchDTO} filled with information.<br/>
|
||||
* If not <code>null</code>.
|
||||
*/
|
||||
public static TimestampMatchDTO getTimestampFromMatcher(
|
||||
final Matcher timestampMatches,
|
||||
final String baseText) {
|
||||
int timestampStart = timestampMatches.start(1);
|
||||
if (timestampStart == -1) {
|
||||
timestampStart = timestampMatches.start(2);
|
||||
}
|
||||
final int timestampEnd = timestampMatches.end(3);
|
||||
|
||||
final String parsedTimestamp = baseText.substring(timestampStart, timestampEnd);
|
||||
final String[] timestampParts = parsedTimestamp.split(":");
|
||||
|
||||
final int seconds;
|
||||
if (timestampParts.length == 3) { // timestamp format: XX:XX:XX
|
||||
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
|
||||
seconds = Integer.parseInt(timestampParts[0]) * 60 // minutes
|
||||
+ Integer.parseInt(timestampParts[1]); // seconds
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new TimestampMatchDTO(timestampStart, timestampEnd, seconds);
|
||||
}
|
||||
|
||||
public static class TimestampMatchDTO {
|
||||
private final int timestampStart;
|
||||
private final int timestampEnd;
|
||||
private final int seconds;
|
||||
|
||||
public TimestampMatchDTO(
|
||||
final int timestampStart,
|
||||
final int timestampEnd,
|
||||
final int seconds) {
|
||||
this.timestampStart = timestampStart;
|
||||
this.timestampEnd = timestampEnd;
|
||||
this.seconds = seconds;
|
||||
}
|
||||
|
||||
public int timestampStart() {
|
||||
return timestampStart;
|
||||
}
|
||||
|
||||
public int timestampEnd() {
|
||||
return timestampEnd;
|
||||
}
|
||||
|
||||
public int seconds() {
|
||||
return seconds;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user