Skip to content

Commit

Permalink
Use better pattern for matching timestamp in text and some reworks
Browse files Browse the repository at this point in the history
Also extracted overhead code into ``TimestampExtractor``
  • Loading branch information
litetex committed Aug 6, 2021
1 parent 1d61bb5 commit 9f8b226
Show file tree
Hide file tree
Showing 3 changed files with 121 additions and 40 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,10 @@
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;

Expand All @@ -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;
Expand All @@ -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);
}
if (minutes != null) {
timestamp += (Integer.parseInt(minutes.replace(":", "")) * 60);
}
if (seconds != null) {
timestamp += (Integer.parseInt(seconds));
final TimestampExtractor.TimestampMatchDTO timestampMatchDTO =
TimestampExtractor.getTimestampFromMatcher(match, commentText);

if (timestampMatchDTO == null) {
return url;
}
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;
Expand Down Expand Up @@ -262,7 +258,14 @@ private void expand() {
}

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);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,8 @@

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() {
}
Expand Down Expand Up @@ -174,33 +173,34 @@ private static void addClickListenersOnTimestamps(final Context context,
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);
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -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;
}
}
}

0 comments on commit 9f8b226

Please sign in to comment.