Loading app/src/main/java/app/fedilab/android/helper/Helper.java +2 −0 Original line number Diff line number Diff line Loading @@ -334,6 +334,8 @@ public class Helper { public static final Pattern bibliogramPattern = Pattern.compile("(m\\.|www\\.)?instagram.com(/p/[\\w-/]+)"); public static final Pattern libredditPattern = Pattern.compile("(www\\.|m\\.)?(reddit\\.com|preview\\.redd\\.it|i\\.redd\\.it|redd\\.it)/(((?!([\"'<])).)*)"); public static final Pattern ouichesPattern = Pattern.compile("https?://ouich\\.es/tag/(\\w+)"); public static final Pattern geminiPattern = Pattern.compile("(gemini://.*)\\b"); public static final Pattern xmppPattern = Pattern.compile("xmpp:[-a-zA-Z0-9+$&@#/%?=~_|!:,.;]*[-a-zA-Z0-9+&@#/%=~_|]"); public static final Pattern peertubePattern = Pattern.compile("(https?://([\\da-z.-]+\\.[a-z.]{2,10}))/videos/watch/(\\w{8}-\\w{4}-\\w{4}-\\w{4}-\\w{12})$"); public static final Pattern mediumPattern = Pattern.compile("([\\w@-]*)?\\.?medium.com/@?([/\\w-]+)"); Loading app/src/main/java/app/fedilab/android/helper/SpannableHelper.java +33 −0 Original line number Diff line number Diff line Loading @@ -147,6 +147,7 @@ public class SpannableHelper { linkify(context, content, urlDetails); linkifyURL(context, content, urlDetails); emails(context, content); gemini(context, content); replaceQuoteSpans(context, content); } else { content = new SpannableStringBuilder(text); Loading Loading @@ -668,6 +669,38 @@ public class SpannableHelper { } } private static void gemini(Context context, Spannable content) { // --- For all patterns defined in Helper class --- Pattern pattern = Helper.geminiPattern; Matcher matcher = pattern.matcher(content); while (matcher.find()) { int matchStart = matcher.start(); int matchEnd = matcher.end(); String geminiLink = content.toString().substring(matchStart, matchEnd); if (matchStart >= 0 && matchEnd <= content.toString().length() && matchEnd >= matchStart) { ClickableSpan[] clickableSpans = content.getSpans(matchStart, matchEnd, ClickableSpan.class); if (clickableSpans != null) { for (ClickableSpan clickableSpan : clickableSpans) { content.removeSpan(clickableSpan); } } content.removeSpan(clickableSpans); content.setSpan(new ClickableSpan() { @Override public void onClick(@NonNull View textView) { Helper.openBrowser(context, geminiLink); } @Override public void updateDrawState(@NonNull TextPaint ds) { super.updateDrawState(ds); ds.setUnderlineText(false); ds.setColor(linkColor); } }, matchStart, matchEnd, Spanned.SPAN_INCLUSIVE_EXCLUSIVE); } } } private static void emails(Context context, Spannable content) { // --- For all patterns defined in Helper class --- Loading Loading
app/src/main/java/app/fedilab/android/helper/Helper.java +2 −0 Original line number Diff line number Diff line Loading @@ -334,6 +334,8 @@ public class Helper { public static final Pattern bibliogramPattern = Pattern.compile("(m\\.|www\\.)?instagram.com(/p/[\\w-/]+)"); public static final Pattern libredditPattern = Pattern.compile("(www\\.|m\\.)?(reddit\\.com|preview\\.redd\\.it|i\\.redd\\.it|redd\\.it)/(((?!([\"'<])).)*)"); public static final Pattern ouichesPattern = Pattern.compile("https?://ouich\\.es/tag/(\\w+)"); public static final Pattern geminiPattern = Pattern.compile("(gemini://.*)\\b"); public static final Pattern xmppPattern = Pattern.compile("xmpp:[-a-zA-Z0-9+$&@#/%?=~_|!:,.;]*[-a-zA-Z0-9+&@#/%=~_|]"); public static final Pattern peertubePattern = Pattern.compile("(https?://([\\da-z.-]+\\.[a-z.]{2,10}))/videos/watch/(\\w{8}-\\w{4}-\\w{4}-\\w{4}-\\w{12})$"); public static final Pattern mediumPattern = Pattern.compile("([\\w@-]*)?\\.?medium.com/@?([/\\w-]+)"); Loading
app/src/main/java/app/fedilab/android/helper/SpannableHelper.java +33 −0 Original line number Diff line number Diff line Loading @@ -147,6 +147,7 @@ public class SpannableHelper { linkify(context, content, urlDetails); linkifyURL(context, content, urlDetails); emails(context, content); gemini(context, content); replaceQuoteSpans(context, content); } else { content = new SpannableStringBuilder(text); Loading Loading @@ -668,6 +669,38 @@ public class SpannableHelper { } } private static void gemini(Context context, Spannable content) { // --- For all patterns defined in Helper class --- Pattern pattern = Helper.geminiPattern; Matcher matcher = pattern.matcher(content); while (matcher.find()) { int matchStart = matcher.start(); int matchEnd = matcher.end(); String geminiLink = content.toString().substring(matchStart, matchEnd); if (matchStart >= 0 && matchEnd <= content.toString().length() && matchEnd >= matchStart) { ClickableSpan[] clickableSpans = content.getSpans(matchStart, matchEnd, ClickableSpan.class); if (clickableSpans != null) { for (ClickableSpan clickableSpan : clickableSpans) { content.removeSpan(clickableSpan); } } content.removeSpan(clickableSpans); content.setSpan(new ClickableSpan() { @Override public void onClick(@NonNull View textView) { Helper.openBrowser(context, geminiLink); } @Override public void updateDrawState(@NonNull TextPaint ds) { super.updateDrawState(ds); ds.setUnderlineText(false); ds.setColor(linkColor); } }, matchStart, matchEnd, Spanned.SPAN_INCLUSIVE_EXCLUSIVE); } } } private static void emails(Context context, Spannable content) { // --- For all patterns defined in Helper class --- Loading