Skip to content

Commit

Permalink
Improve NewPipe's share on some devices + fix crash when no browser i…
Browse files Browse the repository at this point in the history
…s set on some devices

Catching ActivityNotFoundException when trying to open the default browser
Use an ACTION_CHOOSER intent and put as an extra intent the intent to
open an URI / share an URI when no default app is set.

Add a LinkHelper class which set a custom action when clicking web links
in the description of a content. This class also helps to implement a confirmation dialog when trying to open web links in an external app.
  • Loading branch information
AudricV committed Jan 11, 2021
1 parent 68175c1 commit 395f6f6
Show file tree
Hide file tree
Showing 13 changed files with 246 additions and 89 deletions.
12 changes: 8 additions & 4 deletions app/src/main/java/org/schabi/newpipe/about/AboutActivity.java
Expand Up @@ -146,16 +146,20 @@ public View onCreateView(@NonNull final LayoutInflater inflater, final ViewGroup
aboutBinding.appVersion.setText(BuildConfig.VERSION_NAME);

aboutBinding.githubLink.setOnClickListener(nv ->
openUrlInBrowser(context, context.getString(R.string.github_url)));
openUrlInBrowser(context, context.getString(R.string.github_url),
false));

aboutBinding.donationLink.setOnClickListener(v ->
openUrlInBrowser(context, context.getString(R.string.donation_url)));
openUrlInBrowser(context, context.getString(R.string.donation_url),
false));

aboutBinding.websiteLink.setOnClickListener(nv ->
openUrlInBrowser(context, context.getString(R.string.website_url)));
openUrlInBrowser(context, context.getString(R.string.website_url),
false));

aboutBinding.privacyPolicyLink.setOnClickListener(v ->
openUrlInBrowser(context, context.getString(R.string.privacy_policy_url)));
openUrlInBrowser(context, context.getString(R.string.privacy_policy_url),
false));

return aboutBinding.getRoot();
}
Expand Down
Expand Up @@ -16,7 +16,6 @@
import android.os.Handler;
import android.os.Looper;
import android.provider.Settings;
import android.text.util.Linkify;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.LayoutInflater;
Expand Down Expand Up @@ -97,6 +96,7 @@
import org.schabi.newpipe.util.DeviceUtils;
import org.schabi.newpipe.util.ExtractorHelper;
import org.schabi.newpipe.util.ImageDisplayConstants;
import org.schabi.newpipe.util.LinkHelper;
import org.schabi.newpipe.util.ListHelper;
import org.schabi.newpipe.util.Localization;
import org.schabi.newpipe.util.NavigationHelper;
Expand All @@ -113,8 +113,6 @@
import java.util.concurrent.TimeUnit;

import icepick.State;
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;
Expand Down Expand Up @@ -1232,7 +1230,8 @@ private void prepareDescription(final Description description) {
if (description.getType() == Description.HTML) {
disposables.add(Single.just(description.getContent())
.map(descriptionText ->
HtmlCompat.fromHtml(descriptionText,
LinkHelper.createLinksFromHtmlBlock(requireContext(),
descriptionText, videoDescriptionView,
HtmlCompat.FROM_HTML_MODE_LEGACY))
.subscribeOn(Schedulers.computation())
.observeOn(AndroidSchedulers.mainThread())
Expand All @@ -1241,15 +1240,13 @@ private void prepareDescription(final Description description) {
videoDescriptionView.setVisibility(View.VISIBLE);
}));
} else if (description.getType() == Description.MARKDOWN) {
final Markwon markwon = Markwon.builder(requireContext())
.usePlugin(LinkifyPlugin.create())
.build();
markwon.setMarkdown(videoDescriptionView, description.getContent());
LinkHelper.createLinksFromMarkdownText(requireContext(), description.getContent(),
videoDescriptionView);
videoDescriptionView.setVisibility(View.VISIBLE);
} else {
//== Description.PLAIN_TEXT
videoDescriptionView.setAutoLinkMask(Linkify.WEB_URLS);
videoDescriptionView.setText(description.getContent(), TextView.BufferType.SPANNABLE);
LinkHelper.createLinksFromPlainText(requireContext(), description.getContent(),
videoDescriptionView);
videoDescriptionView.setVisibility(View.VISIBLE);
}
}
Expand Down
@@ -1,8 +1,6 @@
package org.schabi.newpipe.fragments.list.channel;

import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
Expand Down Expand Up @@ -205,8 +203,7 @@ public void onCreateOptionsMenu(final Menu menu, final MenuInflater inflater) {
private void openRssFeed() {
final ChannelInfo info = currentInfo;
if (info != null) {
final Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(info.getFeedUrl()));
startActivity(intent);
ShareUtils.openUrlInBrowser(requireContext(), info.getFeedUrl(), false);
}
}

Expand Down
10 changes: 3 additions & 7 deletions app/src/main/java/org/schabi/newpipe/report/ErrorActivity.java
Expand Up @@ -246,11 +246,7 @@ public boolean onOptionsItemSelected(final MenuItem item) {
goToReturnActivity();
break;
case R.id.menu_item_share_error:
final Intent intent = new Intent();
intent.setAction(Intent.ACTION_SEND);
intent.putExtra(Intent.EXTRA_TEXT, buildJson());
intent.setType("text/plain");
startActivity(Intent.createChooser(intent, getString(R.string.share_dialog_title)));
ShareUtils.shareUrl(this, getString(R.string.error_report_title), buildJson());
break;
}
return false;
Expand All @@ -273,10 +269,10 @@ private void openPrivacyPolicyDialog(final Context context, final String action)
.putExtra(Intent.EXTRA_SUBJECT, ERROR_EMAIL_SUBJECT)
.putExtra(Intent.EXTRA_TEXT, buildJson());
if (i.resolveActivity(getPackageManager()) != null) {
startActivity(i);
ShareUtils.openContentInApp(context, i);
}
} else if (action.equals("GITHUB")) { // open the NewPipe issue page on GitHub
ShareUtils.openUrlInBrowser(this, ERROR_GITHUB_ISSUE_URL);
ShareUtils.openUrlInBrowser(this, ERROR_GITHUB_ISSUE_URL, false);
}

})
Expand Down
Expand Up @@ -69,7 +69,8 @@ public boolean onTouch(final View v, final MotionEvent event) {
handled = handleUrl(v.getContext(), (URLSpan) link[0]);
}
if (!handled) {
link[0].onClick(widget);
ShareUtils.openUrlInBrowser(v.getContext(),
((URLSpan) link[0]).getURL(), false);
}
} else if (action == MotionEvent.ACTION_DOWN) {
Selection.setSelection(buffer,
Expand Down
Expand Up @@ -364,8 +364,8 @@ public static void showMetaInfoInTextView(@Nullable final List<MetaInfo> metaInf
}
}

metaInfoTextView.setText(HtmlCompat.fromHtml(stringBuilder.toString(),
HtmlCompat.FROM_HTML_SEPARATOR_LINE_BREAK_HEADING));
LinkHelper.createLinksFromHtmlBlock(context, stringBuilder.toString(),
metaInfoTextView, HtmlCompat.FROM_HTML_SEPARATOR_LINE_BREAK_HEADING);
metaInfoTextView.setMovementMethod(LinkMovementMethod.getInstance());
metaInfoTextView.setVisibility(View.VISIBLE);
metaInfoSeparator.setVisibility(View.VISIBLE);
Expand Down
68 changes: 68 additions & 0 deletions app/src/main/java/org/schabi/newpipe/util/LinkHelper.java
@@ -0,0 +1,68 @@
package org.schabi.newpipe.util;

import android.content.Context;
import android.text.SpannableStringBuilder;
import android.text.method.LinkMovementMethod;
import android.text.style.ClickableSpan;
import android.text.style.URLSpan;
import android.text.util.Linkify;
import android.view.View;
import android.widget.TextView;

import androidx.core.text.HtmlCompat;

import io.noties.markwon.Markwon;
import io.noties.markwon.linkify.LinkifyPlugin;

public final class LinkHelper {
private LinkHelper() {
}

public static SpannableStringBuilder createLinksFromHtmlBlock(final Context context,
final String htmlBlock,
final TextView textView,
final int fromHtmlOption) {
return changeIntentOfDescriptionLinks(context, HtmlCompat.fromHtml(htmlBlock,
fromHtmlOption), textView);
}

public static void createLinksFromPlainText(final Context context,
final String plainTextBlock,
final TextView textView) {
textView.setAutoLinkMask(Linkify.WEB_URLS);
textView.setText(plainTextBlock, TextView.BufferType.SPANNABLE);
changeIntentOfDescriptionLinks(context, textView.getText(), textView);
}

public static void createLinksFromMarkdownText(final Context context,
final String markdownBlock,
final TextView textView) {
final Markwon markwon = Markwon.builder(context).usePlugin(LinkifyPlugin.create()).build();
markwon.setMarkdown(textView, markdownBlock);

changeIntentOfDescriptionLinks(context, textView.getText(), textView);
}

private static SpannableStringBuilder changeIntentOfDescriptionLinks(final Context context,
final CharSequence chars,
final TextView textView) {
final SpannableStringBuilder textBlockLinked = new SpannableStringBuilder(chars);
final URLSpan[] urls = textBlockLinked.getSpans(0, chars.length(), URLSpan.class);

for (final URLSpan span : urls) {
final ClickableSpan clickableSpan = new ClickableSpan() {
public void onClick(final View view) {
ShareUtils.openUrlInBrowser(context, span.getURL(), false);
}
};
textBlockLinked.setSpan(clickableSpan, textBlockLinked.getSpanStart(span),
textBlockLinked.getSpanEnd(span), textBlockLinked.getSpanFlags(span));
textBlockLinked.removeSpan(span);
}

textView.setText(textBlockLinked);
textView.setMovementMethod(LinkMovementMethod.getInstance());

return textBlockLinked;
}
}
27 changes: 6 additions & 21 deletions app/src/main/java/org/schabi/newpipe/util/NavigationHelper.java
Expand Up @@ -247,16 +247,14 @@ public static void playOnExternalPlayer(final Context context, final String name

public static void resolveActivityOrAskToInstall(final Context context, final Intent intent) {
if (intent.resolveActivity(context.getPackageManager()) != null) {
context.startActivity(intent);
ShareUtils.openContentInApp(context, intent);
} else {
if (context instanceof Activity) {
new AlertDialog.Builder(context)
.setMessage(R.string.no_player_found)
.setPositiveButton(R.string.install, (dialog, which) -> {
final Intent i = new Intent();
i.setAction(Intent.ACTION_VIEW);
i.setData(Uri.parse(context.getString(R.string.fdroid_vlc_url)));
context.startActivity(i);
ShareUtils.openUrlInBrowser(context,
context.getString(R.string.fdroid_vlc_url), false);
})
.setNegativeButton(R.string.cancel, (dialog, which)
-> Log.i("NavigationHelper", "You unlocked a secret unicorn."))
Expand Down Expand Up @@ -569,27 +567,14 @@ public static Intent getIntentByLink(final Context context,
return getOpenIntent(context, url, service.getServiceId(), linkType);
}

private static Uri openMarketUrl(final String packageName) {
return Uri.parse("market://details")
.buildUpon()
.appendQueryParameter("id", packageName)
.build();
}

private static Uri getGooglePlayUrl(final String packageName) {
return Uri.parse("https://play.google.com/store/apps/details")
.buildUpon()
.appendQueryParameter("id", packageName)
.build();
}

private static void installApp(final Context context, final String packageName) {
try {
// Try market:// scheme
context.startActivity(new Intent(Intent.ACTION_VIEW, openMarketUrl(packageName)));
ShareUtils.openUrlInBrowser(context, "market://details?id=" + packageName, false);
} catch (final ActivityNotFoundException e) {
// Fall back to google play URL (don't worry F-Droid can handle it :)
context.startActivity(new Intent(Intent.ACTION_VIEW, getGooglePlayUrl(packageName)));
ShareUtils.openUrlInBrowser(context,
"https://play.google.com/store/apps/details?id=" + packageName, false);
}
}

Expand Down

0 comments on commit 395f6f6

Please sign in to comment.