diff --git a/app/src/main/java/eu/faircode/email/EntityAnswer.java b/app/src/main/java/eu/faircode/email/EntityAnswer.java index 802f5a79e2..d3eda1653a 100644 --- a/app/src/main/java/eu/faircode/email/EntityAnswer.java +++ b/app/src/main/java/eu/faircode/email/EntityAnswer.java @@ -19,10 +19,21 @@ package eu.faircode.email; Copyright 2018-2022 by Marcel Bokhorst (M66B) */ +import android.content.Context; +import android.content.Intent; +import android.graphics.Typeface; import android.text.Html; +import android.text.SpannableStringBuilder; +import android.text.Spanned; import android.text.TextUtils; +import android.text.style.RelativeSizeSpan; +import android.text.style.StyleSpan; +import android.view.Menu; +import android.view.MenuItem; +import android.view.SubMenu; import androidx.annotation.NonNull; +import androidx.core.view.MenuCompat; import androidx.room.Entity; import androidx.room.PrimaryKey; @@ -30,6 +41,15 @@ import org.json.JSONException; import org.json.JSONObject; import java.io.Serializable; +import java.text.Collator; +import java.text.NumberFormat; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; import java.util.Objects; import javax.mail.Address; @@ -139,6 +159,134 @@ public class EntityAnswer implements Serializable { return text; } + static void fillMenu(Menu main, boolean compose, List answers, Context context) { + boolean grouped = BuildConfig.DEBUG; + + List favorites = new ArrayList<>(); + List groups = new ArrayList<>(); + for (EntityAnswer answer : answers) + if (compose && answer.favorite) + favorites.add(answer); + else if (answer.group != null && !groups.contains(answer.group)) + groups.add(answer.group); + + Collator collator = Collator.getInstance(Locale.getDefault()); + collator.setStrength(Collator.SECONDARY); // Case insensitive, process accents etc + Collections.sort(groups, collator); + + Collections.sort(answers, new Comparator() { + @Override + public int compare(EntityAnswer a1, EntityAnswer a2) { + if (!grouped || a1.applied.equals(a2.applied)) + return collator.compare(a1.name, a2.name); + else + return -a1.applied.compareTo(a2.applied); + } + }); + + Collections.sort(favorites, new Comparator() { + @Override + public int compare(EntityAnswer a1, EntityAnswer a2) { + return collator.compare(a1.name, a2.name); + } + }); + + int order = 0; + + Map map = new HashMap<>(); + for (String group : groups) + map.put(group, main.addSubMenu(Menu.NONE, order, order++, group)); + + NumberFormat NF = NumberFormat.getNumberInstance(); + for (EntityAnswer answer : answers) { + if (compose && answer.favorite) + continue; + order++; + + SpannableStringBuilder name = new SpannableStringBuilder(answer.name); + if (grouped && answer.applied > 0) { + name.append(" (").append(NF.format(answer.applied)).append(")"); + name.setSpan(new RelativeSizeSpan(HtmlHelper.FONT_SMALL), + answer.name.length() + 1, name.length(), 0); + } + + MenuItem item; + if (answer.group == null) + item = main.add(Menu.NONE, order, order++, name); + else { + SubMenu smenu = map.get(answer.group); + item = smenu.add(answer.applied > 0 ? Menu.FIRST : Menu.NONE, + smenu.size(), smenu.size() + 1, name); + } + item.setIntent(new Intent().putExtra("id", answer.id)); + } + + if (compose && BuildConfig.DEBUG) { + SubMenu profiles = main.addSubMenu(Menu.NONE, order, order++, "Profiles"); + for (EmailProvider p : EmailProvider.loadProfiles(context)) { + SpannableStringBuilder ssb = new SpannableStringBuilderEx(); + int start; + ssb.append("IMAP (account, receive)"); + + ssb.append(" host "); + start = ssb.length(); + ssb.append(p.imap.host); + ssb.setSpan(new StyleSpan(Typeface.BOLD), + start, ssb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + + ssb.append(" port "); + start = ssb.length(); + ssb.append(Integer.toString(p.imap.port)); + ssb.setSpan(new StyleSpan(Typeface.BOLD), + start, ssb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + + ssb.append(" encryption "); + start = ssb.length(); + ssb.append(p.imap.starttls ? "STARTTLS" : "SSL/TLS"); + ssb.setSpan(new StyleSpan(Typeface.BOLD), + start, ssb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + + ssb.append("\n\n"); + + ssb.append("SMTP (identity, send)"); + + ssb.append(" host "); + start = ssb.length(); + ssb.append(p.smtp.host); + ssb.setSpan(new StyleSpan(Typeface.BOLD), + start, ssb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + + ssb.append(" port "); + start = ssb.length(); + ssb.append(Integer.toString(p.smtp.port)); + ssb.setSpan(new StyleSpan(Typeface.BOLD), + start, ssb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + + ssb.append(" encryption "); + start = ssb.length(); + ssb.append(p.smtp.starttls ? "STARTTLS" : "SSL/TLS"); + ssb.setSpan(new StyleSpan(Typeface.BOLD), + start, ssb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + + ssb.append("\n\n"); + + if (!TextUtils.isEmpty(p.link)) + ssb.append(p.link).append("\n\n"); + + profiles.add(999, profiles.size(), profiles.size() + 1, p.name + + (p.appPassword ? "+" : "")) + .setIntent(new Intent().putExtra("config", ssb)); + } + } + + for (EntityAnswer answer : favorites) + main.add(Menu.NONE, order, order++, answer.toString()) + .setIntent(new Intent().putExtra("id", answer.id)); + + if (grouped) + MenuCompat.setGroupDividerEnabled(main, true); + } + public JSONObject toJSON() throws JSONException { JSONObject json = new JSONObject(); json.put("id", id); diff --git a/app/src/main/java/eu/faircode/email/FragmentCompose.java b/app/src/main/java/eu/faircode/email/FragmentCompose.java index f9c2a40d36..ce8e8afbb5 100644 --- a/app/src/main/java/eu/faircode/email/FragmentCompose.java +++ b/app/src/main/java/eu/faircode/email/FragmentCompose.java @@ -79,7 +79,6 @@ import android.text.style.ImageSpan; import android.text.style.ParagraphStyle; import android.text.style.QuoteSpan; import android.text.style.RelativeSizeSpan; -import android.text.style.StyleSpan; import android.text.style.URLSpan; import android.util.LogPrinter; import android.util.Pair; @@ -91,7 +90,6 @@ import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.MotionEvent; -import android.view.SubMenu; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; @@ -1893,138 +1891,15 @@ public class FragmentCompose extends FragmentBase { @Override protected void onExecuted(Bundle args, final List answers) { + final Context context = getContext(); + if (answers.size() == 0) { - ToastEx.makeText(getContext(), R.string.title_no_answers, Toast.LENGTH_LONG).show(); + ToastEx.makeText(context, R.string.title_no_answers, Toast.LENGTH_LONG).show(); return; } - boolean grouped = BuildConfig.DEBUG; - PopupMenuLifecycle popupMenu = new PopupMenuLifecycle(getContext(), getViewLifecycleOwner(), vwAnchorMenu); - Menu main = popupMenu.getMenu(); - - List favorites = new ArrayList<>(); - List groups = new ArrayList<>(); - for (EntityAnswer answer : answers) - if (answer.favorite) - favorites.add(answer); - else if (answer.group != null && !groups.contains(answer.group)) - groups.add(answer.group); - - Collator collator = Collator.getInstance(Locale.getDefault()); - collator.setStrength(Collator.SECONDARY); // Case insensitive, process accents etc - Collections.sort(groups, collator); - - Collections.sort(answers, new Comparator() { - @Override - public int compare(EntityAnswer a1, EntityAnswer a2) { - if (!grouped || a1.applied.equals(a2.applied)) - return collator.compare(a1.name, a2.name); - else - return -a1.applied.compareTo(a2.applied); - } - }); - - Collections.sort(favorites, new Comparator() { - @Override - public int compare(EntityAnswer a1, EntityAnswer a2) { - return collator.compare(a1.name, a2.name); - } - }); - - int order = 0; - - Map map = new HashMap<>(); - for (String group : groups) - map.put(group, main.addSubMenu(Menu.NONE, order, order++, group)); - - NumberFormat NF = NumberFormat.getNumberInstance(); - for (EntityAnswer answer : answers) { - if (answer.favorite) - continue; - order++; - - SpannableStringBuilder name = new SpannableStringBuilder(answer.name); - if (grouped && answer.applied > 0) { - name.append(" (").append(NF.format(answer.applied)).append(")"); - name.setSpan(new RelativeSizeSpan(HtmlHelper.FONT_SMALL), - answer.name.length() + 1, name.length(), 0); - } - - MenuItem item; - if (answer.group == null) - item = main.add(Menu.NONE, order, order++, name); - else { - SubMenu smenu = map.get(answer.group); - item = smenu.add(answer.applied > 0 ? Menu.FIRST : Menu.NONE, - smenu.size(), smenu.size() + 1, name); - } - item.setIntent(new Intent().putExtra("id", answer.id)); - } - - for (EntityAnswer answer : favorites) - main.add(Menu.NONE, order, order++, answer.toString()) - .setIntent(new Intent().putExtra("id", answer.id)); - - if (BuildConfig.DEBUG) { - SubMenu profiles = main.addSubMenu(Menu.NONE, order, order++, "Profiles"); - for (EmailProvider p : EmailProvider.loadProfiles(getContext())) { - SpannableStringBuilder ssb = new SpannableStringBuilderEx(); - int start; - ssb.append("IMAP (account, receive)"); - - ssb.append(" host "); - start = ssb.length(); - ssb.append(p.imap.host); - ssb.setSpan(new StyleSpan(Typeface.BOLD), - start, ssb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); - - ssb.append(" port "); - start = ssb.length(); - ssb.append(Integer.toString(p.imap.port)); - ssb.setSpan(new StyleSpan(Typeface.BOLD), - start, ssb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); - - ssb.append(" encryption "); - start = ssb.length(); - ssb.append(p.imap.starttls ? "STARTTLS" : "SSL/TLS"); - ssb.setSpan(new StyleSpan(Typeface.BOLD), - start, ssb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); - - ssb.append("\n\n"); - - ssb.append("SMTP (identity, send)"); - - ssb.append(" host "); - start = ssb.length(); - ssb.append(p.smtp.host); - ssb.setSpan(new StyleSpan(Typeface.BOLD), - start, ssb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); - - ssb.append(" port "); - start = ssb.length(); - ssb.append(Integer.toString(p.smtp.port)); - ssb.setSpan(new StyleSpan(Typeface.BOLD), - start, ssb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); - - ssb.append(" encryption "); - start = ssb.length(); - ssb.append(p.smtp.starttls ? "STARTTLS" : "SSL/TLS"); - ssb.setSpan(new StyleSpan(Typeface.BOLD), - start, ssb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); - - ssb.append("\n\n"); - - if (!TextUtils.isEmpty(p.link)) - ssb.append(p.link).append("\n\n"); - - profiles.add(999, profiles.size(), profiles.size() + 1, p.name + - (p.appPassword ? "+" : "")) - .setIntent(new Intent().putExtra("config", ssb)); - } - } - - if (grouped) - MenuCompat.setGroupDividerEnabled(popupMenu.getMenu(), true); + PopupMenuLifecycle popupMenu = new PopupMenuLifecycle(context, getViewLifecycleOwner(), vwAnchorMenu); + EntityAnswer.fillMenu(popupMenu.getMenu(), true, answers, context); popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() { @Override @@ -2033,8 +1908,8 @@ public class FragmentCompose extends FragmentBase { if (intent == null) return false; - if (!ActivityBilling.isPro(getContext())) { - startActivity(new Intent(getContext(), ActivityBilling.class)); + if (!ActivityBilling.isPro(context)) { + startActivity(new Intent(context, ActivityBilling.class)); return true; } diff --git a/app/src/main/java/eu/faircode/email/FragmentMessages.java b/app/src/main/java/eu/faircode/email/FragmentMessages.java index a8fb9d21cb..6b138f837e 100644 --- a/app/src/main/java/eu/faircode/email/FragmentMessages.java +++ b/app/src/main/java/eu/faircode/email/FragmentMessages.java @@ -3047,70 +3047,21 @@ public class FragmentMessages extends FragmentBase implements SharedPreferences. @Override protected void onExecuted(Bundle args, List answers) { + final Context context = getContext(); if (answers == null || answers.size() == 0) { Snackbar snackbar = Snackbar.make(view, R.string.title_no_answers, Snackbar.LENGTH_LONG) .setGestureInsetBottomIgnored(true); snackbar.setAction(R.string.title_fix, new View.OnClickListener() { @Override public void onClick(View v) { - LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(getContext()); + LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(v.getContext()); lbm.sendBroadcast(new Intent(ActivityView.ACTION_EDIT_ANSWERS)); } }); snackbar.show(); } else { - boolean grouped = BuildConfig.DEBUG; - PopupMenuLifecycle popupMenu = new PopupMenuLifecycle(getContext(), getViewLifecycleOwner(), fabReply); - Menu main = popupMenu.getMenu(); - - List groups = new ArrayList<>(); - for (EntityAnswer answer : answers) - if (answer.group != null && !groups.contains(answer.group)) - groups.add(answer.group); - - Collator collator = Collator.getInstance(Locale.getDefault()); - collator.setStrength(Collator.SECONDARY); // Case insensitive, process accents etc - Collections.sort(groups, collator); - - Collections.sort(answers, new Comparator() { - @Override - public int compare(EntityAnswer a1, EntityAnswer a2) { - if (!grouped || a1.applied.equals(a2.applied)) - return collator.compare(a1.name, a2.name); - else - return -a1.applied.compareTo(a2.applied); - } - }); - - int order = 0; - - Map map = new HashMap<>(); - for (String group : groups) - map.put(group, main.addSubMenu(Menu.NONE, order, order++, group)); - - for (EntityAnswer answer : answers) { - order++; - - SpannableStringBuilder name = new SpannableStringBuilder(answer.name); - if (grouped && answer.applied > 0) { - name.append(" (").append(NF.format(answer.applied)).append(")"); - name.setSpan(new RelativeSizeSpan(HtmlHelper.FONT_SMALL), - answer.name.length() + 1, name.length(), 0); - } - - MenuItem item; - if (answer.group == null) - item = main.add(Menu.NONE, order, order++, name); - else { - SubMenu smenu = map.get(answer.group); - item = smenu.add(answer.applied > 0 ? Menu.FIRST : Menu.NONE, - smenu.size(), smenu.size() + 1, name); - } - item.setIntent(new Intent().putExtra("id", answer.id)); - } - - if (grouped) - MenuCompat.setGroupDividerEnabled(popupMenu.getMenu(), true); + PopupMenuLifecycle popupMenu = new PopupMenuLifecycle(context, getViewLifecycleOwner(), fabReply); + EntityAnswer.fillMenu(popupMenu.getMenu(), false, answers, context); popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() { @Override @@ -3119,12 +3070,12 @@ public class FragmentMessages extends FragmentBase implements SharedPreferences. if (intent == null) return false; - if (!ActivityBilling.isPro(getContext())) { - startActivity(new Intent(getContext(), ActivityBilling.class)); + if (!ActivityBilling.isPro(context)) { + startActivity(new Intent(context, ActivityBilling.class)); return true; } - startActivity(new Intent(getContext(), ActivityCompose.class) + startActivity(new Intent(context, ActivityCompose.class) .putExtra("action", "reply") .putExtra("reference", message.id) .putExtra("answer", intent.getLongExtra("id", -1)));