mirror of https://github.com/tasks/tasks
Convert Linkify to Kotlin
parent
a011ec5edf
commit
9960e9a0a9
@ -1,136 +0,0 @@
|
|||||||
package org.tasks.dialogs;
|
|
||||||
|
|
||||||
import static java.util.Arrays.asList;
|
|
||||||
import static org.tasks.Strings.isNullOrEmpty;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.net.Uri;
|
|
||||||
import android.text.Spannable;
|
|
||||||
import android.text.SpannableString;
|
|
||||||
import android.text.SpannableStringBuilder;
|
|
||||||
import android.text.style.URLSpan;
|
|
||||||
import android.view.View;
|
|
||||||
import android.widget.TextView;
|
|
||||||
import androidx.core.text.util.LinkifyCompat;
|
|
||||||
import dagger.hilt.android.qualifiers.ActivityContext;
|
|
||||||
import java.io.UnsupportedEncodingException;
|
|
||||||
import java.net.URLDecoder;
|
|
||||||
import javax.inject.Inject;
|
|
||||||
import org.tasks.R;
|
|
||||||
import timber.log.Timber;
|
|
||||||
|
|
||||||
public class Linkify {
|
|
||||||
|
|
||||||
private final Context context;
|
|
||||||
private final DialogBuilder dialogBuilder;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
public Linkify(@ActivityContext Context context, DialogBuilder dialogBuilder) {
|
|
||||||
this.context = context;
|
|
||||||
this.dialogBuilder = dialogBuilder;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void safeLinkify(TextView textView, int mask) {
|
|
||||||
try {
|
|
||||||
LinkifyCompat.addLinks(textView, mask);
|
|
||||||
} catch (UnsatisfiedLinkError e) {
|
|
||||||
Timber.e(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void linkify(TextView textView) {
|
|
||||||
linkify(textView, () -> {});
|
|
||||||
}
|
|
||||||
|
|
||||||
public void linkify(TextView textView, Runnable onClick) {
|
|
||||||
if (textView.length() == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
safeLinkify(textView, android.text.util.Linkify.ALL);
|
|
||||||
|
|
||||||
textView.setOnClickListener(
|
|
||||||
v -> {
|
|
||||||
if (textView.getSelectionStart() == -1 && textView.getSelectionEnd() == -1) {
|
|
||||||
onClick.run();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
URLSpan[] spans;
|
|
||||||
Spannable spannable;
|
|
||||||
CharSequence text = textView.getText();
|
|
||||||
if (text instanceof SpannableStringBuilder || text instanceof SpannableString) {
|
|
||||||
spannable = (Spannable) text;
|
|
||||||
} else {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
spans = spannable.getSpans(0, text.length(), URLSpan.class);
|
|
||||||
for (URLSpan span : spans) {
|
|
||||||
int start = spannable.getSpanStart(span);
|
|
||||||
int end = spannable.getSpanEnd(span);
|
|
||||||
|
|
||||||
spannable.removeSpan(span);
|
|
||||||
spannable.setSpan(new ClickHandlingURLSpan(span.getURL(), onClick), start, end, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private class ClickHandlingURLSpan extends URLSpan {
|
|
||||||
|
|
||||||
private final Runnable onEdit;
|
|
||||||
|
|
||||||
ClickHandlingURLSpan(String url, Runnable onEdit) {
|
|
||||||
super(url);
|
|
||||||
this.onEdit = onEdit;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onClick(View widget) {
|
|
||||||
String title;
|
|
||||||
String edit = context.getString(R.string.TAd_actionEditTask);
|
|
||||||
String action;
|
|
||||||
String url = getURL();
|
|
||||||
Uri uri = Uri.parse(url);
|
|
||||||
String scheme = uri.getScheme();
|
|
||||||
if (isNullOrEmpty(scheme)) {
|
|
||||||
scheme = "";
|
|
||||||
}
|
|
||||||
switch (scheme) {
|
|
||||||
case "tel":
|
|
||||||
title = uri.getEncodedSchemeSpecificPart();
|
|
||||||
action = context.getString(R.string.action_call);
|
|
||||||
break;
|
|
||||||
case "mailto":
|
|
||||||
title = uri.getEncodedSchemeSpecificPart();
|
|
||||||
action = context.getString(R.string.action_open);
|
|
||||||
break;
|
|
||||||
case "geo":
|
|
||||||
title = uri.getEncodedQuery().replaceFirst("q=", "");
|
|
||||||
try {
|
|
||||||
title = URLDecoder.decode(title, "utf-8");
|
|
||||||
} catch (UnsupportedEncodingException ignored) {
|
|
||||||
}
|
|
||||||
action = context.getString(R.string.action_open);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
title = url;
|
|
||||||
action = context.getString(R.string.action_open);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
dialogBuilder
|
|
||||||
.newDialog(title)
|
|
||||||
.setItems(
|
|
||||||
asList(action, edit),
|
|
||||||
(dialogInterface, selected) -> {
|
|
||||||
if (selected == 0) {
|
|
||||||
Intent intent = new Intent(Intent.ACTION_VIEW);
|
|
||||||
intent.setData(uri);
|
|
||||||
context.startActivity(intent);
|
|
||||||
} else {
|
|
||||||
onEdit.run();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.show();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -0,0 +1,106 @@
|
|||||||
|
package org.tasks.dialogs
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import android.net.Uri
|
||||||
|
import android.text.Spannable
|
||||||
|
import android.text.SpannableString
|
||||||
|
import android.text.SpannableStringBuilder
|
||||||
|
import android.text.style.URLSpan
|
||||||
|
import android.text.util.Linkify
|
||||||
|
import android.view.View
|
||||||
|
import android.widget.TextView
|
||||||
|
import androidx.core.text.util.LinkifyCompat
|
||||||
|
import dagger.hilt.android.qualifiers.ActivityContext
|
||||||
|
import org.tasks.R
|
||||||
|
import org.tasks.Strings.isNullOrEmpty
|
||||||
|
import timber.log.Timber
|
||||||
|
import java.io.UnsupportedEncodingException
|
||||||
|
import java.net.URLDecoder
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
class Linkify @Inject constructor(
|
||||||
|
@ActivityContext private val context: Context,
|
||||||
|
private val dialogBuilder: DialogBuilder
|
||||||
|
) {
|
||||||
|
fun linkify(textView: TextView, onClick: Runnable = Runnable {}) {
|
||||||
|
if (textView.length() == 0) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
safeLinkify(textView, Linkify.ALL)
|
||||||
|
textView.setOnClickListener {
|
||||||
|
if (textView.selectionStart == -1 && textView.selectionEnd == -1) {
|
||||||
|
onClick.run()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val text = textView.text
|
||||||
|
if (text is SpannableStringBuilder || text is SpannableString) {
|
||||||
|
val spannable = text as Spannable
|
||||||
|
val spans = spannable.getSpans(0, text.length, URLSpan::class.java)
|
||||||
|
for (span in spans) {
|
||||||
|
val start = spannable.getSpanStart(span)
|
||||||
|
val end = spannable.getSpanEnd(span)
|
||||||
|
spannable.removeSpan(span)
|
||||||
|
spannable.setSpan(ClickHandlingURLSpan(span.url, onClick), start, end, 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private inner class ClickHandlingURLSpan constructor(
|
||||||
|
url: String?,
|
||||||
|
private val onEdit: Runnable
|
||||||
|
) : URLSpan(url) {
|
||||||
|
override fun onClick(widget: View) {
|
||||||
|
var title: String?
|
||||||
|
val edit = context.getString(R.string.TAd_actionEditTask)
|
||||||
|
val action: String
|
||||||
|
val uri = Uri.parse(url)
|
||||||
|
var scheme = uri.scheme
|
||||||
|
if (isNullOrEmpty(scheme)) {
|
||||||
|
scheme = ""
|
||||||
|
}
|
||||||
|
when (scheme) {
|
||||||
|
"tel" -> {
|
||||||
|
title = uri.encodedSchemeSpecificPart
|
||||||
|
action = context.getString(R.string.action_call)
|
||||||
|
}
|
||||||
|
"mailto" -> {
|
||||||
|
title = uri.encodedSchemeSpecificPart
|
||||||
|
action = context.getString(R.string.action_open)
|
||||||
|
}
|
||||||
|
"geo" -> {
|
||||||
|
title = uri.encodedQuery!!.replaceFirst("q=".toRegex(), "")
|
||||||
|
try {
|
||||||
|
title = URLDecoder.decode(title, "utf-8")
|
||||||
|
} catch (ignored: UnsupportedEncodingException) {
|
||||||
|
}
|
||||||
|
action = context.getString(R.string.action_open)
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
title = url
|
||||||
|
action = context.getString(R.string.action_open)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dialogBuilder
|
||||||
|
.newDialog(title)
|
||||||
|
.setItems(listOf(action, edit)) { _, selected ->
|
||||||
|
if (selected == 0) {
|
||||||
|
context.startActivity(Intent(Intent.ACTION_VIEW, uri))
|
||||||
|
} else {
|
||||||
|
onEdit.run()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun safeLinkify(textView: TextView?, mask: Int) {
|
||||||
|
try {
|
||||||
|
LinkifyCompat.addLinks(textView!!, mask)
|
||||||
|
} catch (e: UnsatisfiedLinkError) {
|
||||||
|
Timber.e(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue