summaryrefslogtreecommitdiffstats
path: root/app/src/main/java/app/fedilab/android/helper/SpannableHelper.java
diff options
context:
space:
mode:
Diffstat (limited to 'app/src/main/java/app/fedilab/android/helper/SpannableHelper.java')
-rw-r--r--app/src/main/java/app/fedilab/android/helper/SpannableHelper.java1060
1 files changed, 328 insertions, 732 deletions
diff --git a/app/src/main/java/app/fedilab/android/helper/SpannableHelper.java b/app/src/main/java/app/fedilab/android/helper/SpannableHelper.java
index 26cb125d9..f53c1172a 100644
--- a/app/src/main/java/app/fedilab/android/helper/SpannableHelper.java
+++ b/app/src/main/java/app/fedilab/android/helper/SpannableHelper.java
@@ -41,6 +41,7 @@ import android.text.style.URLSpan;
import android.util.Patterns;
import android.view.LayoutInflater;
import android.view.View;
+import android.webkit.URLUtil;
import android.widget.Toast;
import androidx.annotation.NonNull;
@@ -52,12 +53,6 @@ import androidx.lifecycle.ViewModelStoreOwner;
import androidx.preference.PreferenceManager;
import com.bumptech.glide.Glide;
-import com.google.android.material.dialog.MaterialAlertDialogBuilder;
-
-import org.jsoup.Jsoup;
-import org.jsoup.nodes.Document;
-import org.jsoup.nodes.Element;
-import org.jsoup.select.Elements;
import java.io.IOException;
import java.lang.ref.WeakReference;
@@ -94,20 +89,15 @@ import es.dmoral.toasty.Toasty;
public class SpannableHelper {
public static final String CLICKABLE_SPAN = "CLICKABLE_SPAN";
+ private static int linkColor;
public static Spannable convert(Context context, String text,
- Status status, Account account, Announcement announcement,
- boolean convertHtml, boolean forceMentions, WeakReference<View> viewWeakReference) {
- return convert(context, text, status, account, announcement, convertHtml, forceMentions, viewWeakReference, null);
+ Status status, Account account, Announcement announcement, WeakReference<View> viewWeakReference) {
+ return convert(context, text, status, account, announcement, viewWeakReference, null);
}
-
- private static int linkColor;
-
public static Spannable convert(Context context, String text,
Status status, Account account, Announcement announcement,
- boolean convertHtml,
- boolean forceMentions,
WeakReference<View> viewWeakReference, Status.Callback callback) {
SharedPreferences sharedpreferences = PreferenceManager.getDefaultSharedPreferences(context);
@@ -131,24 +121,126 @@ public class SpannableHelper {
if (linkColor == 0) {
linkColor = -1;
}
- SpannableString initialContent;
- if (text == null) {
- return null;
+ List<Mention> mentions = new ArrayList<>();
+ if (status != null && status.mentions != null) {
+ mentions.addAll(status.mentions);
}
- Document htmlContent = Jsoup.parse(text);
- Elements mentionElements = htmlContent.select("a.mention");
- //We keep a reference to mentions
- HashMap<String, String> mentionsMap = new HashMap<>();
- if (mentionElements.size() > 0) {
- for (int i = 0; i < mentionElements.size(); i++) {
- Element mentionElement = mentionElements.get(i);
- String href = mentionElement.attr("href");
- String mention = mentionElement.text();
- mentionsMap.put(mention, href);
+ text = text.replaceAll("((<\\s?p\\s?>|<\\s?br\\s?/?>)&gt;(((?!(<\\s?br\\s?/?>|<\\s?/s?p\\s?>)).)*))", "$2<blockquote>$3</blockquote>");
+ text = text.trim().replaceAll("\\s{3}", "&nbsp;&nbsp;&nbsp;");
+ text = text.trim().replaceAll("\\s{2}", "&nbsp;&nbsp;");
+ SpannableString initialContent;
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
+ initialContent = new SpannableString(Html.fromHtml(text, Html.FROM_HTML_MODE_LEGACY));
+ else
+ initialContent = new SpannableString(Html.fromHtml(text));
+
+ //Get all links
+ SpannableStringBuilder content = new SpannableStringBuilder(initialContent);
+ URLSpan[] urls = content.getSpans(0, (content.length() - 1), URLSpan.class);
+ //Loop through links
+ for (URLSpan span : urls) {
+ String url = span.getURL();
+ int start = content.getSpanStart(span);
+ int end = content.getSpanEnd(span);
+ if (start < 0 || end > content.length()) {
+ continue;
}
+ content.removeSpan(span);
+ //Get the matching word associated to the URL
+ String word = content.subSequence(start, end).toString();
+ if (word.startsWith("@") || word.startsWith("#")) {
+ content.setSpan(new LongClickableSpan() {
+ @Override
+ public void onLongClick(View textView) {
+ textView.setTag(CLICKABLE_SPAN);
+ if (word.startsWith("#") && BaseMainActivity.filterFetched && MainActivity.mainFilters != null) {
+ String tag = word.trim();
+ if (!tag.startsWith("#")) {
+ tag = "#" + tag;
+ }
+ Filter fedilabFilter = null;
+ for (Filter filter : MainActivity.mainFilters) {
+ if (filter.title.equals(Helper.FEDILAB_MUTED_HASHTAGS)) {
+ fedilabFilter = filter;
+ break;
+ }
+ }
+ //Filter for Fedilab doesn't exist we have to create it
+ if (fedilabFilter == null) {
+ Filter.FilterParams filterParams = new Filter.FilterParams();
+ filterParams.title = Helper.FEDILAB_MUTED_HASHTAGS;
+ filterParams.filter_action = "hide";
+ filterParams.context = new ArrayList<>();
+ filterParams.context.add("home");
+ filterParams.context.add("public");
+ filterParams.context.add("thread");
+ filterParams.context.add("account");
+ String finalTag = tag;
+ FiltersVM filtersVM = new ViewModelProvider((ViewModelStoreOwner) context).get(FiltersVM.class);
+ filtersVM.addFilter(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, filterParams)
+ .observe((LifecycleOwner) context, filter -> {
+ if (filter != null) {
+ MainActivity.mainFilters.add(filter);
+ addTagToFilter(context, finalTag, status, filter);
+ }
+ });
+ } else {
+ addTagToFilter(context, tag, status, fedilabFilter);
+ }
+ }
+ }
+
+ @Override
+ public void onClick(@NonNull View textView) {
+ textView.setTag(CLICKABLE_SPAN);
+ Intent intent;
+ Bundle b;
+ if (word.startsWith("#")) {
+ intent = new Intent(context, HashTagActivity.class);
+ b = new Bundle();
+ b.putString(Helper.ARG_SEARCH_KEYWORD, word.trim());
+ intent.putExtras(b);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ context.startActivity(intent);
+ } else if (word.startsWith("@")) {
+ intent = new Intent(context, ProfileActivity.class);
+ b = new Bundle();
+ Mention targetedMention = null;
+
+ for (Mention mention : mentions) {
+ if (word.compareToIgnoreCase("@" + mention.username) == 0) {
+ targetedMention = mention;
+ break;
+ }
+ }
+ if (targetedMention != null) {
+ b.putString(Helper.ARG_USER_ID, targetedMention.id);
+ } else {
+ b.putString(Helper.ARG_MENTION, word);
+ }
+ intent.putExtras(b);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ context.startActivity(intent);
+ }
+ }
+
+ @Override
+ public void updateDrawState(@NonNull TextPaint ds) {
+ super.updateDrawState(ds);
+ ds.setUnderlineText(false);
+ if (linkColor != -1) {
+ ds.setColor(linkColor);
+ }
+ }
+
+ }, start, end, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
+ } else {
+ makeLinks(context, content, url, start, end);
+ }
+ replaceQuoteSpans(context, content);
+ emails(context, content);
}
- text = text.replaceAll("((<\\s?p\\s?>|<\\s?br\\s?\\/?>)&gt;(((?!([<])).)*))", "$2<blockquote>$3</blockquote>");
Pattern imgPattern = Pattern.compile("<img [^>]*src=\"([^\"]+)\"[^>]*>");
Matcher matcherImg = imgPattern.matcher(text);
HashMap<String, String> imagesToReplace = new LinkedHashMap<>();
@@ -160,57 +252,15 @@ public class SpannableHelper {
text = text.replaceAll(Pattern.quote(matcherImg.group()), replacement);
}
- SpannableStringBuilder content;
View view = viewWeakReference.get();
- List<Mention> mentionList = null;
List<Emoji> emojiList = null;
if (status != null) {
- mentionList = status.mentions;
emojiList = status.emojis;
} else if (account != null) {
emojiList = account.emojis;
} else if (announcement != null) {
emojiList = announcement.emojis;
}
- //UrlDetails will contain links having a text different from the url
- HashMap<String, String> urlDetails = new HashMap<>();
- if (convertHtml) {
- Matcher matcherALink = Helper.aLink.matcher(text);
-
- //We stock details
- while (matcherALink.find()) {
- String urlText = matcherALink.group(3);
- String url = matcherALink.group(2);
- if (urlText != null && urlText.startsWith(">")) {
- urlText = urlText.substring(1);
- }
- if (url != null && urlText != null && !url.equalsIgnoreCase(urlText) && !urlText.contains("<span")) {
- urlDetails.put(url, urlText);
- }
- }
- text = text.trim().replaceAll("\\s{3}", "&nbsp;&nbsp;&nbsp;");
- text = text.trim().replaceAll("\\s{2}", "&nbsp;&nbsp;");
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
- initialContent = new SpannableString(Html.fromHtml(text, Html.FROM_HTML_MODE_LEGACY));
- else
- initialContent = new SpannableString(Html.fromHtml(text));
-
- content = new SpannableStringBuilder(initialContent);
- URLSpan[] urls = content.getSpans(0, (content.length() - 1), URLSpan.class);
- for (URLSpan span : urls) {
- content.removeSpan(span);
- }
- //Make tags, mentions, groups
- interaction(context, content, status, mentionList, forceMentions, mentionsMap);
- //Make all links
- linkify(context, content, urlDetails);
- linkifyURL(context, content, urlDetails);
- emails(context, content);
- gemini(context, content);
- replaceQuoteSpans(context, content);
- } else {
- content = new SpannableStringBuilder(text);
- }
boolean animate = !sharedpreferences.getBoolean(context.getString(R.string.SET_DISABLE_ANIMATED_EMOJI), false);
CustomEmoji customEmoji = new CustomEmoji(new WeakReference<>(view));
content = customEmoji.makeEmoji(content, emojiList, animate, callback);
@@ -234,542 +284,251 @@ public class SpannableHelper {
return trimSpannable(new SpannableStringBuilder(content));
}
- private static void linkify(Context context, SpannableStringBuilder content, HashMap<String, String> urlDetails) {
- //--- URLs ----
- Matcher matcherLink = Patterns.WEB_URL.matcher(content);
-
- int offSetTruncate = 0;
-
-
- while (matcherLink.find()) {
- int matchStart = matcherLink.start() - offSetTruncate;
- int matchEnd = matchStart + matcherLink.group().length();
- if (matchEnd > content.toString().length()) {
- matchEnd = content.toString().length();
- }
-
- if (content.toString().length() < matchEnd || matchStart < 0 || matchStart > matchEnd) {
- continue;
- }
-
-
- final String url = content.toString().substring(matchStart, matchEnd);
- if (urlDetails.containsKey(url)) {
- continue;
- }
-
- ClickableSpan[] clickableSpans = content.getSpans(matchStart, matchEnd, ClickableSpan.class);
- if (clickableSpans != null) {
- for (ClickableSpan clickableSpan : clickableSpans) {
- content.removeSpan(clickableSpan);
- }
- }
- content.removeSpan(clickableSpans);
- String newURL = Helper.transformURL(context, url);
- //If URL has been transformed
- if (newURL.compareTo(url) != 0) {
- content.replace(matchStart, matchEnd, newURL);
- offSetTruncate -= (newURL.length() - url.length());
- matchEnd = matchStart + newURL.length();
- }
- //Truncate URL if needed
- //TODO: add an option to disable truncated URLs
- String urlText = newURL;
- if (newURL.length() > 30 && !urlDetails.containsKey(urlText) && !urlText.startsWith("gemini")) {
- urlText = urlText.substring(0, 30);
- urlText += "…";
- content.replace(matchStart, matchEnd, urlText);
- matchEnd = matchStart + 31;
- offSetTruncate += (newURL.length() - urlText.length());
- }
+ private static void makeLinks(Context context, SpannableStringBuilder content, String url, int start, int end) {
+ String newUrl = url;
+ boolean validUrl = URLUtil.isValidUrl(url) && url.length() == (end - start);
+ if (validUrl) {
+ newUrl = Helper.transformURL(context, url);
+ }
- if (matchEnd <= content.length() && matchEnd >= matchStart) {
- content.setSpan(new LongClickableSpan() {
- @Override
- public void onLongClick(View view) {
- Context mContext = view.getContext();
- MaterialAlertDialogBuilder materialAlertDialogBuilder = new MaterialAlertDialogBuilder(mContext);
- PopupLinksBinding popupLinksBinding = PopupLinksBinding.inflate(LayoutInflater.from(context));
- materialAlertDialogBuilder.setView(popupLinksBinding.getRoot());
- AlertDialog alertDialog = materialAlertDialogBuilder.create();
- alertDialog.show();
- String finalURl = newURL;
- String uniqueUrl = newURL.endsWith("…") ? newURL : newURL + "…";
- if (urlDetails.containsValue(uniqueUrl)) {
- finalURl = Helper.getKeyByValue(urlDetails, uniqueUrl);
- }
- if (finalURl == null) {
- return;
- }
- if (finalURl.startsWith("http://")) {
- finalURl = finalURl.replace("http://", "https://");
- }
- String finalURl1 = finalURl;
- popupLinksBinding.displayFullLink.setOnClickListener(v -> {
- AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
- builder.setMessage(finalURl1);
- builder.setTitle(context.getString(R.string.display_full_link));
- builder.setPositiveButton(R.string.close, (dialog, which) -> dialog.dismiss())
- .show();
- alertDialog.dismiss();
- });
- popupLinksBinding.shareLink.setOnClickListener(v -> {
- Intent sendIntent = new Intent(Intent.ACTION_SEND);
- sendIntent.putExtra(Intent.EXTRA_SUBJECT, context.getString(R.string.shared_via));
- sendIntent.putExtra(Intent.EXTRA_TEXT, finalURl1);
- sendIntent.setType("text/plain");
- sendIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- Intent intentChooser = Intent.createChooser(sendIntent, context.getString(R.string.share_with));
- intentChooser.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- context.startActivity(intentChooser);
- alertDialog.dismiss();
- });
+ //If URL has been transformed
+ if (validUrl && newUrl.compareTo(url) != 0) {
+ content.replace(start, end, newUrl);
+ end = start + newUrl.length();
+ url = newUrl;
+ }
+ if (url.length() > 30 && (validUrl || url.startsWith("gimini://"))) {
+ newUrl = url.substring(0, 30);
+ newUrl += "…";
+ content.replace(start, end, newUrl);
+ }
+ int matchEnd = validUrl ? start + newUrl.length() : end;
- popupLinksBinding.openOtherApp.setOnClickListener(v -> {
- Intent intent = new Intent(Intent.ACTION_VIEW);
- intent.setData(Uri.parse(finalURl1));
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- try {
- context.startActivity(intent);
- } catch (Exception e) {
- Toasty.error(context, context.getString(R.string.toast_error), Toast.LENGTH_LONG).show();
- }
- alertDialog.dismiss();
- });
+ String finalUrl = url;
+ if (content.length() < matchEnd) {
+ matchEnd = content.length();
+ }
+ content.setSpan(new LongClickableSpan() {
+ @Override
+ public void onLongClick(View view) {
+ Context mContext = view.getContext();
+ AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(mContext);
+ PopupLinksBinding popupLinksBinding = PopupLinksBinding.inflate(LayoutInflater.from(context));
+ dialogBuilder.setView(popupLinksBinding.getRoot());
+ AlertDialog alertDialog = dialogBuilder.create();
+ alertDialog.show();
+ popupLinksBinding.displayFullLink.setOnClickListener(v -> {
+ AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
+ builder.setMessage(finalUrl);
+ builder.setTitle(context.getString(R.string.display_full_link));
+ builder.setPositiveButton(R.string.close, (dialog, which) -> dialog.dismiss())
+ .show();
+ alertDialog.dismiss();
+ });
+ popupLinksBinding.shareLink.setOnClickListener(v -> {
+ Intent sendIntent = new Intent(Intent.ACTION_SEND);
+ sendIntent.putExtra(Intent.EXTRA_SUBJECT, context.getString(R.string.shared_via));
+ sendIntent.putExtra(Intent.EXTRA_TEXT, finalUrl);
+ sendIntent.setType("text/plain");
+ sendIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ Intent intentChooser = Intent.createChooser(sendIntent, context.getString(R.string.share_with));
+ intentChooser.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ context.startActivity(intentChooser);
+ alertDialog.dismiss();
+ });
+
+ popupLinksBinding.openOtherApp.setOnClickListener(v -> {
+ Intent intent = new Intent(Intent.ACTION_VIEW);
+ intent.setData(Uri.parse(finalUrl));
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ try {
+ context.startActivity(intent);
+ } catch (Exception e) {
+ Toasty.error(context, context.getString(R.string.toast_error), Toast.LENGTH_LONG).show();
+ }
+ alertDialog.dismiss();
+ });
+
+ popupLinksBinding.copyLink.setOnClickListener(v -> {
+ ClipboardManager clipboard = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
+ ClipData clip = ClipData.newPlainText(Helper.CLIP_BOARD, finalUrl);
+ if (clipboard != null) {
+ clipboard.setPrimaryClip(clip);
+ Toasty.info(context, context.getString(R.string.clipboard_url), Toast.LENGTH_LONG).show();
+ }
+ alertDialog.dismiss();
+ });
- popupLinksBinding.copyLink.setOnClickListener(v -> {
- ClipboardManager clipboard = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
- ClipData clip = ClipData.newPlainText(Helper.CLIP_BOARD, finalURl1);
- if (clipboard != null) {
- clipboard.setPrimaryClip(clip);
- Toasty.info(context, context.getString(R.string.clipboard_url), Toast.LENGTH_LONG).show();
- }
- alertDialog.dismiss();
- });
+ popupLinksBinding.checkRedirect.setOnClickListener(v -> {
+ try {
- popupLinksBinding.checkRedirect.setOnClickListener(v -> {
+ URL finalUrlCheck = new URL(finalUrl);
+ new Thread(() -> {
try {
-
- URL finalUrlCheck = new URL(finalURl1);
- new Thread(() -> {
- try {
- String redirect = null;
- HttpsURLConnection httpsURLConnection = (HttpsURLConnection) finalUrlCheck.openConnection();
- httpsURLConnection.setConnectTimeout(10 * 1000);
- httpsURLConnection.setRequestProperty("http.keepAlive", "false");
- // httpsURLConnection.setRequestProperty("User-Agent", USER_AGENT);
- httpsURLConnection.setRequestMethod("HEAD");
- httpsURLConnection.setInstanceFollowRedirects(false);
- if (httpsURLConnection.getResponseCode() == 301 || httpsURLConnection.getResponseCode() == 302) {
- Map<String, List<String>> map = httpsURLConnection.getHeaderFields();
- for (Map.Entry<String, List<String>> entry : map.entrySet()) {
- if (entry.toString().toLowerCase().startsWith("location")) {
- Matcher matcher = Patterns.WEB_URL.matcher(entry.toString());
- if (matcher.find()) {
- redirect = matcher.group(1);
- }
- }
+ String redirect = null;
+ HttpsURLConnection httpsURLConnection = (HttpsURLConnection) finalUrlCheck.openConnection();
+ httpsURLConnection.setConnectTimeout(10 * 1000);
+ httpsURLConnection.setRequestProperty("http.keepAlive", "false");
+ //httpsURLConnection.setRequestProperty("User-Agent", USER_AGENT);
+ httpsURLConnection.setRequestMethod("HEAD");
+ httpsURLConnection.setInstanceFollowRedirects(false);
+ if (httpsURLConnection.getResponseCode() == 301 || httpsURLConnection.getResponseCode() == 302) {
+ Map<String, List<String>> map = httpsURLConnection.getHeaderFields();
+ for (Map.Entry<String, List<String>> entry : map.entrySet()) {
+ if (entry.toString().toLowerCase().startsWith("location")) {
+ Matcher matcher = Patterns.WEB_URL.matcher(entry.toString());
+ if (matcher.find()) {
+ redirect = matcher.group(1);
}
}
- httpsURLConnection.getInputStream().close();
- if (redirect != null && redirect.compareTo(finalURl1) != 0) {
- URL redirectURL = new URL(redirect);
- String host = redirectURL.getHost();
- String protocol = redirectURL.getProtocol();
- if (protocol == null || host == null) {
- redirect = null;
- }
- }
- Handler mainHandler = new Handler(context.getMainLooper());
- String finalRedirect = redirect;
- Runnable myRunnable = () -> {
- AlertDialog.Builder builder1 = new AlertDialog.Builder(view.getContext());
- if (finalRedirect != null) {
- builder1.setMessage(context.getString(R.string.redirect_detected, finalURl1, finalRedirect));
- builder1.setNegativeButton(R.string.copy_link, (dialog, which) -> {
- ClipboardManager clipboard1 = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
- ClipData clip1 = ClipData.newPlainText(Helper.CLIP_BOARD, finalRedirect);
- if (clipboard1 != null) {
- clipboard1.setPrimaryClip(clip1);
- Toasty.info(context, context.getString(R.string.clipboard_url), Toast.LENGTH_LONG).show();
- }
- dialog.dismiss();
- });
- builder1.setNeutralButton(R.string.share_link, (dialog, which) -> {
- Intent sendIntent1 = new Intent(Intent.ACTION_SEND);
- sendIntent1.putExtra(Intent.EXTRA_SUBJECT, context.getString(R.string.shared_via));
- sendIntent1.putExtra(Intent.EXTRA_TEXT, finalURl1);
- sendIntent1.setType("text/plain");
- context.startActivity(Intent.createChooser(sendIntent1, context.getString(R.string.share_with)));
- dialog.dismiss();
- });
- } else {
- builder1.setMessage(R.string.no_redirect);
- }
- builder1.setTitle(context.getString(R.string.check_redirect));
- builder1.setPositiveButton(R.string.close, (dialog, which) -> dialog.dismiss())
- .show();
-
- };
- mainHandler.post(myRunnable);
- } catch (IOException e) {
- e.printStackTrace();
- }
-
- }).start();
- } catch (MalformedURLException e) {
- e.printStackTrace();
- }
-
- alertDialog.dismiss();
- });
-
- }
-
- @Override
- public void onClick(@NonNull View textView) {
- String finalURl = newURL;
- String finalURl2 = url;
- String uniqueNewURL = newURL.endsWith("…") ? newURL : newURL + "…";
- if (urlDetails.containsValue(uniqueNewURL)) {
- finalURl = Helper.getKeyByValue(urlDetails, uniqueNewURL);
- }
- String uniqueUrl = url.endsWith("…") ? url : url + "…";
- if (urlDetails.containsValue(uniqueUrl)) {
- finalURl2 = Helper.getKeyByValue(urlDetails, uniqueUrl);
- }
- textView.setTag(CLICKABLE_SPAN);
- Pattern link = Pattern.compile("https?://([\\da-z.-]+\\.[a-z.]{2,10})/(@[\\w._-]*[0-9]*)(/[0-9]+)?$");
- Matcher matcherLink = null;
- if (finalURl2 != null) {
- matcherLink = link.matcher(finalURl2);
- }
- if (finalURl2 != null && matcherLink.find() && !finalURl2.contains("medium.com")) {
- if (matcherLink.group(3) != null && Objects.requireNonNull(matcherLink.group(3)).length() > 0) { //It's a toot
- CrossActionHelper.fetchRemoteStatus(context, currentAccount, finalURl2, new CrossActionHelper.Callback() {
- @Override
- public void federatedStatus(Status status) {
- Intent intent = new Intent(context, ContextActivity.class);
- intent.putExtra(Helper.ARG_STATUS, status);
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- context.startActivity(intent);
}
-
- @Override
- public void federatedAccount(Account account) {
+ }
+ httpsURLConnection.getInputStream().close();
+ if (redirect != null && redirect.compareTo(finalUrl) != 0) {
+ URL redirectURL = new URL(redirect);
+ String host = redirectURL.getHost();
+ String protocol = redirectURL.getProtocol();
+ if (protocol == null || host == null) {
+ redirect = null;
}
- });
- } else {//It's an account
- CrossActionHelper.fetchRemoteAccount(context, currentAccount, matcherLink.group(2) + "@" + matcherLink.group(1), new CrossActionHelper.Callback() {
- @Override
- public void federatedStatus(Status status) {
+ }
+ Handler mainHandler = new Handler(context.getMainLooper());
+ String finalRedirect = redirect;
+ Runnable myRunnable = () -> {
+ AlertDialog.Builder builder1 = new AlertDialog.Builder(view.getContext());
+ if (finalRedirect != null) {
+ builder1.setMessage(context.getString(R.string.redirect_detected, finalUrl, finalRedirect));
+ builder1.setNegativeButton(R.string.copy_link, (dialog, which) -> {
+ ClipboardManager clipboard1 = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
+ ClipData clip1 = ClipData.newPlainText(Helper.CLIP_BOARD, finalRedirect);
+ if (clipboard1 != null) {
+ clipboard1.setPrimaryClip(clip1);
+ Toasty.info(context, context.getString(R.string.clipboard_url), Toast.LENGTH_LONG).show();
+ }
+ dialog.dismiss();
+ });
+ builder1.setNeutralButton(R.string.share_link, (dialog, which) -> {
+ Intent sendIntent1 = new Intent(Intent.ACTION_SEND);
+ sendIntent1.putExtra(Intent.EXTRA_SUBJECT, context.getString(R.string.shared_via));
+ sendIntent1.putExtra(Intent.EXTRA_TEXT, finalUrl);
+ sendIntent1.setType("text/plain");
+ context.startActivity(Intent.createChooser(sendIntent1, context.getString(R.string.share_with)));
+ dialog.dismiss();
+ });
+ } else {
+ builder1.setMessage(R.string.no_redirect);
}
+ builder1.setTitle(context.getString(R.string.check_redirect));
+ builder1.setPositiveButton(R.string.close, (dialog, which) -> dialog.dismiss())
+ .show();
- @Override
- public void federatedAccount(Account account) {
- Intent intent = new Intent(context, ProfileActivity.class);
- Bundle b = new Bundle();
- b.putSerializable(Helper.ARG_ACCOUNT, account);
- intent.putExtras(b);
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- context.startActivity(intent);
- }
- });
+ };
+ mainHandler.post(myRunnable);
+ } catch (IOException e) {
+ e.printStackTrace();
}
- } else {
- Helper.openBrowser(context, finalURl);
- }
+ }).start();
+ } catch (MalformedURLException e) {
+ e.printStackTrace();
}
- @Override
- public void updateDrawState(@NonNull TextPaint ds) {
- super.updateDrawState(ds);
- if (linkColor != -1) {
- ds.setColor(linkColor);
- }
- }
-
- }, matchStart, matchEnd, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
- }
- }
- }
-
- private static void linkifyURL(Context context, SpannableStringBuilder content, HashMap<String, String> urlDetails) {
+ alertDialog.dismiss();
+ });
- for (Map.Entry<String, String> entry : urlDetails.entrySet()) {
- String value = entry.getValue();
- if (value.startsWith("@") || value.startsWith("#")) {
- continue;
- }
- SpannableString contentUrl;
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
- contentUrl = new SpannableString(Html.fromHtml(value, Html.FROM_HTML_MODE_LEGACY));
- else
- contentUrl = new SpannableString(Html.fromHtml(value));
- if (contentUrl.toString().trim().isEmpty()) {
- continue;
}
- Pattern word = Pattern.compile(Pattern.quote(contentUrl.toString()));
- Matcher matcherLink = word.matcher(content);
- while (matcherLink.find()) {
- String url = entry.getKey();
- int matchStart = matcherLink.start();
- int matchEnd = matchStart + matcherLink.group().length();
- if (matchEnd > content.toString().length()) {
- matchEnd = content.toString().length();
- }
- if (content.toString().length() < matchEnd || matchStart < 0 || matchStart > matchEnd) {
- continue;
- }
-
- ClickableSpan[] clickableSpans = content.getSpans(matchStart, matchEnd, ClickableSpan.class);
- if (clickableSpans != null) {
- for (ClickableSpan clickableSpan : clickableSpans) {
- content.removeSpan(clickableSpan);
- }
- }
- content.removeSpan(clickableSpans);
+ @Override
+ public void onClick(@NonNull View textView) {
+
+ textView.setTag(CLICKABLE_SPAN);
+ Pattern link = Pattern.compile("https?://([\\da-z.-]+\\.[a-z.]{2,10})/(@[\\w._-]*[0-9]*)(/[0-9]+)?$");
+ Matcher matcherLink = link.matcher(finalUrl);
+ Pattern linkLong = Pattern.compile("https?://([\\da-z.-]+\\.[a-z.]{2,10})/(@[\\w_.-]+@[a-zA-Z0-9][a-zA-Z0-9.-]{1,61}[a-zA-Z0-9](?:\\.[a-zA-Z]{2,})+)(/[0-9]+)?$");
+ Matcher matcherLinkLong = linkLong.matcher(finalUrl);
+ if (matcherLink.find() && !finalUrl.contains("medium.com")) {
+ if (matcherLink.group(3) != null && Objects.requireNonNull(matcherLink.group(3)).length() > 0) { //It's a toot
+ CrossActionHelper.fetchRemoteStatus(context, currentAccount, finalUrl, new CrossActionHelper.Callback() {
+ @Override
+ public void federatedStatus(Status status) {
+ Intent intent = new Intent(context, ContextActivity.class);
+ intent.putExtra(Helper.ARG_STATUS, status);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ context.startActivity(intent);
+ }
-