From b48532f8bd184f3b7a3e2dbbf0b44f97814b451a Mon Sep 17 00:00:00 2001 From: M66B Date: Fri, 26 Apr 2024 10:54:47 +0200 Subject: [PATCH] Refactoring --- app/build.gradle | 5 + .../eu/faircode/email/FragmentAccounts.java | 71 +------- .../faircode/email/FragmentDialogPwned.java | 157 ++++++++++++++++++ app/src/main/res/layout/dialog_pwned.xml | 120 +++++++------ 4 files changed, 230 insertions(+), 123 deletions(-) create mode 100644 app/src/main/java/eu/faircode/email/FragmentDialogPwned.java diff --git a/app/build.gradle b/app/build.gradle index 47edf614a1..6634bfa838 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -216,6 +216,7 @@ android { buildConfigField "String", "GEMINI_ENDPOINT", "\"https://generativelanguage.googleapis.com/v1beta/\"" buildConfigField "String", "GEMINI_PRIVACY", "\"https://support.google.com/gemini/answer/13594961\"" buildConfigField "String", "PWNED_ENDPOINT", "\"https://api.pwnedpasswords.com/\"" + buildConfigField "String", "PWNED_PRIVACY", "\"https://haveibeenpwned.com/Privacy\"" buildConfigField "String", "FDROID", "\"https://f-droid.org/packages/%s/\"" } large { @@ -241,6 +242,7 @@ android { buildConfigField "String", "GEMINI_ENDPOINT", "\"https://generativelanguage.googleapis.com/v1beta/\"" buildConfigField "String", "GEMINI_PRIVACY", "\"https://support.google.com/gemini/answer/13594961\"" buildConfigField "String", "PWNED_ENDPOINT", "\"https://api.pwnedpasswords.com/\"" + buildConfigField "String", "PWNED_PRIVACY", "\"https://haveibeenpwned.com/Privacy\"" buildConfigField "String", "FDROID", "\"https://f-droid.org/packages/%s/\"" } fdroid { @@ -275,6 +277,7 @@ android { buildConfigField "String", "GEMINI_ENDPOINT", "\"https://generativelanguage.googleapis.com/v1beta/\"" buildConfigField "String", "GEMINI_PRIVACY", "\"https://support.google.com/gemini/answer/13594961\"" buildConfigField "String", "PWNED_ENDPOINT", "\"https://api.pwnedpasswords.com/\"" + buildConfigField "String", "PWNED_PRIVACY", "\"https://haveibeenpwned.com/Privacy\"" buildConfigField "String", "FDROID", "\"https://f-droid.org/packages/%s/\"" } play { @@ -301,6 +304,7 @@ android { buildConfigField "String", "GEMINI_ENDPOINT", "\"\"" buildConfigField "String", "GEMINI_PRIVACY", "\"\"" buildConfigField "String", "PWNED_ENDPOINT", "\"\"" + buildConfigField "String", "PWNED_PRIVACY", "\"\"" buildConfigField "String", "FDROID", "\"\"" getIsDefault().set(true) } @@ -328,6 +332,7 @@ android { buildConfigField "String", "GEMINI_ENDPOINT", "\"\"" buildConfigField "String", "GEMINI_PRIVACY", "\"\"" buildConfigField "String", "PWNED_ENDPOINT", "\"\"" + buildConfigField "String", "PWNED_PRIVACY", "\"\"" buildConfigField "String", "FDROID", "\"\"" } } diff --git a/app/src/main/java/eu/faircode/email/FragmentAccounts.java b/app/src/main/java/eu/faircode/email/FragmentAccounts.java index 2013fd74e0..83ec3e1c1a 100644 --- a/app/src/main/java/eu/faircode/email/FragmentAccounts.java +++ b/app/src/main/java/eu/faircode/email/FragmentAccounts.java @@ -31,13 +31,9 @@ import android.content.SharedPreferences; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Rect; -import android.graphics.Typeface; import android.graphics.drawable.Drawable; import android.os.Bundle; -import android.text.SpannableStringBuilder; import android.text.TextUtils; -import android.text.style.ForegroundColorSpan; -import android.text.style.StyleSpan; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuInflater; @@ -45,7 +41,6 @@ import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.widget.Button; -import android.widget.ProgressBar; import android.widget.TextView; import android.widget.Toast; @@ -486,71 +481,7 @@ public class FragmentAccounts extends FragmentBase { } private void onMenuPwned() { - final Context context = getContext(); - final View dview = LayoutInflater.from(context).inflate(R.layout.dialog_pwned, null); - final TextView tvPwned = dview.findViewById(R.id.tvPwned); - final ProgressBar pbWait = dview.findViewById(R.id.pbWait); - final Group grpReady = dview.findViewById(R.id.grpReady); - - pbWait.setVisibility(View.VISIBLE); - grpReady.setVisibility(View.GONE); - - new AlertDialog.Builder(context) - .setView(dview) - .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - // Do nothing - } - }) - .show(); - - new SimpleTask() { - @Override - protected void onPostExecute(Bundle args) { - pbWait.setVisibility(View.GONE); - } - - @Override - protected SpannableStringBuilder onExecute(Context context, Bundle args) throws Throwable { - SpannableStringBuilder ssb = new SpannableStringBuilder(); - - final int colorError = Helper.resolveColor(context, androidx.appcompat.R.attr.colorError); - final int colorVerified = Helper.resolveColor(context, R.attr.colorVerified); - - DB db = DB.getInstance(context); - List accounts = db.account().getAccounts(); - if (accounts != null) - for (EntityAccount account : accounts) - if (account.auth_type == AUTH_TYPE_PASSWORD && !TextUtils.isEmpty(account.password)) { - Integer count = HaveIBeenPwned.check(account.password, context); - boolean pwned = (count != null && count != 0); - ssb.append(account.name).append(": "); - int start = ssb.length(); - ssb.append(pwned ? "PWNED!" : "OK"); - if (pwned) { - ssb.setSpan(new ForegroundColorSpan(colorError), start, ssb.length(), 0); - ssb.setSpan(new StyleSpan(Typeface.BOLD), start, ssb.length(), 0); - } else - ssb.setSpan(new ForegroundColorSpan(colorVerified), start, ssb.length(), 0); - ssb.append('\n'); - } - - return ssb; - } - - @Override - protected void onExecuted(Bundle args, SpannableStringBuilder ssb) { - tvPwned.setText(ssb); - grpReady.setVisibility(View.VISIBLE); - } - - @Override - protected void onException(Bundle args, Throwable ex) { - tvPwned.setText(Log.formatThrowable(ex)); - grpReady.setVisibility(View.VISIBLE); - } - }.execute(this, new Bundle(), "pwned"); + new FragmentDialogPwned().show(getParentFragmentManager(), "pawned"); } @Override diff --git a/app/src/main/java/eu/faircode/email/FragmentDialogPwned.java b/app/src/main/java/eu/faircode/email/FragmentDialogPwned.java new file mode 100644 index 0000000000..5a48622877 --- /dev/null +++ b/app/src/main/java/eu/faircode/email/FragmentDialogPwned.java @@ -0,0 +1,157 @@ +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 . + + Copyright 2018-2024 by Marcel Bokhorst (M66B) +*/ + +import static eu.faircode.email.ServiceAuthenticator.AUTH_TYPE_PASSWORD; + +import android.app.Dialog; +import android.content.Context; +import android.content.DialogInterface; +import android.graphics.Typeface; +import android.net.Uri; +import android.os.Bundle; +import android.text.SpannableStringBuilder; +import android.text.TextUtils; +import android.text.style.ForegroundColorSpan; +import android.text.style.StyleSpan; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.Button; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.app.AlertDialog; +import androidx.constraintlayout.widget.Group; + +import java.io.IOException; +import java.security.NoSuchAlgorithmException; +import java.util.List; + +public class FragmentDialogPwned extends FragmentDialogBase { + @NonNull + @Override + public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) { + final Context context = getContext(); + final View dview = LayoutInflater.from(context).inflate(R.layout.dialog_pwned, null); + final TextView tvPwned = dview.findViewById(R.id.tvPwned); + final Button btnCheck = dview.findViewById(R.id.btnCheck); + final ContentLoadingProgressBar pbCheck = dview.findViewById(R.id.pbCheck); + final TextView tvPrivacy = dview.findViewById(R.id.tvPrivacy); + final Group grpReady = dview.findViewById(R.id.grpReady); + + final int colorError = Helper.resolveColor(context, androidx.appcompat.R.attr.colorError); + final int colorVerified = Helper.resolveColor(context, R.attr.colorVerified); + + btnCheck.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + new SimpleTask() { + @Override + protected void onPreExecute(Bundle args) { + btnCheck.setEnabled(false); + pbCheck.setVisibility(View.VISIBLE); + grpReady.setVisibility(View.GONE); + } + + @Override + protected void onPostExecute(Bundle args) { + btnCheck.setEnabled(true); + pbCheck.setVisibility(View.GONE); + grpReady.setVisibility(View.VISIBLE); + } + + @Override + protected SpannableStringBuilder onExecute(Context context, Bundle args) throws Throwable { + SpannableStringBuilder ssb = new SpannableStringBuilder(); + + DB db = DB.getInstance(context); + List accounts = db.account().getAccounts(); + if (accounts != null) + for (EntityAccount account : accounts) + if (account.auth_type == AUTH_TYPE_PASSWORD && + !TextUtils.isEmpty(account.password)) { + check(context, account.name, account.password, ssb); + List identities = db.identity().getIdentities(account.id); + if (identities != null) + for (EntityIdentity identity : identities) + if (identity.auth_type == AUTH_TYPE_PASSWORD && + !account.password.equals(identity.password)) + check(context, account.name + "/" + identity.user, identity.password, ssb); + } + + return ssb; + } + + private void check(Context context, String name, String password, SpannableStringBuilder ssb) throws NoSuchAlgorithmException, IOException { + Integer count = HaveIBeenPwned.check(password, context); + boolean pwned = (count != null && count != 0); + + if (ssb.length() > 0) + ssb.append('\n'); + + ssb.append(name).append(": "); + int start = ssb.length(); + ssb.append(pwned ? "PWNED!" : "OK"); + + if (pwned) { + ssb.setSpan(new ForegroundColorSpan(colorError), start, ssb.length(), 0); + ssb.setSpan(new StyleSpan(Typeface.BOLD), start, ssb.length(), 0); + } else + ssb.setSpan(new ForegroundColorSpan(colorVerified), start, ssb.length(), 0); + } + + @Override + protected void onExecuted(Bundle args, SpannableStringBuilder ssb) { + tvPwned.setText(ssb); + } + + @Override + protected void onException(Bundle args, Throwable ex) { + tvPwned.setText(Log.formatThrowable(ex)); + } + }.execute(FragmentDialogPwned.this, new Bundle(), "pwned"); + } + }); + + pbCheck.setVisibility(View.GONE); + grpReady.setVisibility(View.GONE); + + tvPrivacy.setText(BuildConfig.PWNED_PRIVACY); + tvPrivacy.getPaint().setUnderlineText(true); + tvPrivacy.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Helper.view(v.getContext(), Uri.parse(BuildConfig.PWNED_PRIVACY), true); + } + }); + + return new AlertDialog.Builder(context) + .setView(dview) + .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + // Do nothing + } + }) + .create(); + } +} + diff --git a/app/src/main/res/layout/dialog_pwned.xml b/app/src/main/res/layout/dialog_pwned.xml index 9b1369be5c..a10ce2ac4c 100644 --- a/app/src/main/res/layout/dialog_pwned.xml +++ b/app/src/main/res/layout/dialog_pwned.xml @@ -1,64 +1,78 @@ - + android:scrollbarStyle="outsideOverlay"> - + - + - - - - + - +