Added definable placeholders

pull/209/head
M66B 2 years ago
parent 4b353d9c07
commit 93a512c0f7

@ -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);

@ -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

@ -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("<br>", lines));
}
return text;
}

@ -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);

@ -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<String> 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<String>() {
@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);
}

@ -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();
}
}

@ -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());
}

@ -0,0 +1,69 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="24dp">
<TextView
android:id="@+id/tvName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:labelFor="@+id/etName"
android:text="@string/title_answer_define"
android:textAppearance="@style/TextAppearance.AppCompat.Large"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/tvBefore"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="9dp"
android:paddingEnd="6dp"
android:text="$"
android:textAppearance="@style/TextAppearance.AppCompat.Large"
app:layout_constraintBottom_toBottomOf="@id/etName"
app:layout_constraintStart_toStartOf="parent" />
<EditText
android:id="@+id/etName"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:hint="@string/title_answer_define_name"
android:imeOptions="actionDone"
android:inputType="text"
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
app:layout_constraintEnd_toStartOf="@+id/tvAfter"
app:layout_constraintStart_toEndOf="@+id/tvBefore"
app:layout_constraintTop_toBottomOf="@id/tvName">
<requestFocus />
</EditText>
<TextView
android:id="@+id/tvAfter"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:layout_marginBottom="9dp"
android:paddingStart="6dp"
android:text="$"
android:textAppearance="@style/TextAppearance.AppCompat.Large"
app:layout_constraintBottom_toBottomOf="@id/etName"
app:layout_constraintEnd_toEndOf="parent" />
<EditText
android:id="@+id/etValue"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:hint="@string/title_answer_define_value"
android:imeOptions="actionDone"
android:inputType="textMultiLine|textCapSentences|textAutoCorrect"
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/etName" />
</androidx.constraintlayout.widget.ConstraintLayout>

@ -6,7 +6,9 @@
android:icon="@drawable/twotone_help_24"
android:title=""
app:showAsAction="always" />
<item android:title="@string/title_answer_placeholder">
<item
android:id="@+id/menu_placeholders"
android:title="@string/title_answer_placeholder">
<menu>
<item
android:id="@+id/menu_placeholder_name"

@ -7,4 +7,9 @@
android:title="@string/title_search"
app:actionViewClass="androidx.appcompat.widget.SearchView"
app:showAsAction="collapseActionView|always" />
<item
android:id="@+id/menu_define"
android:icon="@drawable/twotone_add_24"
android:title="@string/title_answer_define" />
</menu>

@ -1652,6 +1652,9 @@
So, don\'t delete the image file!
</string>
<string name="title_answer_define">Define placeholder</string>
<string name="title_answer_define_name">Name</string>
<string name="title_answer_define_value">Value</string>
<string name="title_answer_caption">Edit template</string>
<string name="title_answer_reply">Reply template</string>
<string name="title_answer_name">Template name</string>

Loading…
Cancel
Save