diff --git a/app/src/dummy/java/eu/faircode/email/Avatar.java b/app/src/dummy/java/eu/faircode/email/Avatar.java index 33a13855fa..0f55755fdd 100644 --- a/app/src/dummy/java/eu/faircode/email/Avatar.java +++ b/app/src/dummy/java/eu/faircode/email/Avatar.java @@ -26,6 +26,8 @@ import java.util.concurrent.Callable; public class Avatar { static final String GRAVATAR_PRIVACY_URI = ""; static final String LIBRAVATAR_PRIVACY_URI = ""; + static final String DDG_URI = ""; + static final String DDG_PRIVACY_URI = ""; static Callable getGravatar(String email, int scaleToPixels, Context context) { return new Callable() { diff --git a/app/src/extra/java/eu/faircode/email/Avatar.java b/app/src/extra/java/eu/faircode/email/Avatar.java index df44f154a1..babc5dab85 100644 --- a/app/src/extra/java/eu/faircode/email/Avatar.java +++ b/app/src/extra/java/eu/faircode/email/Avatar.java @@ -31,6 +31,8 @@ import javax.net.ssl.HttpsURLConnection; public class Avatar { static final String GRAVATAR_PRIVACY_URI = "https://automattic.com/privacy/"; static final String LIBRAVATAR_PRIVACY_URI = "https://www.libravatar.org/privacy/"; + static final String DDG_URI = "https://icons.duckduckgo.com/ip3/"; + static final String DDG_PRIVACY_URI = "https://duckduckgo.com/privacy"; private static final String GRAVATAR_URI = "https://www.gravatar.com/avatar/"; private static final int GRAVATAR_CONNECT_TIMEOUT = 5 * 1000; // milliseconds diff --git a/app/src/main/java/eu/faircode/email/ContactInfo.java b/app/src/main/java/eu/faircode/email/ContactInfo.java index f048f2eb6c..b3ec1eb6c9 100644 --- a/app/src/main/java/eu/faircode/email/ContactInfo.java +++ b/app/src/main/java/eu/faircode/email/ContactInfo.java @@ -285,6 +285,7 @@ public class ContactInfo { boolean gravatars = (prefs.getBoolean("gravatars", false) && (!favicons_dmarc || dmarc) && !BuildConfig.PLAY_STORE_RELEASE); boolean libravatars = (prefs.getBoolean("libravatars", false) && (!favicons_dmarc || dmarc) && !BuildConfig.PLAY_STORE_RELEASE); boolean favicons = (prefs.getBoolean("favicons", false) && (!favicons_dmarc || dmarc)); + boolean ddg_icons = (prefs.getBoolean("ddg_icons", false) && (!favicons_dmarc || dmarc) && !BuildConfig.PLAY_STORE_RELEASE); boolean generated = prefs.getBoolean("generated_icons", true); boolean identicons = prefs.getBoolean("identicons", false); boolean circular = prefs.getBoolean("circular", true); @@ -475,6 +476,18 @@ public class ContactInfo { } } + if (ddg_icons && !TextUtils.isEmpty(Avatar.DDG_URI)) + futures.add(Helper.getDownloadTaskExecutor().submit(new Callable() { + @Override + public Favicon call() throws Exception { + String parent = UriHelper.getRootDomain(context, domain); + String uri = Avatar.DDG_URI + Uri.encode(parent) + ".ico"; + Favicon ddg = getFavicon(new URL(uri), null, scaleToPixels, context); + ddg.type = "ddg"; + return ddg; + } + })); + Throwable ex = null; for (Future future : futures) try { diff --git a/app/src/main/java/eu/faircode/email/FragmentOptionsDisplay.java b/app/src/main/java/eu/faircode/email/FragmentOptionsDisplay.java index 2c27d031e8..6df22d5015 100644 --- a/app/src/main/java/eu/faircode/email/FragmentOptionsDisplay.java +++ b/app/src/main/java/eu/faircode/email/FragmentOptionsDisplay.java @@ -124,9 +124,11 @@ public class FragmentOptionsDisplay extends FragmentBase implements SharedPrefer private SwitchCompat swLibravatars; private TextView tvLibravatarPrivacy; private SwitchCompat swFavicons; + private TextView tvFaviconsHint; private SwitchCompat swFaviconsPartial; private SwitchCompat swFaviconsManifest; - private TextView tvFaviconsHint; + private SwitchCompat swDdg; + private TextView tvDdgPrivacy; private SwitchCompat swFaviconsDmarc; private SwitchCompat swGeneratedIcons; private SwitchCompat swIdenticons; @@ -218,7 +220,7 @@ public class FragmentOptionsDisplay extends FragmentBase implements SharedPrefer "hide_toolbar", "edge_to_edge", "nav_options", "nav_categories", "nav_last_sync", "nav_count", "nav_unseen_drafts", "nav_count_pinned", "show_unexposed", "threading", "threading_unread", "indentation", "seekbar", "actionbar", "actionbar_swap", "actionbar_color", "highlight_unread", "highlight_color", "color_stripe", "color_stripe_wide", - "avatars", "bimi", "bimi_vmc", "gravatars", "libravatars", "favicons", "favicons_partial", "favicons_manifest", "favicons_dmarc", "generated_icons", "identicons", + "avatars", "bimi", "bimi_vmc", "gravatars", "libravatars", "favicons", "favicons_partial", "favicons_manifest", "ddg_icons", "favicons_dmarc", "generated_icons", "identicons", "circular", "saturation", "brightness", "threshold", "email_format", "prefer_contact", "only_contact", "distinguish_contacts", "show_recipients", "reverse_addresses", "font_size_sender", "sender_ellipsize", @@ -304,9 +306,11 @@ public class FragmentOptionsDisplay extends FragmentBase implements SharedPrefer swLibravatars = view.findViewById(R.id.swLibravatars); tvLibravatarPrivacy = view.findViewById(R.id.tvLibravatarPrivacy); swFavicons = view.findViewById(R.id.swFavicons); + tvFaviconsHint = view.findViewById(R.id.tvFaviconsHint); swFaviconsPartial = view.findViewById(R.id.swFaviconsPartial); swFaviconsManifest = view.findViewById(R.id.swFaviconsManifest); - tvFaviconsHint = view.findViewById(R.id.tvFaviconsHint); + swDdg = view.findViewById(R.id.swDdg); + tvDdgPrivacy = view.findViewById(R.id.tvDdgPrivacy); swFaviconsDmarc = view.findViewById(R.id.swFaviconsDmarc); swGeneratedIcons = view.findViewById(R.id.swGeneratedIcons); swIdenticons = view.findViewById(R.id.swIdenticons); @@ -894,6 +898,14 @@ public class FragmentOptionsDisplay extends FragmentBase implements SharedPrefer } }); + tvFaviconsHint.getPaint().setUnderlineText(true); + tvFaviconsHint.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Helper.view(v.getContext(), Uri.parse(Helper.FAVICON_PRIVACY_URI), true); + } + }); + swFaviconsPartial.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton compoundButton, boolean checked) { @@ -910,11 +922,19 @@ public class FragmentOptionsDisplay extends FragmentBase implements SharedPrefer } }); - tvFaviconsHint.getPaint().setUnderlineText(true); - tvFaviconsHint.setOnClickListener(new View.OnClickListener() { + swDdg.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton compoundButton, boolean checked) { + prefs.edit().putBoolean("ddg_icons", checked).apply(); + ContactInfo.clearCache(compoundButton.getContext()); + } + }); + + tvDdgPrivacy.getPaint().setUnderlineText(true); + tvDdgPrivacy.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - Helper.view(v.getContext(), Uri.parse(Helper.FAVICON_PRIVACY_URI), true); + Helper.view(v.getContext(), Uri.parse(Avatar.DDG_PRIVACY_URI), true); } }); @@ -1625,6 +1645,7 @@ public class FragmentOptionsDisplay extends FragmentBase implements SharedPrefer swFaviconsPartial.setEnabled(swFavicons.isChecked()); swFaviconsManifest.setChecked(prefs.getBoolean("favicons_manifest", false)); swFaviconsManifest.setEnabled(swFavicons.isChecked()); + swDdg.setChecked(prefs.getBoolean("ddg_icons", false)); swFaviconsDmarc.setChecked(prefs.getBoolean("favicons_dmarc", false)); swGeneratedIcons.setChecked(prefs.getBoolean("generated_icons", true)); swIdenticons.setChecked(prefs.getBoolean("identicons", false)); diff --git a/app/src/main/res/layout/fragment_options_display.xml b/app/src/main/res/layout/fragment_options_display.xml index 9795fa3e74..06642c0ca4 100644 --- a/app/src/main/res/layout/fragment_options_display.xml +++ b/app/src/main/res/layout/fragment_options_display.xml @@ -1085,6 +1085,7 @@ app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/tvLibravatarsHint" /> + + + + + + + + swLibravatars,tvLibravatarsHint,tvLibravatarPrivacy, + swDdg,tvDdgHint,tvDdgPrivacy" /> diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 38f49e53c3..38a2385e6f 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -619,6 +619,7 @@ Show favicons Scan only the first %1$s of the web page Scan web app manifests + Show DuckDuckGo icons Require DMARC verification for external images Show generated icons Show identicons