Initial work: use disposables for timestamps parsing in YouTube video descriptions and YouTube comments

This commit is contained in:
TiA4f8R 2021-04-04 16:37:09 +02:00
parent f13f4cc5d2
commit da4d379b22
No known key found for this signature in database
GPG Key ID: E6D3E7F5949450DD
3 changed files with 40 additions and 24 deletions

View File

@ -13,6 +13,8 @@ import android.widget.TextView;
import org.schabi.newpipe.util.external_communication.ShareUtils;
import org.schabi.newpipe.util.external_communication.InternalUrlsHandler;
import io.reactivex.rxjava3.disposables.CompositeDisposable;
public class CommentTextOnTouchListener implements View.OnTouchListener {
public static final CommentTextOnTouchListener INSTANCE = new CommentTextOnTouchListener();
@ -50,8 +52,8 @@ public class CommentTextOnTouchListener implements View.OnTouchListener {
if (action == MotionEvent.ACTION_UP) {
if (link[0] instanceof URLSpan) {
final String url = ((URLSpan) link[0]).getURL();
if (!InternalUrlsHandler.handleUrlCommentsTimestamp(v.getContext(),
url)) {
if (!InternalUrlsHandler.handleUrlCommentsTimestamp(
new CompositeDisposable(), v.getContext(), url)) {
ShareUtils.openUrlInBrowser(v.getContext(), url, false);
}
}

View File

@ -18,6 +18,7 @@ import java.util.regex.Pattern;
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
import io.reactivex.rxjava3.core.Single;
import io.reactivex.rxjava3.disposables.CompositeDisposable;
import io.reactivex.rxjava3.schedulers.Schedulers;
import static org.schabi.newpipe.extractor.utils.Utils.isNullOrEmpty;
@ -38,12 +39,15 @@ public final class InternalUrlsHandler {
* popup player will be opened when the user will click on the timestamp in the comment,
* at the time and for the video indicated in the timestamp.
*
* @param context the context to use
* @param url the URL to check if it can be handled
* @param disposables a field of the Activity/Fragment class that calls this method
* @param context the context to use
* @param url the URL to check if it can be handled
* @return true if the URL can be handled by NewPipe, false if it cannot
*/
public static boolean handleUrlCommentsTimestamp(final Context context, final String url) {
return handleUrl(context, url, HASHTAG_TIMESTAMP_PATTERN);
public static boolean handleUrlCommentsTimestamp(final CompositeDisposable disposables,
final Context context,
final String url) {
return handleUrl(disposables, context, url, HASHTAG_TIMESTAMP_PATTERN);
}
/**
@ -54,12 +58,15 @@ public final class InternalUrlsHandler {
* player will be opened when the user will click on the timestamp in the video description,
* at the time and for the video indicated in the timestamp.
*
* @param context the context to use
* @param url the URL to check if it can be handled
* @param disposables a field of the Activity/Fragment class that calls this method
* @param context the context to use
* @param url the URL to check if it can be handled
* @return true if the URL can be handled by NewPipe, false if it cannot
*/
public static boolean handleUrlDescriptionTimestamp(final Context context, final String url) {
return handleUrl(context, url, AMPERSAND_TIMESTAMP_PATTERN);
public static boolean handleUrlDescriptionTimestamp(final CompositeDisposable disposables,
final Context context,
final String url) {
return handleUrl(disposables, context, url, AMPERSAND_TIMESTAMP_PATTERN);
}
/**
@ -69,12 +76,14 @@ public final class InternalUrlsHandler {
* service URL with a timestamp, the popup player will be opened and true will be returned;
* else, false will be returned.
*
* @param context the context to use
* @param url the URL to check if it can be handled
* @param pattern the pattern
* @param disposables a field of the Activity/Fragment class that calls this method
* @param context the context to use
* @param url the URL to check if it can be handled
* @param pattern the pattern to use
* @return true if the URL can be handled by NewPipe, false if it cannot
*/
private static boolean handleUrl(final Context context,
private static boolean handleUrl(final CompositeDisposable disposables,
final Context context,
final String url,
final Pattern pattern) {
final String matchedUrl;
@ -102,7 +111,7 @@ public final class InternalUrlsHandler {
return false;
}
if (linkType == StreamingService.LinkType.STREAM && seconds != -1) {
return playOnPopup(context, matchedUrl, service, seconds);
return playOnPopup(disposables, context, matchedUrl, service, seconds);
} else {
NavigationHelper.openRouterActivity(context, matchedUrl);
return true;
@ -112,13 +121,15 @@ public final class InternalUrlsHandler {
/**
* Play a content in the floating player.
*
* @param context the context to be used
* @param url the URL of the content
* @param service the service of the content
* @param seconds the position in seconds at which the floating player will start
* @param disposables a field of the Activity/Fragment class that calls this method
* @param context the context to be used
* @param url the URL of the content
* @param service the service of the content
* @param seconds the position in seconds at which the floating player will start
* @return true if the playback of the content has successfully started or false if not
*/
public static boolean playOnPopup(final Context context,
public static boolean playOnPopup(final CompositeDisposable disposables,
final Context context,
final String url,
final StreamingService service,
final int seconds) {
@ -133,13 +144,13 @@ public final class InternalUrlsHandler {
final Single<StreamInfo> single
= ExtractorHelper.getStreamInfo(service.getServiceId(), cleanUrl, false);
single.subscribeOn(Schedulers.io())
disposables.add(single.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(info -> {
final PlayQueue playQueue
= new SinglePlayQueue(info, seconds * 1000);
NavigationHelper.playOnPopupPlayer(context, playQueue, false);
});
}));
return true;
}
}

View File

@ -23,6 +23,7 @@ import io.noties.markwon.Markwon;
import io.noties.markwon.linkify.LinkifyPlugin;
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
import io.reactivex.rxjava3.core.Single;
import io.reactivex.rxjava3.disposables.CompositeDisposable;
import io.reactivex.rxjava3.disposables.Disposable;
import io.reactivex.rxjava3.schedulers.Schedulers;
@ -201,7 +202,8 @@ public final class TextLinkifier {
spannableDescription.setSpan(new ClickableSpan() {
@Override
public void onClick(@NonNull final View view) {
playOnPopup(context, contentUrl, streamingService, time);
playOnPopup(new CompositeDisposable(), context, contentUrl, streamingService,
time);
}
}, timestampStart, timestampEnd, 0);
}
@ -245,7 +247,8 @@ public final class TextLinkifier {
final String url = span.getURL();
final ClickableSpan clickableSpan = new ClickableSpan() {
public void onClick(@NonNull final View view) {
if (!InternalUrlsHandler.handleUrlDescriptionTimestamp(context, url)) {
if (!InternalUrlsHandler.handleUrlDescriptionTimestamp(
new CompositeDisposable(), context, url)) {
ShareUtils.openUrlInBrowser(context, url, false);
}
}