From 93a512c0f76800cbdd735f2a26bfba76161fef51 Mon Sep 17 00:00:00 2001 From: M66B Date: Sun, 21 Aug 2022 08:50:42 +0200 Subject: [PATCH] Added definable placeholders --- .../eu/faircode/email/ActivityAnswer.java | 2 +- .../eu/faircode/email/EditTextCompose.java | 2 +- .../java/eu/faircode/email/EntityAnswer.java | 21 +++++- .../java/eu/faircode/email/EntityRule.java | 2 +- .../eu/faircode/email/FragmentAnswer.java | 63 +++++++++++++---- .../eu/faircode/email/FragmentAnswers.java | 62 +++++++++++++++++ .../eu/faircode/email/FragmentCompose.java | 8 +-- .../main/res/layout/dialog_placeholder.xml | 69 +++++++++++++++++++ app/src/main/res/menu/menu_answer.xml | 4 +- app/src/main/res/menu/menu_answers.xml | 5 ++ app/src/main/res/values/strings.xml | 3 + 11 files changed, 215 insertions(+), 26 deletions(-) create mode 100644 app/src/main/res/layout/dialog_placeholder.xml diff --git a/app/src/main/java/eu/faircode/email/ActivityAnswer.java b/app/src/main/java/eu/faircode/email/ActivityAnswer.java index 973dd9b0ee..bf435c6696 100644 --- a/app/src/main/java/eu/faircode/email/ActivityAnswer.java +++ b/app/src/main/java/eu/faircode/email/ActivityAnswer.java @@ -83,7 +83,7 @@ public class ActivityAnswer extends ActivityBase { } }); - String html = answer.getHtml(null); + String html = answer.getHtml(context, null); String text = HtmlHelper.getText(context, html); ClipboardManager cbm = Helper.getSystemService(ActivityAnswer.this, ClipboardManager.class); diff --git a/app/src/main/java/eu/faircode/email/EditTextCompose.java b/app/src/main/java/eu/faircode/email/EditTextCompose.java index 385ec20842..e9bcca2574 100644 --- a/app/src/main/java/eu/faircode/email/EditTextCompose.java +++ b/app/src/main/java/eu/faircode/email/EditTextCompose.java @@ -242,7 +242,7 @@ public class EditTextCompose extends FixedEditText { for (EntityAnswer snippet : snippets) if (snippet.id.equals(id)) { - String html = snippet.getHtml(to); + String html = snippet.getHtml(context, to); executor.submit(new Runnable() { @Override diff --git a/app/src/main/java/eu/faircode/email/EntityAnswer.java b/app/src/main/java/eu/faircode/email/EntityAnswer.java index a879b1b8ce..2f3a8c3b02 100644 --- a/app/src/main/java/eu/faircode/email/EntityAnswer.java +++ b/app/src/main/java/eu/faircode/email/EntityAnswer.java @@ -99,11 +99,13 @@ public class EntityAnswer implements Serializable { public Integer applied = 0; public Long last_applied; - String getHtml(Address[] address) { - return replacePlaceholders(text, address); + static final String PREF_PLACEHOLDER = "answer.value."; + + String getHtml(Context context, Address[] address) { + return replacePlaceholders(context, text, address); } - static String replacePlaceholders(String text, Address[] address) { + static String replacePlaceholders(Context context, String text, Address[] address) { String fullName = null; String email = null; if (address != null && address.length > 0) { @@ -173,6 +175,19 @@ public class EntityAnswer implements Serializable { text = text.replace("$lastname$", last == null ? "" : Html.escapeHtml(last)); text = text.replace("$email$", email == null ? "" : Html.escapeHtml(email)); + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); + for (String key : prefs.getAll().keySet()) + if (key.startsWith(PREF_PLACEHOLDER)) { + String name = key.substring(PREF_PLACEHOLDER.length()); + String value = prefs.getString(key, null); + + String[] lines = (value == null ? new String[0] : value.split("\n")); + for (int i = 0; i < lines.length; i++) + lines[i] = Html.escapeHtml(lines[i]); + + text = text.replace("$" + name + "$", TextUtils.join("
", lines)); + } + return text; } diff --git a/app/src/main/java/eu/faircode/email/EntityRule.java b/app/src/main/java/eu/faircode/email/EntityRule.java index f3c683b3ed..9fa7740e74 100644 --- a/app/src/main/java/eu/faircode/email/EntityRule.java +++ b/app/src/main/java/eu/faircode/email/EntityRule.java @@ -805,7 +805,7 @@ public class EntityRule { if (resend) body = Helper.readText(message.getFile(context)); else { - body = answer.getHtml(message.from); + body = answer.getHtml(context, message.from); if (original_text) { Document msg = JsoupEx.parse(body); diff --git a/app/src/main/java/eu/faircode/email/FragmentAnswer.java b/app/src/main/java/eu/faircode/email/FragmentAnswer.java index 4d5791db9d..d25a3d8a7b 100644 --- a/app/src/main/java/eu/faircode/email/FragmentAnswer.java +++ b/app/src/main/java/eu/faircode/email/FragmentAnswer.java @@ -56,6 +56,13 @@ import com.google.android.material.snackbar.Snackbar; import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; +import java.text.Collator; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; +import java.util.Locale; + public class FragmentAnswer extends FragmentBase { private ViewGroup view; private EditText etName; @@ -279,6 +286,26 @@ public class FragmentAnswer extends FragmentBase { @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { inflater.inflate(R.menu.menu_answer, menu); + + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getContext()); + List names = new ArrayList<>(); + for (String key : prefs.getAll().keySet()) + if (key.startsWith(EntityAnswer.PREF_PLACEHOLDER)) + names.add(key.substring(EntityAnswer.PREF_PLACEHOLDER.length())); + + final Collator collator = Collator.getInstance(Locale.getDefault()); + collator.setStrength(Collator.SECONDARY); // Case insensitive, process accents etc + Collections.sort(names, new Comparator() { + @Override + public int compare(String n1, String n2) { + return collator.compare(n1, n2); + } + }); + + Menu smenu = menu.findItem(R.id.menu_placeholders).getSubMenu(); + for (int i = 0; i < names.size(); i++) + smenu.add(Menu.FIRST, i + 1, i + 1, names.get(i)); + super.onCreateOptionsMenu(menu, inflater); } @@ -291,22 +318,28 @@ public class FragmentAnswer extends FragmentBase { @Override public boolean onOptionsItemSelected(MenuItem item) { - int itemId = item.getItemId(); - if (itemId == R.id.menu_help) { - onMenuHelp(); - return true; - } else if (itemId == R.id.menu_placeholder_name) { - onMenuPlaceholder("$name$"); - return true; - } else if (itemId == R.id.menu_placeholder_email) { - onMenuPlaceholder("$email$"); - return true; - } else if (itemId == R.id.menu_placeholder_firstname) { - onMenuPlaceholder("$firstname$"); - return true; - } else if (itemId == R.id.menu_placeholder_lastname) { - onMenuPlaceholder("$lastname$"); + if (item.getGroupId() == Menu.FIRST) { + String name = item.getTitle().toString(); + onMenuPlaceholder("$" + name + "$"); return true; + } else { + int itemId = item.getItemId(); + if (itemId == R.id.menu_help) { + onMenuHelp(); + return true; + } else if (itemId == R.id.menu_placeholder_name) { + onMenuPlaceholder("$name$"); + return true; + } else if (itemId == R.id.menu_placeholder_email) { + onMenuPlaceholder("$email$"); + return true; + } else if (itemId == R.id.menu_placeholder_firstname) { + onMenuPlaceholder("$firstname$"); + return true; + } else if (itemId == R.id.menu_placeholder_lastname) { + onMenuPlaceholder("$lastname$"); + return true; + } } return super.onOptionsItemSelected(item); } diff --git a/app/src/main/java/eu/faircode/email/FragmentAnswers.java b/app/src/main/java/eu/faircode/email/FragmentAnswers.java index 77b55fd295..cf2075a590 100644 --- a/app/src/main/java/eu/faircode/email/FragmentAnswers.java +++ b/app/src/main/java/eu/faircode/email/FragmentAnswers.java @@ -21,21 +21,27 @@ package eu.faircode.email; import static androidx.recyclerview.widget.RecyclerView.NO_POSITION; +import android.content.Context; +import android.content.DialogInterface; import android.content.SharedPreferences; import android.graphics.Canvas; import android.graphics.Rect; import android.os.Bundle; +import android.text.Editable; import android.text.TextUtils; +import android.text.TextWatcher; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; +import android.widget.EditText; import android.widget.TextView; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import androidx.appcompat.app.AlertDialog; import androidx.appcompat.widget.SearchView; import androidx.constraintlayout.widget.Group; import androidx.fragment.app.FragmentTransaction; @@ -275,4 +281,60 @@ public class FragmentAnswers extends FragmentBase { super.onCreateOptionsMenu(menu, inflater); } + + @Override + public boolean onOptionsItemSelected(@NonNull MenuItem item) { + int id = item.getItemId(); + if (id == R.id.menu_define) { + onDefine(); + return true; + } else + return super.onOptionsItemSelected(item); + } + + private void onDefine() { + final Context context = getContext(); + View view = LayoutInflater.from(context).inflate(R.layout.dialog_placeholder, null); + final EditText etName = view.findViewById(R.id.etName); + final EditText etValue = view.findViewById(R.id.etValue); + + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); + + etName.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + // Do nothing + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + // Do nothing + } + + @Override + public void afterTextChanged(Editable s) { + String value = prefs.getString(EntityAnswer.PREF_PLACEHOLDER + s.toString().trim(), null); + if (!TextUtils.isEmpty(value)) + etValue.setText(value); + } + }); + + new AlertDialog.Builder(context) + .setView(view) + .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + String name = etName.getText().toString().trim(); + String value = etValue.getText().toString(); + if (TextUtils.isEmpty(name)) + return; + if (TextUtils.isEmpty(value)) + prefs.edit().remove(EntityAnswer.PREF_PLACEHOLDER + name).apply(); + else + prefs.edit().putString(EntityAnswer.PREF_PLACEHOLDER + name, value).apply(); + } + }) + .setNegativeButton(android.R.string.cancel, null) + .show(); + } } diff --git a/app/src/main/java/eu/faircode/email/FragmentCompose.java b/app/src/main/java/eu/faircode/email/FragmentCompose.java index d4e5787235..4238f3c10c 100644 --- a/app/src/main/java/eu/faircode/email/FragmentCompose.java +++ b/app/src/main/java/eu/faircode/email/FragmentCompose.java @@ -2230,7 +2230,7 @@ public class FragmentCompose extends FragmentBase { } catch (AddressException ignored) { } - String html = EntityAnswer.replacePlaceholders(answer.text, to); + String html = EntityAnswer.replacePlaceholders(context, answer.text, to); Spanned spanned = HtmlHelper.fromHtml(html, new HtmlHelper.ImageGetterEx() { @Override @@ -4821,7 +4821,7 @@ public class FragmentCompose extends FragmentBase { if (answer > 0) data.draft.subject = a.name; if (TextUtils.isEmpty(external_body)) { - Document d = JsoupEx.parse(a.getHtml(null)); + Document d = JsoupEx.parse(a.getHtml(context, null)); document.body().append(d.body().html()); } } @@ -5004,7 +5004,7 @@ public class FragmentCompose extends FragmentBase { else { db.answer().applyAnswer(receipt.id, new Date().getTime()); texts = new String[0]; - Document d = JsoupEx.parse(receipt.getHtml(null)); + Document d = JsoupEx.parse(receipt.getHtml(context, null)); document.body().append(d.body().html()); } } @@ -5066,7 +5066,7 @@ public class FragmentCompose extends FragmentBase { if (a != null) { db.answer().applyAnswer(a.id, new Date().getTime()); - Document d = JsoupEx.parse(a.getHtml(data.draft.to)); + Document d = JsoupEx.parse(a.getHtml(context, data.draft.to)); document.body().append(d.body().html()); } diff --git a/app/src/main/res/layout/dialog_placeholder.xml b/app/src/main/res/layout/dialog_placeholder.xml new file mode 100644 index 0000000000..3ae3f51462 --- /dev/null +++ b/app/src/main/res/layout/dialog_placeholder.xml @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/menu/menu_answer.xml b/app/src/main/res/menu/menu_answer.xml index e67f06548f..e2e939728f 100644 --- a/app/src/main/res/menu/menu_answer.xml +++ b/app/src/main/res/menu/menu_answer.xml @@ -6,7 +6,9 @@ android:icon="@drawable/twotone_help_24" android:title="" app:showAsAction="always" /> - + + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 1a613eeee1..0eef0579f3 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1652,6 +1652,9 @@ So, don\'t delete the image file! + Define placeholder + Name + Value Edit template Reply template Template name