Change summary
src/main/java/de/gultsch/common/MiniUri.java | 13 +
src/main/java/eu/siacs/conversations/ui/text/FixedURLSpan.java | 37 +++
2 files changed, 44 insertions(+), 6 deletions(-)
Detailed changes
@@ -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<String> 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<String, String> getParameter() {
return this.parameter;
}
@@ -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);