From 64be4b8385903bfc93d9588817396d759f64e6ef Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Thu, 3 Apr 2025 11:45:55 +0200 Subject: [PATCH] rewrite fedilinks to https when no app handles web+ap --- src/main/java/de/gultsch/common/MiniUri.java | 13 +++++++ .../conversations/ui/text/FixedURLSpan.java | 37 ++++++++++++++++--- 2 files changed, 44 insertions(+), 6 deletions(-) diff --git a/src/main/java/de/gultsch/common/MiniUri.java b/src/main/java/de/gultsch/common/MiniUri.java index 6ea24a90dd6d1dd497f03813e64cbc7dda7bf7e1..6c5e123bb649e221de68e2b06e72c7b49d414726 100644 --- a/src/main/java/de/gultsch/common/MiniUri.java +++ b/src/main/java/de/gultsch/common/MiniUri.java @@ -1,5 +1,6 @@ package de.gultsch.common; +import android.net.Uri; import com.google.common.base.MoreObjects; import com.google.common.base.Splitter; import com.google.common.base.Strings; @@ -7,6 +8,7 @@ import com.google.common.collect.ImmutableMap; import java.io.UnsupportedEncodingException; import java.net.URLDecoder; import java.util.Collections; +import java.util.List; import java.util.Locale; import java.util.Map; import org.checkerframework.checker.nullness.qual.NonNull; @@ -33,6 +35,7 @@ public class MiniUri { } this.scheme = schemeAndRest.get(0); final var rest = schemeAndRest.get(1); + // TODO add fragment parser final var authorityPathAndQuery = Splitter.on('?').limit(2).splitToList(rest); final var authorityPath = authorityPathAndQuery.get(0); System.out.println("authorityPath " + authorityPath); @@ -106,10 +109,20 @@ public class MiniUri { : '/' + this.path; } + public List getPathSegments() { + return Strings.isNullOrEmpty(this.path) + ? Collections.emptyList() + : Splitter.on('/').splitToList(this.path); + } + public String getRaw() { return this.raw; } + public Uri asUri() { + return Uri.parse(this.raw); + } + public Map getParameter() { return this.parameter; } diff --git a/src/main/java/eu/siacs/conversations/ui/text/FixedURLSpan.java b/src/main/java/eu/siacs/conversations/ui/text/FixedURLSpan.java index aba355214b764ab28db0d0ea641e68837717aee4..c76494736fccdfd8819b92acd4456d3bfca0dc1b 100644 --- a/src/main/java/eu/siacs/conversations/ui/text/FixedURLSpan.java +++ b/src/main/java/eu/siacs/conversations/ui/text/FixedURLSpan.java @@ -37,9 +37,13 @@ import android.net.Uri; import android.text.Editable; import android.text.Spanned; import android.text.style.URLSpan; +import android.util.Log; import android.view.SoundEffectConstants; import android.view.View; import android.widget.Toast; +import com.google.common.base.Joiner; +import de.gultsch.common.MiniUri; +import eu.siacs.conversations.Config; import eu.siacs.conversations.R; import eu.siacs.conversations.ui.ConversationsActivity; import eu.siacs.conversations.ui.ShowLocationActivity; @@ -67,26 +71,47 @@ public class FixedURLSpan extends URLSpan { @Override public void onClick(final View widget) { - final Uri uri = Uri.parse(getURL()); + final var uri = new MiniUri(getURL()); final Context context = widget.getContext(); final boolean candidateToProcessDirectly = "xmpp".equals(uri.getScheme()) || ("https".equals(uri.getScheme()) - && "conversations.im".equals(uri.getHost()) + && "conversations.im".equals(uri.getAuthority()) && uri.getPathSegments().size() > 1 && Arrays.asList("j", "i").contains(uri.getPathSegments().get(0))); - if (candidateToProcessDirectly && context instanceof ConversationsActivity) { - if (((ConversationsActivity) context).onXmppUriClicked(uri)) { + if (candidateToProcessDirectly + && context instanceof ConversationsActivity conversationsActivity) { + if (conversationsActivity.onXmppUriClicked(uri.asUri())) { + Log.d(Config.LOGTAG, "handled xmpp uri internally"); widget.playSoundEffect(SoundEffectConstants.CLICK); return; } } - final Intent intent = new Intent(Intent.ACTION_VIEW, uri); - if ("geo".equalsIgnoreCase(uri.getScheme())) { + final Intent intent = new Intent(Intent.ACTION_VIEW, uri.asUri()); + if ("web+ap".equals(uri.getScheme())) { + if (intent.resolveActivity(context.getPackageManager()) == null) { + Log.d(Config.LOGTAG, "no app found to handle web+ap"); + final var webApAsHttps = + Uri.parse( + String.format( + "https://%s/%s", + uri.getAuthority(), + Joiner.on('/').join(uri.getPathSegments()))); + final var viewHttpsIntent = new Intent(Intent.ACTION_VIEW, webApAsHttps); + startActivity(widget, viewHttpsIntent); + return; + } + } + if ("geo".equals(uri.getScheme())) { intent.setClass(context, ShowLocationActivity.class); } else { intent.setFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT); } + startActivity(widget, intent); + } + + private void startActivity(final View widget, final Intent intent) { + final var context = widget.getContext(); try { context.startActivity(intent); widget.playSoundEffect(SoundEffectConstants.CLICK);