Added direct reply

pull/162/head
M66B 6 years ago
parent cf56913a1b
commit 6edad1dce7

@ -35,6 +35,7 @@ import android.util.Pair;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.core.app.NotificationCompat; import androidx.core.app.NotificationCompat;
import androidx.core.app.RemoteInput;
import androidx.preference.PreferenceManager; import androidx.preference.PreferenceManager;
import com.sun.mail.iap.BadCommandException; import com.sun.mail.iap.BadCommandException;
@ -2080,6 +2081,7 @@ class Core {
boolean notify_trash = (prefs.getBoolean("notify_trash", true) || !pro); boolean notify_trash = (prefs.getBoolean("notify_trash", true) || !pro);
boolean notify_archive = (prefs.getBoolean("notify_archive", true) || !pro); boolean notify_archive = (prefs.getBoolean("notify_archive", true) || !pro);
boolean notify_reply = (prefs.getBoolean("notify_reply", false) && pro); boolean notify_reply = (prefs.getBoolean("notify_reply", false) && pro);
boolean notify_reply_direct = (prefs.getBoolean("notify_reply_direct", false) && pro);
boolean notify_flag = (prefs.getBoolean("notify_flag", false) && flags && pro); boolean notify_flag = (prefs.getBoolean("notify_flag", false) && flags && pro);
boolean notify_seen = (prefs.getBoolean("notify_seen", true) || !pro); boolean notify_seen = (prefs.getBoolean("notify_seen", true) || !pro);
boolean light = prefs.getBoolean("light", false); boolean light = prefs.getBoolean("light", false);
@ -2279,6 +2281,25 @@ class Core {
mbuilder.addAction(actionReply.build()); mbuilder.addAction(actionReply.build());
} }
if (notify_reply_direct &&
message.content &&
message.identity != null &&
message.from != null && message.from.length > 0 &&
db.folder().getOutbox() != null) {
Intent reply = new Intent(context, ServiceUI.class)
.setAction("reply:" + message.id)
.putExtra("group", group);
PendingIntent piReply = PendingIntent.getService(context, ServiceUI.PI_REPLY_DIRECT, reply, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Action.Builder actionReply = new NotificationCompat.Action.Builder(
R.drawable.baseline_reply_24,
context.getString(R.string.title_advanced_notify_action_reply_direct),
piReply);
RemoteInput.Builder input = new RemoteInput.Builder("text")
.setLabel(context.getString(R.string.title_advanced_notify_action_reply));
actionReply.addRemoteInput(input.build()).setAllowGeneratedReplies(false);
mbuilder.addAction(actionReply.build());
}
if (notify_flag) { if (notify_flag) {
Intent flag = new Intent(context, ServiceUI.class) Intent flag = new Intent(context, ServiceUI.class)
.setAction("flag:" + message.id) .setAction("flag:" + message.id)

@ -56,6 +56,7 @@ public class FragmentOptionsNotifications extends FragmentBase implements Shared
private CheckBox cbNotifyActionTrash; private CheckBox cbNotifyActionTrash;
private CheckBox cbNotifyActionArchive; private CheckBox cbNotifyActionArchive;
private CheckBox cbNotifyActionReply; private CheckBox cbNotifyActionReply;
private CheckBox cbNotifyActionReplyDirect;
private CheckBox cbNotifyActionFlag; private CheckBox cbNotifyActionFlag;
private CheckBox cbNotifyActionSeen; private CheckBox cbNotifyActionSeen;
private TextView tvNotifyActionsPro; private TextView tvNotifyActionsPro;
@ -70,7 +71,7 @@ public class FragmentOptionsNotifications extends FragmentBase implements Shared
private final static String[] RESET_OPTIONS = new String[]{ private final static String[] RESET_OPTIONS = new String[]{
"badge", "unseen_ignored", "badge", "unseen_ignored",
"notify_preview", "notify_trash", "notify_archive", "notify_reply", "notify_flag", "notify_seen", "biometrics_notify", "notify_preview", "notify_trash", "notify_archive", "notify_reply", "notify_reply_direct", "notify_flag", "notify_seen", "biometrics_notify",
"light", "sound" "light", "sound"
}; };
@ -90,6 +91,7 @@ public class FragmentOptionsNotifications extends FragmentBase implements Shared
cbNotifyActionTrash = view.findViewById(R.id.cbNotifyActionTrash); cbNotifyActionTrash = view.findViewById(R.id.cbNotifyActionTrash);
cbNotifyActionArchive = view.findViewById(R.id.cbNotifyActionArchive); cbNotifyActionArchive = view.findViewById(R.id.cbNotifyActionArchive);
cbNotifyActionReply = view.findViewById(R.id.cbNotifyActionReply); cbNotifyActionReply = view.findViewById(R.id.cbNotifyActionReply);
cbNotifyActionReplyDirect = view.findViewById(R.id.cbNotifyActionReplyDirect);
cbNotifyActionFlag = view.findViewById(R.id.cbNotifyActionFlag); cbNotifyActionFlag = view.findViewById(R.id.cbNotifyActionFlag);
cbNotifyActionSeen = view.findViewById(R.id.cbNotifyActionSeen); cbNotifyActionSeen = view.findViewById(R.id.cbNotifyActionSeen);
tvNotifyActionsPro = view.findViewById(R.id.tvNotifyActionsPro); tvNotifyActionsPro = view.findViewById(R.id.tvNotifyActionsPro);
@ -153,6 +155,13 @@ public class FragmentOptionsNotifications extends FragmentBase implements Shared
} }
}); });
cbNotifyActionReplyDirect.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean checked) {
prefs.edit().putBoolean("notify_reply_direct", checked).apply();
}
});
cbNotifyActionFlag.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { cbNotifyActionFlag.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override @Override
public void onCheckedChanged(CompoundButton buttonView, boolean checked) { public void onCheckedChanged(CompoundButton buttonView, boolean checked) {
@ -273,6 +282,7 @@ public class FragmentOptionsNotifications extends FragmentBase implements Shared
cbNotifyActionTrash.setChecked(prefs.getBoolean("notify_trash", true) || !pro); cbNotifyActionTrash.setChecked(prefs.getBoolean("notify_trash", true) || !pro);
cbNotifyActionArchive.setChecked(prefs.getBoolean("notify_archive", true) || !pro); cbNotifyActionArchive.setChecked(prefs.getBoolean("notify_archive", true) || !pro);
cbNotifyActionReply.setChecked(prefs.getBoolean("notify_reply", false) && pro); cbNotifyActionReply.setChecked(prefs.getBoolean("notify_reply", false) && pro);
cbNotifyActionReplyDirect.setChecked(prefs.getBoolean("notify_reply_direct", false) && pro);
cbNotifyActionFlag.setChecked(prefs.getBoolean("notify_flag", false) && pro); cbNotifyActionFlag.setChecked(prefs.getBoolean("notify_flag", false) && pro);
cbNotifyActionSeen.setChecked(prefs.getBoolean("notify_seen", true) || !pro); cbNotifyActionSeen.setChecked(prefs.getBoolean("notify_seen", true) || !pro);

@ -24,20 +24,30 @@ import android.app.NotificationManager;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.os.Bundle;
import android.widget.Toast;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.core.app.RemoteInput;
import androidx.preference.PreferenceManager; import androidx.preference.PreferenceManager;
import java.io.IOException;
import java.util.Date;
import java.util.List; import java.util.List;
import java.util.regex.Pattern;
import javax.mail.Address;
import javax.mail.internet.InternetAddress;
public class ServiceUI extends IntentService { public class ServiceUI extends IntentService {
static final int PI_CLEAR = 1; static final int PI_CLEAR = 1;
static final int PI_TRASH = 2; static final int PI_TRASH = 2;
static final int PI_ARCHIVE = 3; static final int PI_ARCHIVE = 3;
static final int PI_FLAG = 4; static final int PI_REPLY_DIRECT = 4;
static final int PI_SEEN = 5; static final int PI_FLAG = 5;
static final int PI_IGNORED = 6; static final int PI_SEEN = 6;
static final int PI_SNOOZED = 7; static final int PI_IGNORED = 7;
static final int PI_SNOOZED = 8;
public ServiceUI() { public ServiceUI() {
this(ServiceUI.class.getName()); this(ServiceUI.class.getName());
@ -74,47 +84,58 @@ public class ServiceUI extends IntentService {
if (action == null) if (action == null)
return; return;
String[] parts = action.split(":"); try {
long id = (parts.length > 1 ? Long.parseLong(parts[1]) : -1); String[] parts = action.split(":");
long id = (parts.length > 1 ? Long.parseLong(parts[1]) : -1);
switch (parts[0]) { String group = intent.getStringExtra("group");
case "clear":
onClear(); switch (parts[0]) {
break; case "clear":
onClear();
case "trash": break;
cancel(intent.getStringExtra("group"), id);
onTrash(id); case "trash":
break; cancel(group, id);
onTrash(id);
case "archive": break;
cancel(intent.getStringExtra("group"), id);
onArchive(id); case "archive":
break; cancel(group, id);
onArchive(id);
case "flag": break;
cancel(intent.getStringExtra("group"), id);
onFlag(id); case "reply":
break; onReplyDirect(id, intent);
cancel(group, id);
case "seen": onSeen(id);
cancel(intent.getStringExtra("group"), id); break;
onSeen(id);
break; case "flag":
cancel(group, id);
case "ignore": onFlag(id);
onIgnore(id); break;
break;
case "seen":
case "snooze": cancel(group, id);
// AlarmManager.RTC_WAKEUP onSeen(id);
// When the alarm is dispatched, the app will also be added to the system's temporary whitelist break;
// for approximately 10 seconds to allow that application to acquire further wake locks in which to complete its work.
// https://developer.android.com/reference/android/app/AlarmManager case "ignore":
onSnooze(id); onIgnore(id);
break; break;
default:
Log.w("Unknown action: " + parts[0]); case "snooze":
// AlarmManager.RTC_WAKEUP
// When the alarm is dispatched, the app will also be added to the system's temporary whitelist
// for approximately 10 seconds to allow that application to acquire further wake locks in which to complete its work.
// https://developer.android.com/reference/android/app/AlarmManager
onSnooze(id);
break;
default:
throw new IllegalArgumentException("Unknown UI action: " + parts[0]);
}
} catch (Throwable ex) {
Log.e(ex);
} }
} }
@ -167,6 +188,67 @@ public class ServiceUI extends IntentService {
} }
} }
private void onReplyDirect(long id, Intent intent) throws IOException {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
boolean prefix_once = prefs.getBoolean("prefix_once", true);
boolean plain_only = prefs.getBoolean("plain_only", false);
Bundle results = RemoteInput.getResultsFromIntent(intent);
String text = results.getString("text");
DB db = DB.getInstance(this);
try {
db.beginTransaction();
EntityMessage ref = db.message().getMessage(id);
if (ref == null)
throw new IllegalArgumentException("message not found");
EntityIdentity identity = db.identity().getIdentity(ref.identity);
if (identity == null)
throw new IllegalArgumentException("identity not found");
EntityFolder outbox = db.folder().getOutbox();
if (outbox == null)
throw new IllegalArgumentException("outbox not found");
String subject = (ref.subject == null ? "" : ref.subject);
if (prefix_once) {
String re = getString(R.string.title_subject_reply, "");
subject = subject.replaceAll("(?i)" + Pattern.quote(re.trim()), "").trim();
}
EntityMessage reply = new EntityMessage();
reply.account = identity.account;
reply.folder = outbox.id;
reply.identity = identity.id;
reply.msgid = EntityMessage.generateMessageId();
reply.inreplyto = ref.msgid;
reply.thread = ref.thread;
reply.to = ref.from;
reply.from = new Address[]{new InternetAddress(identity.email, identity.name)};
reply.subject = getString(R.string.title_subject_reply, subject);
reply.received = new Date().getTime();
reply.seen = true;
reply.ui_seen = true;
reply.id = db.message().insertMessage(reply);
Helper.writeText(reply.getFile(this), text);
db.message().setMessageContent(reply.id,
true,
plain_only || ref.plain_only,
HtmlHelper.getPreview(text),
null);
EntityOperation.queue(this, reply, EntityOperation.SEND);
db.setTransactionSuccessful();
ToastEx.makeText(this, R.string.title_queued, Toast.LENGTH_LONG).show();
} finally {
db.endTransaction();
}
}
private void onFlag(long id) { private void onFlag(long id) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
boolean threading = prefs.getBoolean("threading", true); boolean threading = prefs.getBoolean("threading", true);

@ -117,6 +117,15 @@
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/cbNotifyActionArchive" /> app:layout_constraintTop_toBottomOf="@id/cbNotifyActionArchive" />
<CheckBox
android:id="@+id/cbNotifyActionReplyDirect"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="6dp"
android:text="@string/title_advanced_notify_action_reply_direct"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/cbNotifyActionReply" />
<CheckBox <CheckBox
android:id="@+id/cbNotifyActionFlag" android:id="@+id/cbNotifyActionFlag"
android:layout_width="wrap_content" android:layout_width="wrap_content"
@ -124,7 +133,7 @@
android:layout_marginTop="6dp" android:layout_marginTop="6dp"
android:text="@string/title_advanced_notify_action_flag" android:text="@string/title_advanced_notify_action_flag"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/cbNotifyActionReply" /> app:layout_constraintTop_toBottomOf="@id/cbNotifyActionReplyDirect" />
<CheckBox <CheckBox
android:id="@+id/cbNotifyActionSeen" android:id="@+id/cbNotifyActionSeen"

@ -276,6 +276,7 @@
<string name="title_advanced_notify_action_trash">Trash</string> <string name="title_advanced_notify_action_trash">Trash</string>
<string name="title_advanced_notify_action_archive">Archive</string> <string name="title_advanced_notify_action_archive">Archive</string>
<string name="title_advanced_notify_action_reply">Reply</string> <string name="title_advanced_notify_action_reply">Reply</string>
<string name="title_advanced_notify_action_reply_direct">Direct reply</string>
<string name="title_advanced_notify_action_flag">Star</string> <string name="title_advanced_notify_action_flag">Star</string>
<string name="title_advanced_notify_action_seen">Read</string> <string name="title_advanced_notify_action_seen">Read</string>
<string name="title_advanced_biometrics_notify">Show notification content when using biometric authentication</string> <string name="title_advanced_biometrics_notify">Show notification content when using biometric authentication</string>

Loading…
Cancel
Save