FairEmail/app/src/main/java/eu/faircode/email/FragmentDialogOpenLink.java

559 lines
23 KiB
Java
Raw Normal View History

2021-04-04 10:55:47 +00:00
package eu.faircode.email;
/*
This file is part of FairEmail.
FairEmail is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
FairEmail is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with FairEmail. If not, see <http://www.gnu.org/licenses/>.
2022-01-01 08:46:36 +00:00
Copyright 2018-2022 by Marcel Bokhorst (M66B)
2021-04-04 10:55:47 +00:00
*/
import android.app.Dialog;
2021-06-09 15:28:11 +00:00
import android.content.ActivityNotFoundException;
2021-04-04 10:55:47 +00:00
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
2021-07-28 14:48:07 +00:00
import android.graphics.Paint;
2021-04-04 10:55:47 +00:00
import android.graphics.Typeface;
import android.net.Uri;
2021-08-10 15:46:29 +00:00
import android.os.Build;
2021-04-04 10:55:47 +00:00
import android.os.Bundle;
2021-08-10 15:46:29 +00:00
import android.provider.Settings;
2021-04-04 10:55:47 +00:00
import android.text.Editable;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
2021-04-04 10:55:47 +00:00
import android.text.TextUtils;
import android.text.TextWatcher;
import android.text.method.LinkMovementMethod;
import android.text.style.ForegroundColorSpan;
2021-08-09 15:09:54 +00:00
import android.text.style.StyleSpan;
2021-04-04 10:55:47 +00:00
import android.util.Pair;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.inputmethod.EditorInfo;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.constraintlayout.widget.Group;
import androidx.core.net.MailTo;
2021-04-04 10:55:47 +00:00
import androidx.core.util.PatternsCompat;
2021-09-28 19:15:46 +00:00
import androidx.lifecycle.Lifecycle;
2021-08-09 14:48:15 +00:00
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
2021-04-04 10:55:47 +00:00
import androidx.preference.PreferenceManager;
import java.net.IDN;
2021-07-03 18:36:38 +00:00
import java.net.InetAddress;
2021-04-04 10:55:47 +00:00
import java.util.List;
2021-07-02 17:54:04 +00:00
import java.util.regex.Matcher;
import java.util.regex.Pattern;
2021-04-04 10:55:47 +00:00
public class FragmentDialogOpenLink extends FragmentDialogBase {
2021-07-04 06:29:51 +00:00
private ImageButton ibMore;
private TextView tvMore;
private Button btnOwner;
private ContentLoadingProgressBar pbWait;
private TextView tvOwnerRemark;
private TextView tvHost;
private TextView tvOwner;
private Group grpOwner;
private Button btnSettings;
2021-08-10 15:46:29 +00:00
private Button btnDefault;
2021-07-28 14:48:07 +00:00
private TextView tvReset;
2021-07-04 06:29:51 +00:00
2021-04-04 10:55:47 +00:00
@NonNull
@Override
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
2021-08-10 14:27:16 +00:00
Uri _uri = getArguments().getParcelable("uri");
2021-04-04 10:55:47 +00:00
String _title = getArguments().getString("title");
if (_title != null)
_title = _title.replace("\uFFFC", ""); // Object replacement character
if (TextUtils.isEmpty(_title))
_title = null;
final String title = _title;
2021-04-05 13:43:30 +00:00
final Context context = getContext();
final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
boolean check_links_dbl = prefs.getBoolean("check_links_dbl", BuildConfig.PLAY_STORE_RELEASE);
boolean disconnect_links = prefs.getBoolean("disconnect_links", true);
2021-04-05 13:43:30 +00:00
2021-04-04 10:55:47 +00:00
// Preload web view
2021-04-05 13:43:30 +00:00
Helper.customTabsWarmup(context);
2021-04-04 10:55:47 +00:00
2021-09-02 18:28:27 +00:00
final Uri uri = UriHelper.guessScheme(_uri);
2021-08-10 14:27:16 +00:00
2021-04-04 10:55:47 +00:00
// Process link
final Uri sanitized;
if (uri.isOpaque())
sanitized = uri;
else {
2021-09-12 11:18:16 +00:00
Uri s = UriHelper.sanitize(uri);
2021-04-04 10:55:47 +00:00
sanitized = (s == null ? uri : s);
}
// Process title
final Uri uriTitle;
if (title != null && PatternsCompat.WEB_URL.matcher(title).matches()) {
String t = title.replaceAll("\\s+", "");
Uri u = Uri.parse(title.contains("://") ? t : "http://" + t);
String host = u.getHost(); // Capture1.PNG
uriTitle = (UriHelper.hasParentDomain(context, host) ? u : null);
} else
2021-04-04 10:55:47 +00:00
uriTitle = null;
// Get views
2021-04-05 13:43:30 +00:00
final View dview = LayoutInflater.from(context).inflate(R.layout.dialog_open_link, null);
2021-06-12 18:29:57 +00:00
final ImageButton ibInfo = dview.findViewById(R.id.ibInfo);
2021-04-04 10:55:47 +00:00
final TextView tvTitle = dview.findViewById(R.id.tvTitle);
final ImageButton ibDifferent = dview.findViewById(R.id.ibDifferent);
final EditText etLink = dview.findViewById(R.id.etLink);
2021-04-04 13:33:09 +00:00
final TextView tvLink = dview.findViewById(R.id.tvLink);
2021-08-09 14:48:15 +00:00
final ImageButton ibSearch = dview.findViewById(R.id.ibSearch);
final ImageButton ibShare = dview.findViewById(R.id.ibShare);
final ImageButton ibCopy = dview.findViewById(R.id.ibCopy);
2021-04-04 11:40:23 +00:00
final TextView tvSuspicious = dview.findViewById(R.id.tvSuspicious);
2021-04-04 10:55:47 +00:00
final TextView tvDisconnect = dview.findViewById(R.id.tvDisconnect);
final TextView tvDisconnectCategories = dview.findViewById(R.id.tvDisconnectCategories);
final CheckBox cbSecure = dview.findViewById(R.id.cbSecure);
final CheckBox cbSanitize = dview.findViewById(R.id.cbSanitize);
final CheckBox cbNotAgain = dview.findViewById(R.id.cbNotAgain);
2021-07-04 06:29:51 +00:00
ibMore = dview.findViewById(R.id.ibMore);
tvMore = dview.findViewById(R.id.tvMore);
btnOwner = dview.findViewById(R.id.btnOwner);
pbWait = dview.findViewById(R.id.pbWait);
tvOwnerRemark = dview.findViewById(R.id.tvOwnerRemark);
tvHost = dview.findViewById(R.id.tvHost);
tvOwner = dview.findViewById(R.id.tvOwner);
grpOwner = dview.findViewById(R.id.grpOwner);
btnSettings = dview.findViewById(R.id.btnSettings);
2021-08-10 15:46:29 +00:00
btnDefault = dview.findViewById(R.id.btnDefault);
2021-07-28 14:48:07 +00:00
tvReset = dview.findViewById(R.id.tvReset);
2021-07-04 06:29:51 +00:00
2021-04-04 10:55:47 +00:00
final Group grpDifferent = dview.findViewById(R.id.grpDifferent);
2021-07-04 06:29:51 +00:00
// Wire
2021-04-04 10:55:47 +00:00
2021-06-12 18:29:57 +00:00
ibInfo.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Helper.viewFAQ(v.getContext(), 35);
}
});
2021-04-04 10:55:47 +00:00
ibDifferent.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
etLink.setText(format(uriTitle, context));
2021-04-04 10:55:47 +00:00
}
});
etLink.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
@Override
public void onTextChanged(CharSequence text, int i, int i1, int i2) {
}
@Override
public void afterTextChanged(Editable editable) {
Uri uri = Uri.parse(editable.toString());
2021-09-12 11:18:16 +00:00
boolean secure = UriHelper.isSecure(uri);
boolean hyperlink = UriHelper.isHyperLink(uri);
2021-04-04 10:55:47 +00:00
cbSecure.setTag(secure);
cbSecure.setChecked(secure);
cbSecure.setText(
secure ? R.string.title_link_https : R.string.title_link_http);
cbSecure.setTextColor(Helper.resolveColor(context,
secure ? android.R.attr.textColorSecondary : R.attr.colorWarning));
cbSecure.setTypeface(
secure ? Typeface.DEFAULT : Typeface.DEFAULT_BOLD);
cbSecure.setVisibility(hyperlink ? View.VISIBLE : View.GONE);
}
});
etLink.setHorizontallyScrolling(false);
etLink.setMaxLines(10);
etLink.setOnEditorActionListener(new TextView.OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (actionId == EditorInfo.IME_ACTION_DONE) {
((AlertDialog) getDialog()).getButton(DialogInterface.BUTTON_POSITIVE).performClick();
return true;
} else
return false;
}
});
2021-08-09 14:48:15 +00:00
MailTo mailto = null;
if ("mailto".equals(uri.getScheme()))
try {
mailto = MailTo.parse(uri);
} catch (Throwable ex) {
Log.w(ex);
}
ibSearch.setVisibility(
mailto != null && !TextUtils.isEmpty(mailto.getTo())
? View.VISIBLE : View.GONE);
ibSearch.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
dismiss();
LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(context);
lbm.sendBroadcast(
new Intent(ActivityView.ACTION_SEARCH_ADDRESS)
.putExtra("account", -1L)
.putExtra("folder", -1L)
.putExtra("query", MailTo.parse(uri).getTo()));
}
});
2021-04-04 10:55:47 +00:00
ibShare.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent send = new Intent();
send.setAction(Intent.ACTION_SEND);
send.putExtra(Intent.EXTRA_TEXT, etLink.getText().toString());
send.setType("text/plain");
startActivity(Intent.createChooser(send, title));
}
});
ibCopy.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
ClipboardManager clipboard =
(ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
2021-04-07 16:26:07 +00:00
if (clipboard == null)
return;
ClipData clip = ClipData.newPlainText(title, etLink.getText().toString());
clipboard.setPrimaryClip(clip);
2021-04-04 10:55:47 +00:00
2021-04-07 16:26:07 +00:00
ToastEx.makeText(context, R.string.title_clipboard_copied, Toast.LENGTH_LONG).show();
2021-04-04 10:55:47 +00:00
}
});
cbSecure.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean checked) {
boolean tag = (Boolean) compoundButton.getTag();
if (tag == checked)
return;
Uri uri = Uri.parse(etLink.getText().toString());
2021-09-12 11:18:16 +00:00
etLink.setText(format(UriHelper.secure(uri, checked), context));
2021-04-04 10:55:47 +00:00
}
});
cbSanitize.setVisibility(uri.equals(sanitized) ? View.GONE : View.VISIBLE);
cbSanitize.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean checked) {
Uri link = (checked ? sanitized : uri);
2021-09-12 11:18:16 +00:00
boolean secure = UriHelper.isSecure(link);
cbSecure.setTag(secure);
cbSecure.setChecked(secure);
2021-09-12 11:18:16 +00:00
etLink.setText(format(UriHelper.secure(link, secure), context));
2021-04-04 10:55:47 +00:00
}
});
cbNotAgain.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
prefs.edit().putBoolean(uri.getHost() + ".confirm_link", !isChecked).apply();
}
});
2021-07-04 06:29:51 +00:00
View.OnClickListener onMore = new View.OnClickListener() {
2021-06-23 10:13:59 +00:00
@Override
public void onClick(View v) {
2021-07-04 06:29:51 +00:00
setMore(btnOwner.getVisibility() == View.GONE);
2021-06-23 10:13:59 +00:00
}
2021-07-04 06:29:51 +00:00
};
2021-06-23 10:13:59 +00:00
2021-07-04 06:29:51 +00:00
ibMore.setOnClickListener(onMore);
tvMore.setOnClickListener(onMore);
2021-04-04 10:55:47 +00:00
btnOwner.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Bundle args = new Bundle();
args.putParcelable("uri", uri);
2021-07-03 18:36:38 +00:00
new SimpleTask<Pair<InetAddress, IPInfo.Organization>>() {
2021-04-04 10:55:47 +00:00
@Override
protected void onPreExecute(Bundle args) {
2021-07-04 06:29:51 +00:00
ibMore.setEnabled(false);
tvMore.setEnabled(false);
2021-04-04 10:55:47 +00:00
btnOwner.setEnabled(false);
pbWait.setVisibility(View.VISIBLE);
grpOwner.setVisibility(View.GONE);
}
@Override
protected void onPostExecute(Bundle args) {
2021-07-04 06:29:51 +00:00
ibMore.setEnabled(true);
tvMore.setEnabled(true);
2021-04-04 10:55:47 +00:00
btnOwner.setEnabled(true);
pbWait.setVisibility(View.GONE);
grpOwner.setVisibility(View.VISIBLE);
}
@Override
2021-07-03 18:36:38 +00:00
protected Pair<InetAddress, IPInfo.Organization> onExecute(Context context, Bundle args) throws Throwable {
2021-04-04 10:55:47 +00:00
Uri uri = args.getParcelable("uri");
return IPInfo.getOrganization(uri, context);
}
@Override
2021-07-03 18:36:38 +00:00
protected void onExecuted(Bundle args, Pair<InetAddress, IPInfo.Organization> data) {
tvHost.setText(data.first.toString());
2021-04-04 10:55:47 +00:00
tvOwner.setText(data.second.name == null ? "?" : data.second.name);
ApplicationEx.getMainHandler().post(new Runnable() {
@Override
public void run() {
2021-09-28 19:15:46 +00:00
if (!getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.STARTED))
return;
2021-04-04 10:55:47 +00:00
dview.scrollTo(0, tvOwner.getBottom());
}
});
}
@Override
protected void onException(Bundle args, Throwable ex) {
tvHost.setText(ex.getClass().getName());
tvOwner.setText(ex.getMessage());
}
}.execute(FragmentDialogOpenLink.this, args, "link:owner");
}
});
2021-07-04 06:29:51 +00:00
tvOwnerRemark.setMovementMethod(LinkMovementMethod.getInstance());
btnSettings.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
2021-08-13 14:39:44 +00:00
v.getContext().startActivity(new Intent(v.getContext(), ActivitySetup.class)
2021-09-27 16:57:39 +00:00
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK)
2021-08-13 14:39:44 +00:00
.putExtra("tab", "privacy"));
2021-07-04 06:29:51 +00:00
}
});
2021-08-10 15:46:29 +00:00
final Intent manage = new Intent(Settings.ACTION_MANAGE_DEFAULT_APPS_SETTINGS);
btnDefault.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
v.getContext().startActivity(manage);
}
});
2021-07-28 14:48:07 +00:00
tvReset.setPaintFlags(tvReset.getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG);
tvReset.setOnClickListener(new View.OnClickListener() {
@Override
2021-10-27 12:44:21 +00:00
public void onClick(View c) {
Helper.view(c.getContext(), Uri.parse(Helper.URI_SUPPORT_RESET_OPEN), true);
2021-07-28 14:48:07 +00:00
}
});
2021-07-04 06:29:51 +00:00
// Initialize
2021-04-04 10:55:47 +00:00
tvTitle.setText(title);
tvTitle.setVisibility(TextUtils.isEmpty(title) ? View.GONE : View.VISIBLE);
String host = uri.getHost();
String thost = (uriTitle == null ? null : uriTitle.getHost());
2021-04-04 11:45:32 +00:00
String puny = null;
2021-04-04 10:55:47 +00:00
try {
2021-04-04 11:45:32 +00:00
if (host != null)
puny = IDN.toASCII(host, IDN.ALLOW_UNASSIGNED);
2021-04-04 10:55:47 +00:00
} catch (Throwable ex) {
2021-04-06 15:33:51 +00:00
Log.i(ex);
2021-04-04 10:55:47 +00:00
puny = host;
}
if (host != null && !host.equals(puny)) {
etLink.setText(format(uri.buildUpon().encodedAuthority(puny).build(), context));
2021-04-04 13:33:09 +00:00
tvLink.setText(uri.toString());
2021-12-29 08:01:14 +00:00
tvSuspicious.setVisibility(View.GONE);
2021-04-04 10:55:47 +00:00
} else {
etLink.setText(format(uri, context));
2021-04-04 13:33:09 +00:00
tvLink.setText(null);
2021-04-04 11:45:32 +00:00
tvSuspicious.setVisibility(Helper.isSingleScript(host) ? View.GONE : View.VISIBLE);
2021-04-04 10:55:47 +00:00
}
if (check_links_dbl &&
2021-08-07 11:51:51 +00:00
tvSuspicious.getVisibility() != View.VISIBLE) {
Bundle args = new Bundle();
2021-08-08 10:57:55 +00:00
args.putParcelable("uri", uri);
2021-08-07 11:51:51 +00:00
new SimpleTask<Boolean>() {
@Override
protected Boolean onExecute(Context context, Bundle args) throws Throwable {
2021-08-08 10:57:55 +00:00
Uri uri = args.getParcelable("uri");
return DnsBlockList.isJunk(context, uri);
2021-08-07 11:51:51 +00:00
}
@Override
protected void onExecuted(Bundle args, Boolean blocklist) {
if (blocklist != null && blocklist)
tvSuspicious.setVisibility(View.VISIBLE);
}
@Override
protected void onException(Bundle args, Throwable ex) {
// Ignored
}
}.execute(this, args, "link:blocklist");
}
2021-04-04 11:40:23 +00:00
grpDifferent.setVisibility(
host == null || thost == null || host.equalsIgnoreCase(thost)
? View.GONE : View.VISIBLE);
2021-04-04 10:55:47 +00:00
List<String> categories = null;
if (disconnect_links)
categories = DisconnectBlacklist.getCategories(uri.getHost());
if (categories != null)
tvDisconnectCategories.setText(TextUtils.join(", ", categories));
2021-07-04 06:29:51 +00:00
tvDisconnect.setVisibility(
categories == null ? View.GONE : View.VISIBLE);
tvDisconnectCategories.setVisibility(
categories == null || !BuildConfig.DEBUG ? View.GONE : View.VISIBLE);
cbNotAgain.setText(context.getString(R.string.title_no_ask_for_again, uri.getHost()));
cbNotAgain.setVisibility(
"https".equals(uri.getScheme()) && !TextUtils.isEmpty(uri.getHost())
? View.VISIBLE : View.GONE);
setMore(false);
2021-04-04 10:55:47 +00:00
return new AlertDialog.Builder(context)
.setView(dview)
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Uri uri = Uri.parse(etLink.getText().toString());
Helper.view(context, uri, false);
}
})
.setNeutralButton(R.string.title_browse, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
2021-06-09 15:28:11 +00:00
// https://developer.android.com/training/basics/intents/sending#AppChooser
2021-04-04 10:55:47 +00:00
Uri uri = Uri.parse(etLink.getText().toString());
2021-06-09 15:28:11 +00:00
Intent view = new Intent(Intent.ACTION_VIEW, uri);
Intent chooser = Intent.createChooser(view, context.getString(R.string.title_select_app));
try {
startActivity(chooser);
} catch (ActivityNotFoundException ex) {
Log.w(ex);
Helper.view(context, uri, true, true);
}
2021-04-04 10:55:47 +00:00
}
})
.setNegativeButton(android.R.string.cancel, null)
.create();
}
2021-07-04 06:29:51 +00:00
private void setMore(boolean show) {
2021-08-10 15:46:29 +00:00
boolean n = (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N);
2021-07-04 06:29:51 +00:00
ibMore.setImageLevel(show ? 0 : 1);
btnOwner.setVisibility(show ? View.VISIBLE : View.GONE);
pbWait.setVisibility(View.GONE);
tvOwnerRemark.setVisibility(show ? View.VISIBLE : View.GONE);
grpOwner.setVisibility(View.GONE);
btnSettings.setVisibility(show ? View.VISIBLE : View.GONE);
2021-08-10 15:46:29 +00:00
btnDefault.setVisibility(show && n ? View.VISIBLE : View.GONE);
2021-07-28 14:48:07 +00:00
tvReset.setVisibility(show ? View.VISIBLE : View.GONE);
2021-07-04 06:29:51 +00:00
}
private Spanned format(Uri uri, Context context) {
2021-07-04 18:41:13 +00:00
String scheme = uri.getScheme();
String host = uri.getHost();
String text = uri.toString();
2021-09-09 10:52:10 +00:00
SpannableStringBuilder ssb = new SpannableStringBuilderEx(text);
try {
2021-07-02 17:54:04 +00:00
int textColorLink = Helper.resolveColor(context, android.R.attr.textColorLink);
2021-08-10 05:00:41 +00:00
int textColorSecondary = Helper.resolveColor(context, android.R.attr.textColorSecondary);
2021-08-09 15:09:54 +00:00
int colorWarning = Helper.resolveColor(context, R.attr.colorWarning);
2021-07-04 18:41:13 +00:00
if ("tel".equals(scheme)) {
// tel://+123%2045%20678%123456
host = Uri.decode(host);
text = "tel://" + host;
} else if ("mailto".equals(scheme)) {
2021-07-07 04:59:47 +00:00
if (host == null) {
2021-08-09 14:48:15 +00:00
MailTo email = MailTo.parse(uri);
2021-07-04 18:41:13 +00:00
host = UriHelper.getEmailDomain(email.getTo());
}
}
2021-08-09 15:09:54 +00:00
if (scheme != null) {
int index = text.indexOf(scheme);
if (index >= 0)
if ("http".equals(scheme)) {
ssb.setSpan(new ForegroundColorSpan(colorWarning),
index, index + scheme.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
ssb.setSpan(new StyleSpan(Typeface.BOLD),
index, index + scheme.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
} else
2021-08-10 05:00:41 +00:00
ssb.setSpan(new ForegroundColorSpan(textColorSecondary),
2021-08-09 15:09:54 +00:00
index, index + scheme.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
if (host != null) {
int index = text.indexOf(host);
if (index >= 0)
ssb.setSpan(new ForegroundColorSpan(textColorLink),
index, index + host.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
2021-07-02 17:54:04 +00:00
if (uri.isHierarchical())
for (String name : uri.getQueryParameterNames()) {
Pattern pattern = Pattern.compile("[?&]" + Pattern.quote(name) + "=");
Matcher matcher = pattern.matcher(text);
while (matcher.find()) {
ssb.setSpan(new ForegroundColorSpan(textColorLink),
matcher.start() + 1, matcher.end() - 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
2021-07-02 17:54:04 +00:00
}
} catch (Throwable ex) {
Log.e(ex);
}
return ssb;
}
2021-04-04 10:55:47 +00:00
}