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