Experimental: external use of templates

pull/201/head
M66B 3 years ago
parent b4ca7c6df6
commit ec35b51ef5

File diff suppressed because it is too large Load Diff

@ -225,6 +225,22 @@
</intent-filter>
</activity>
<activity
android:name=".ActivityAnswer"
android:enabled="false"
android:excludeFromRecents="true"
android:exported="true"
android:icon="@drawable/twotone_reply_24"
android:label="@string/app_answer"
android:launchMode="singleTask">
<intent-filter>
<action android:name="android.intent.action.PROCESS_TEXT" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain" />
</intent-filter>
</activity>
<activity
android:name=".ActivityCompose"
android:exported="true"

@ -0,0 +1,113 @@
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 <http://www.gnu.org/licenses/>.
Copyright 2018-2021 by Marcel Bokhorst (M66B)
*/
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.Toast;
import androidx.annotation.RequiresApi;
import androidx.constraintlayout.widget.Group;
import java.util.List;
public class ActivityAnswer extends ActivityBase {
@Override
@RequiresApi(api = Build.VERSION_CODES.M)
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getSupportActionBar().setSubtitle(getString(R.string.app_answer));
View view = LayoutInflater.from(this).inflate(R.layout.activity_answer, null);
setContentView(view);
ListView lvAnswer = view.findViewById(R.id.lvAnswer);
Group grpReady = view.findViewById(R.id.grpReady);
ContentLoadingProgressBar pbWait = view.findViewById(R.id.pbWait);
lvAnswer.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int pos, long id) {
EntityAnswer answer = (EntityAnswer) adapterView.getAdapter().getItem(pos);
String html = answer.getText(null);
String text = HtmlHelper.getText(ActivityAnswer.this, html);
ClipboardManager cbm = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
cbm.setPrimaryClip(ClipData.newHtmlText(getString(R.string.app_name), text, html));
ToastEx.makeText(ActivityAnswer.this, R.string.title_clipboard_copied, Toast.LENGTH_LONG).show();
Intent intent = getIntent();
if (intent != null) {
boolean readonly = intent.getBooleanExtra(Intent.EXTRA_PROCESS_TEXT_READONLY, false);
if (!readonly) {
Intent result = new Intent();
result.putExtra(Intent.EXTRA_PROCESS_TEXT, text);
setResult(RESULT_OK, result);
}
}
finish();
}
});
new SimpleTask<List<EntityAnswer>>() {
@Override
protected void onPreExecute(Bundle args) {
grpReady.setVisibility(View.GONE);
pbWait.setVisibility(View.VISIBLE);
}
@Override
protected void onPostExecute(Bundle args) {
grpReady.setVisibility(View.VISIBLE);
pbWait.setVisibility(View.GONE);
}
@Override
protected List<EntityAnswer> onExecute(Context context, Bundle args) throws Throwable {
DB db = DB.getInstance(context);
return db.answer().getAnswersExternal();
}
@Override
protected void onExecuted(Bundle args, List<EntityAnswer> answers) {
ArrayAdapter<EntityAnswer> adapter = new ArrayAdapter<EntityAnswer>(ActivityAnswer.this,
android.R.layout.simple_list_item_1, answers);
lvAnswer.setAdapter(adapter);
}
@Override
protected void onException(Bundle args, Throwable ex) {
Log.unexpectedError(getSupportFragmentManager(), ex);
}
}.execute(this, new Bundle(), "answers");
}
}

@ -66,7 +66,7 @@ import static eu.faircode.email.ServiceAuthenticator.AUTH_TYPE_PASSWORD;
// https://developer.android.com/topic/libraries/architecture/room.html
@Database(
version = 204,
version = 205,
entities = {
EntityIdentity.class,
EntityAccount.class,
@ -2079,6 +2079,12 @@ public abstract class DB extends RoomDatabase {
cursor.close();
}
}
}).addMigrations(new Migration(204, 205) {
@Override
public void migrate(@NonNull SupportSQLiteDatabase db) {
Log.i("DB migration from version " + startVersion + " to " + endVersion);
db.execSQL("ALTER TABLE `answer` ADD COLUMN `external` INTEGER NOT NULL DEFAULT 0");
}
}).addMigrations(new Migration(998, 999) {
@Override
public void migrate(@NonNull SupportSQLiteDatabase db) {

@ -40,6 +40,12 @@ public interface DaoAnswer {
" ORDER BY name COLLATE NOCASE")
List<EntityAnswer> getAnswersByFavorite(boolean favorite);
@Query("SELECT * FROM answer" +
" WHERE external" +
" AND NOT hide" +
" ORDER BY name COLLATE NOCASE")
List<EntityAnswer> getAnswersExternal();
@Query("SELECT * FROM answer WHERE id = :id")
EntityAnswer getAnswer(long id);

@ -60,6 +60,8 @@ public class EntityAnswer implements Serializable {
@NonNull
public Boolean hide;
@NonNull
public Boolean external;
@NonNull
public String text;
@NonNull
public Integer applied = 0;
@ -164,6 +166,7 @@ public class EntityAnswer implements Serializable {
this.receipt.equals(other.receipt) &&
this.favorite.equals(other.favorite) &&
this.hide.equals(other.hide) &&
this.external.equals(other.external) &&
this.text.equals(other.text) &&
this.applied.equals(other.applied) &&
Objects.equals(this.last_applied, other.last_applied));

@ -19,6 +19,8 @@ package eu.faircode.email;
Copyright 2018-2021 by Marcel Bokhorst (M66B)
*/
import static android.app.Activity.RESULT_OK;
import android.content.ClipboardManager;
import android.content.Context;
import android.content.Intent;
@ -53,8 +55,6 @@ import com.google.android.material.snackbar.Snackbar;
import org.jsoup.nodes.Document;
import static android.app.Activity.RESULT_OK;
public class FragmentAnswer extends FragmentBase {
private ViewGroup view;
private EditText etName;
@ -63,6 +63,7 @@ public class FragmentAnswer extends FragmentBase {
private CheckBox cbReceipt;
private CheckBox cbFavorite;
private CheckBox cbHide;
private CheckBox cbExternal;
private EditTextCompose etText;
private BottomNavigationView style_bar;
private BottomNavigationView bottom_navigation;
@ -107,6 +108,7 @@ public class FragmentAnswer extends FragmentBase {
cbReceipt = view.findViewById(R.id.cbReceipt);
cbFavorite = view.findViewById(R.id.cbFavorite);
cbHide = view.findViewById(R.id.cbHide);
cbExternal = view.findViewById(R.id.cbExternal);
etText = view.findViewById(R.id.etText);
style_bar = view.findViewById(R.id.style_bar);
@ -150,6 +152,7 @@ public class FragmentAnswer extends FragmentBase {
});
// Initialize
cbExternal.setVisibility(View.GONE);
grpReady.setVisibility(View.GONE);
style_bar.setVisibility(View.GONE);
bottom_navigation.setVisibility(View.GONE);
@ -201,6 +204,7 @@ public class FragmentAnswer extends FragmentBase {
cbReceipt.setChecked(answer == null ? false : answer.receipt);
cbFavorite.setChecked(answer == null ? false : answer.favorite);
cbHide.setChecked(answer == null ? false : answer.hide);
cbExternal.setChecked(answer == null ? false : answer.external);
String html = (answer == null ? a.getString("html") : answer.text);
if (html == null)
@ -218,6 +222,8 @@ public class FragmentAnswer extends FragmentBase {
bottom_navigation.findViewById(R.id.action_delete).setVisibility(answer == null ? View.GONE : View.VISIBLE);
if (BuildConfig.DEBUG)
cbExternal.setVisibility(View.VISIBLE);
grpReady.setVisibility(View.VISIBLE);
bottom_navigation.setVisibility(View.VISIBLE);
}
@ -321,6 +327,7 @@ public class FragmentAnswer extends FragmentBase {
args.putBoolean("receipt", cbReceipt.isChecked());
args.putBoolean("favorite", cbFavorite.isChecked());
args.putBoolean("hide", cbHide.isChecked());
args.putBoolean("external", cbExternal.isChecked());
args.putString("html", HtmlHelper.toHtml(etText.getText(), getContext()));
new SimpleTask<Void>() {
@ -343,6 +350,7 @@ public class FragmentAnswer extends FragmentBase {
boolean receipt = args.getBoolean("receipt");
boolean favorite = args.getBoolean("favorite");
boolean hide = args.getBoolean("hide");
boolean external = args.getBoolean("external");
String html = args.getString("html");
if (TextUtils.isEmpty(name))
@ -369,6 +377,7 @@ public class FragmentAnswer extends FragmentBase {
answer.receipt = receipt;
answer.favorite = favorite;
answer.hide = hide;
answer.external = external;
answer.text = document.body().html();
answer.id = db.answer().insertAnswer(answer);
} else {
@ -379,6 +388,7 @@ public class FragmentAnswer extends FragmentBase {
answer.receipt = receipt;
answer.favorite = favorite;
answer.hide = hide;
answer.external = external;
answer.text = document.body().html();
db.answer().updateAnswer(answer);
}

@ -274,6 +274,8 @@ public class FragmentOptionsMisc extends FragmentBase implements SharedPreferenc
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean checked) {
Helper.enableComponent(getContext(), ActivitySearch.class, checked);
if (BuildConfig.DEBUG)
Helper.enableComponent(getContext(), ActivityAnswer.class, checked);
}
});

@ -0,0 +1,29 @@
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="eu.faircode.email.ActivityAnswer">
<ListView
android:id="@+id/lvAnswer"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<androidx.constraintlayout.widget.Group
android:id="@+id/grpReady"
android:layout_width="0dp"
android:layout_height="0dp"
app:constraint_referenced_ids="lvAnswer" />
<eu.faircode.email.ContentLoadingProgressBar
android:id="@+id/pbWait"
style="@style/Base.Widget.AppCompat.ProgressBar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:indeterminate="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

@ -92,6 +92,16 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/cbFavorite" />
<CheckBox
android:id="@+id/cbExternal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="6dp"
android:layout_marginTop="6dp"
android:text="@string/title_answer_external"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/cbHide" />
<View
android:id="@+id/vSeparator"
android:layout_width="0dp"
@ -100,7 +110,7 @@
android:background="?attr/colorSeparator"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/cbHide" />
app:layout_constraintTop_toBottomOf="@+id/cbExternal" />
<eu.faircode.email.EditTextCompose
android:id="@+id/etText"

@ -2,6 +2,7 @@
<string name="app_name" translatable="false">FairEmail</string>
<string name="app_copyright" translatable="false">Copyright &#x24B8; 20182021 by M. Bokhorst</string>
<string name="app_search">FairEmail search</string>
<string name="app_answer" translatable="false">FairEmail template</string>
<string name="app_changelog">Changelog</string>
<string name="app_welcome">FairEmail is an open source email app focused on privacy and security. For this reason some features might work differently from what you are used to.</string>
<string name="app_limitations">For example, messages are reformatted by default to remove unsafe elements and to improve readability, and opening links needs to be confirmed for safety. Both can be disabled if desired.</string>
@ -1325,6 +1326,7 @@
<string name="title_answer_favorite">Favorite</string>
<string name="title_answer_receipt">Use as read receipt</string>
<string name="title_answer_hide">Hide from menus</string>
<string name="title_answer_external" translatable="false">External</string>
<string name="title_answer_text">Template text</string>
<string name="title_answer_placeholder">Placeholder</string>
<string name="title_answer_placeholder_name">Sender\'s full name</string>

Loading…
Cancel
Save