mirror of https://github.com/M66B/FairEmail.git
Added direct reply
This commit is contained in:
parent
cf56913a1b
commit
6edad1dce7
|
@ -35,6 +35,7 @@ import android.util.Pair;
|
|||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.core.app.NotificationCompat;
|
||||
import androidx.core.app.RemoteInput;
|
||||
import androidx.preference.PreferenceManager;
|
||||
|
||||
import com.sun.mail.iap.BadCommandException;
|
||||
|
@ -2080,6 +2081,7 @@ class Core {
|
|||
boolean notify_trash = (prefs.getBoolean("notify_trash", true) || !pro);
|
||||
boolean notify_archive = (prefs.getBoolean("notify_archive", true) || !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_seen = (prefs.getBoolean("notify_seen", true) || !pro);
|
||||
boolean light = prefs.getBoolean("light", false);
|
||||
|
@ -2279,6 +2281,25 @@ class Core {
|
|||
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) {
|
||||
Intent flag = new Intent(context, ServiceUI.class)
|
||||
.setAction("flag:" + message.id)
|
||||
|
|
|
@ -56,6 +56,7 @@ public class FragmentOptionsNotifications extends FragmentBase implements Shared
|
|||
private CheckBox cbNotifyActionTrash;
|
||||
private CheckBox cbNotifyActionArchive;
|
||||
private CheckBox cbNotifyActionReply;
|
||||
private CheckBox cbNotifyActionReplyDirect;
|
||||
private CheckBox cbNotifyActionFlag;
|
||||
private CheckBox cbNotifyActionSeen;
|
||||
private TextView tvNotifyActionsPro;
|
||||
|
@ -70,7 +71,7 @@ public class FragmentOptionsNotifications extends FragmentBase implements Shared
|
|||
|
||||
private final static String[] RESET_OPTIONS = new String[]{
|
||||
"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"
|
||||
};
|
||||
|
||||
|
@ -90,6 +91,7 @@ public class FragmentOptionsNotifications extends FragmentBase implements Shared
|
|||
cbNotifyActionTrash = view.findViewById(R.id.cbNotifyActionTrash);
|
||||
cbNotifyActionArchive = view.findViewById(R.id.cbNotifyActionArchive);
|
||||
cbNotifyActionReply = view.findViewById(R.id.cbNotifyActionReply);
|
||||
cbNotifyActionReplyDirect = view.findViewById(R.id.cbNotifyActionReplyDirect);
|
||||
cbNotifyActionFlag = view.findViewById(R.id.cbNotifyActionFlag);
|
||||
cbNotifyActionSeen = view.findViewById(R.id.cbNotifyActionSeen);
|
||||
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() {
|
||||
@Override
|
||||
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);
|
||||
cbNotifyActionArchive.setChecked(prefs.getBoolean("notify_archive", true) || !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);
|
||||
cbNotifyActionSeen.setChecked(prefs.getBoolean("notify_seen", true) || !pro);
|
||||
|
||||
|
|
|
@ -24,20 +24,30 @@ import android.app.NotificationManager;
|
|||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Bundle;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.app.RemoteInput;
|
||||
import androidx.preference.PreferenceManager;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import javax.mail.Address;
|
||||
import javax.mail.internet.InternetAddress;
|
||||
|
||||
public class ServiceUI extends IntentService {
|
||||
static final int PI_CLEAR = 1;
|
||||
static final int PI_TRASH = 2;
|
||||
static final int PI_ARCHIVE = 3;
|
||||
static final int PI_FLAG = 4;
|
||||
static final int PI_SEEN = 5;
|
||||
static final int PI_IGNORED = 6;
|
||||
static final int PI_SNOOZED = 7;
|
||||
static final int PI_REPLY_DIRECT = 4;
|
||||
static final int PI_FLAG = 5;
|
||||
static final int PI_SEEN = 6;
|
||||
static final int PI_IGNORED = 7;
|
||||
static final int PI_SNOOZED = 8;
|
||||
|
||||
public ServiceUI() {
|
||||
this(ServiceUI.class.getName());
|
||||
|
@ -74,47 +84,58 @@ public class ServiceUI extends IntentService {
|
|||
if (action == null)
|
||||
return;
|
||||
|
||||
String[] parts = action.split(":");
|
||||
long id = (parts.length > 1 ? Long.parseLong(parts[1]) : -1);
|
||||
try {
|
||||
String[] parts = action.split(":");
|
||||
long id = (parts.length > 1 ? Long.parseLong(parts[1]) : -1);
|
||||
String group = intent.getStringExtra("group");
|
||||
|
||||
switch (parts[0]) {
|
||||
case "clear":
|
||||
onClear();
|
||||
break;
|
||||
switch (parts[0]) {
|
||||
case "clear":
|
||||
onClear();
|
||||
break;
|
||||
|
||||
case "trash":
|
||||
cancel(intent.getStringExtra("group"), id);
|
||||
onTrash(id);
|
||||
break;
|
||||
case "trash":
|
||||
cancel(group, id);
|
||||
onTrash(id);
|
||||
break;
|
||||
|
||||
case "archive":
|
||||
cancel(intent.getStringExtra("group"), id);
|
||||
onArchive(id);
|
||||
break;
|
||||
case "archive":
|
||||
cancel(group, id);
|
||||
onArchive(id);
|
||||
break;
|
||||
|
||||
case "flag":
|
||||
cancel(intent.getStringExtra("group"), id);
|
||||
onFlag(id);
|
||||
break;
|
||||
case "reply":
|
||||
onReplyDirect(id, intent);
|
||||
cancel(group, id);
|
||||
onSeen(id);
|
||||
break;
|
||||
|
||||
case "seen":
|
||||
cancel(intent.getStringExtra("group"), id);
|
||||
onSeen(id);
|
||||
break;
|
||||
case "flag":
|
||||
cancel(group, id);
|
||||
onFlag(id);
|
||||
break;
|
||||
|
||||
case "ignore":
|
||||
onIgnore(id);
|
||||
break;
|
||||
case "seen":
|
||||
cancel(group, id);
|
||||
onSeen(id);
|
||||
break;
|
||||
|
||||
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:
|
||||
Log.w("Unknown action: " + parts[0]);
|
||||
case "ignore":
|
||||
onIgnore(id);
|
||||
break;
|
||||
|
||||
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) {
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
|
||||
boolean threading = prefs.getBoolean("threading", true);
|
||||
|
|
|
@ -117,6 +117,15 @@
|
|||
app:layout_constraintStart_toStartOf="parent"
|
||||
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
|
||||
android:id="@+id/cbNotifyActionFlag"
|
||||
android:layout_width="wrap_content"
|
||||
|
@ -124,7 +133,7 @@
|
|||
android:layout_marginTop="6dp"
|
||||
android:text="@string/title_advanced_notify_action_flag"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/cbNotifyActionReply" />
|
||||
app:layout_constraintTop_toBottomOf="@id/cbNotifyActionReplyDirect" />
|
||||
|
||||
<CheckBox
|
||||
android:id="@+id/cbNotifyActionSeen"
|
||||
|
|
|
@ -276,6 +276,7 @@
|
|||
<string name="title_advanced_notify_action_trash">Trash</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_direct">Direct reply</string>
|
||||
<string name="title_advanced_notify_action_flag">Star</string>
|
||||
<string name="title_advanced_notify_action_seen">Read</string>
|
||||
<string name="title_advanced_biometrics_notify">Show notification content when using biometric authentication</string>
|
||||
|
|
Loading…
Reference in New Issue