mirror of
https://github.com/TeamNewPipe/NewPipe
synced 2024-12-23 16:40:32 +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.ImageDisplayConstants;
|
||||||
import org.schabi.newpipe.util.Localization;
|
import org.schabi.newpipe.util.Localization;
|
||||||
import org.schabi.newpipe.util.NavigationHelper;
|
import org.schabi.newpipe.util.NavigationHelper;
|
||||||
|
import org.schabi.newpipe.util.external_communication.TimestampExtractor;
|
||||||
import org.schabi.newpipe.util.external_communication.ShareUtils;
|
import org.schabi.newpipe.util.external_communication.ShareUtils;
|
||||||
|
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
|
||||||
|
|
||||||
import de.hdodenhof.circleimageview.CircleImageView;
|
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_DEFAULT_LINES = 2;
|
||||||
private static final int COMMENT_EXPANDED_LINES = 1000;
|
private static final int COMMENT_EXPANDED_LINES = 1000;
|
||||||
private static final Pattern PATTERN = Pattern.compile("(\\d+:)?(\\d+)?:(\\d+)");
|
|
||||||
private final String downloadThumbnailKey;
|
private final String downloadThumbnailKey;
|
||||||
private final int commentHorizontalPadding;
|
private final int commentHorizontalPadding;
|
||||||
private final int commentVerticalPadding;
|
private final int commentVerticalPadding;
|
||||||
@ -57,20 +57,16 @@ public class CommentsMiniInfoItemHolder extends InfoItemHolder {
|
|||||||
@Override
|
@Override
|
||||||
public String transformUrl(final Matcher match, final String url) {
|
public String transformUrl(final Matcher match, final String url) {
|
||||||
try {
|
try {
|
||||||
int timestamp = 0;
|
final TimestampExtractor.TimestampMatchDTO timestampMatchDTO =
|
||||||
final String hours = match.group(1);
|
TimestampExtractor.getTimestampFromMatcher(match, commentText);
|
||||||
final String minutes = match.group(2);
|
|
||||||
final String seconds = match.group(3);
|
if (timestampMatchDTO == null) {
|
||||||
if (hours != null) {
|
return url;
|
||||||
timestamp += (Integer.parseInt(hours.replace(":", "")) * 3600);
|
|
||||||
}
|
}
|
||||||
if (minutes != null) {
|
|
||||||
timestamp += (Integer.parseInt(minutes.replace(":", "")) * 60);
|
return streamUrl + url.replace(
|
||||||
}
|
match.group(0),
|
||||||
if (seconds != null) {
|
"#timestamp=" + timestampMatchDTO.seconds());
|
||||||
timestamp += (Integer.parseInt(seconds));
|
|
||||||
}
|
|
||||||
return streamUrl + url.replace(match.group(0), "#timestamp=" + timestamp);
|
|
||||||
} catch (final Exception ex) {
|
} catch (final Exception ex) {
|
||||||
Log.e(TAG, "Unable to process url='" + url + "' as timestampLink", ex);
|
Log.e(TAG, "Unable to process url='" + url + "' as timestampLink", ex);
|
||||||
return url;
|
return url;
|
||||||
@ -262,7 +258,14 @@ public class CommentsMiniInfoItemHolder extends InfoItemHolder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void linkify() {
|
private void linkify() {
|
||||||
Linkify.addLinks(itemContentView, Linkify.WEB_URLS);
|
Linkify.addLinks(
|
||||||
Linkify.addLinks(itemContentView, PATTERN, null, null, timestampLink);
|
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 final class TextLinkifier {
|
||||||
public static final String TAG = TextLinkifier.class.getSimpleName();
|
public static final String TAG = TextLinkifier.class.getSimpleName();
|
||||||
|
|
||||||
private static final Pattern HASHTAGS_PATTERN = Pattern.compile("(#[A-Za-z0-9_]+)");
|
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() {
|
private TextLinkifier() {
|
||||||
}
|
}
|
||||||
@ -174,33 +173,34 @@ public final class TextLinkifier {
|
|||||||
final Info relatedInfo,
|
final Info relatedInfo,
|
||||||
final CompositeDisposable disposables) {
|
final CompositeDisposable disposables) {
|
||||||
final String descriptionText = spannableDescription.toString();
|
final String descriptionText = spannableDescription.toString();
|
||||||
final Matcher timestampsMatches = TIMESTAMPS_PATTERN.matcher(descriptionText);
|
final Matcher timestampsMatches =
|
||||||
|
TimestampExtractor.TIMESTAMPS_PATTERN.matcher(descriptionText);
|
||||||
|
|
||||||
while (timestampsMatches.find()) {
|
while (timestampsMatches.find()) {
|
||||||
final int timestampStart = timestampsMatches.start(2);
|
final TimestampExtractor.TimestampMatchDTO timestampMatchDTO =
|
||||||
final int timestampEnd = timestampsMatches.end(3);
|
TimestampExtractor.getTimestampFromMatcher(
|
||||||
final String parsedTimestamp = descriptionText.substring(timestampStart, timestampEnd);
|
timestampsMatches,
|
||||||
final String[] timestampParts = parsedTimestamp.split(":");
|
descriptionText);
|
||||||
|
|
||||||
final int seconds;
|
if (timestampMatchDTO == null) {
|
||||||
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 {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
spannableDescription.setSpan(new ClickableSpan() {
|
spannableDescription.setSpan(
|
||||||
|
new ClickableSpan() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(@NonNull final View view) {
|
public void onClick(@NonNull final View view) {
|
||||||
playOnPopup(context, relatedInfo.getUrl(), relatedInfo.getService(), seconds,
|
playOnPopup(
|
||||||
|
context,
|
||||||
|
relatedInfo.getUrl(),
|
||||||
|
relatedInfo.getService(),
|
||||||
|
timestampMatchDTO.seconds(),
|
||||||
disposables);
|
disposables);
|
||||||
}
|
}
|
||||||
}, timestampStart, timestampEnd, 0);
|
},
|
||||||
|
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