diff --git a/app/src/main/java/eu/faircode/email/FragmentCompose.java b/app/src/main/java/eu/faircode/email/FragmentCompose.java
index a3891a0097..a16bbea5d1 100644
--- a/app/src/main/java/eu/faircode/email/FragmentCompose.java
+++ b/app/src/main/java/eu/faircode/email/FragmentCompose.java
@@ -126,6 +126,8 @@ import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
@@ -2647,17 +2649,32 @@ public class FragmentCompose extends FragmentBase {
for (EntityAttachment attachment : attachments)
db.attachment().setMessage(attachment.id, draft.id);
+ // Delay sending message
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
+ int send_delayed = prefs.getInt("send_delayed", 0);
+ if (send_delayed != 0) {
+ draft.ui_snoozed = new Date().getTime() + send_delayed * 1000L;
+ db.message().setMessageSnoozed(draft.id, draft.ui_snoozed);
+ }
+
+ // Send message
if (draft.ui_snoozed == null)
EntityOperation.queue(context, db, draft, EntityOperation.SEND);
- if (draft.ui_snoozed == null) {
- Handler handler = new Handler(context.getMainLooper());
- handler.post(new Runnable() {
- public void run() {
- Toast.makeText(context, R.string.title_queued, Toast.LENGTH_LONG).show();
- }
- });
+ final String feedback;
+ if (draft.ui_snoozed == null)
+ feedback = context.getString(R.string.title_queued);
+ else {
+ DateFormat df = SimpleDateFormat.getDateTimeInstance();
+ feedback = context.getString(R.string.title_queued_at, df.format(draft.ui_snoozed));
}
+
+ Handler handler = new Handler(context.getMainLooper());
+ handler.post(new Runnable() {
+ public void run() {
+ Toast.makeText(context, feedback, Toast.LENGTH_LONG).show();
+ }
+ });
}
db.setTransactionSuccessful();
diff --git a/app/src/main/java/eu/faircode/email/FragmentOptions.java b/app/src/main/java/eu/faircode/email/FragmentOptions.java
index 3eb4fef99e..4eba168846 100644
--- a/app/src/main/java/eu/faircode/email/FragmentOptions.java
+++ b/app/src/main/java/eu/faircode/email/FragmentOptions.java
@@ -76,14 +76,16 @@ public class FragmentOptions extends FragmentBase {
case 0:
return new FragmentOptionsSynchronize();
case 1:
- return new FragmentOptionsConnection();
+ return new FragmentOptionsSend();
case 2:
- return new FragmentOptionsDisplay();
+ return new FragmentOptionsConnection();
case 3:
- return new FragmentOptionsBehavior();
+ return new FragmentOptionsDisplay();
case 4:
- return new FragmentOptionsNotifications();
+ return new FragmentOptionsBehavior();
case 5:
+ return new FragmentOptionsNotifications();
+ case 6:
return new FragmentOptionsMisc();
default:
throw new IllegalArgumentException();
@@ -92,7 +94,7 @@ public class FragmentOptions extends FragmentBase {
@Override
public int getCount() {
- return 6;
+ return 7;
}
@Override
@@ -101,14 +103,16 @@ public class FragmentOptions extends FragmentBase {
case 0:
return getString(R.string.title_advanced_section_synchronize);
case 1:
- return getString(R.string.title_advanced_section_connection);
+ return getString(R.string.title_advanced_section_send);
case 2:
- return getString(R.string.title_advanced_section_display);
+ return getString(R.string.title_advanced_section_connection);
case 3:
- return getString(R.string.title_advanced_section_behavior);
+ return getString(R.string.title_advanced_section_display);
case 4:
- return getString(R.string.title_advanced_section_notifications);
+ return getString(R.string.title_advanced_section_behavior);
case 5:
+ return getString(R.string.title_advanced_section_notifications);
+ case 6:
return getString(R.string.title_advanced_section_misc);
default:
throw new IllegalArgumentException();
diff --git a/app/src/main/java/eu/faircode/email/FragmentOptionsBehavior.java b/app/src/main/java/eu/faircode/email/FragmentOptionsBehavior.java
index fb4667508a..ba3553ba4e 100644
--- a/app/src/main/java/eu/faircode/email/FragmentOptionsBehavior.java
+++ b/app/src/main/java/eu/faircode/email/FragmentOptionsBehavior.java
@@ -50,12 +50,10 @@ public class FragmentOptionsBehavior extends FragmentBase implements SharedPrefe
private SwitchCompat swAutoResize;
private Spinner spAutoResize;
private TextView tvAutoResize;
- private SwitchCompat swPrefixOnce;
- private SwitchCompat swAutoSend;
private final static String[] RESET_OPTIONS = new String[]{
"pull", "autoscroll", "swipenav", "autoexpand", "autoclose", "autonext",
- "collapse", "autoread", "automove", "autoresize", "resize", "prefix_once", "autosend"
+ "collapse", "autoread", "automove", "autoresize", "resize"
};
@Override
@@ -80,8 +78,6 @@ public class FragmentOptionsBehavior extends FragmentBase implements SharedPrefe
swAutoResize = view.findViewById(R.id.swAutoResize);
spAutoResize = view.findViewById(R.id.spAutoResize);
tvAutoResize = view.findViewById(R.id.tvAutoResize);
- swPrefixOnce = view.findViewById(R.id.swPrefixOnce);
- swAutoSend = view.findViewById(R.id.swAutoSend);
setOptions();
@@ -175,20 +171,6 @@ public class FragmentOptionsBehavior extends FragmentBase implements SharedPrefe
}
});
- swPrefixOnce.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
- @Override
- public void onCheckedChanged(CompoundButton compoundButton, boolean checked) {
- prefs.edit().putBoolean("prefix_once", checked).apply();
- }
- });
-
- swAutoSend.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
- @Override
- public void onCheckedChanged(CompoundButton compoundButton, boolean checked) {
- prefs.edit().putBoolean("autosend", !checked).apply();
- }
- });
-
PreferenceManager.getDefaultSharedPreferences(getContext()).registerOnSharedPreferenceChangeListener(this);
return view;
@@ -254,8 +236,5 @@ public class FragmentOptionsBehavior extends FragmentBase implements SharedPrefe
break;
}
spAutoResize.setEnabled(swAutoResize.isChecked());
-
- swPrefixOnce.setChecked(prefs.getBoolean("prefix_once", false));
- swAutoSend.setChecked(!prefs.getBoolean("autosend", false));
}
}
diff --git a/app/src/main/java/eu/faircode/email/FragmentOptionsSend.java b/app/src/main/java/eu/faircode/email/FragmentOptionsSend.java
new file mode 100644
index 0000000000..9b64ea4bd5
--- /dev/null
+++ b/app/src/main/java/eu/faircode/email/FragmentOptionsSend.java
@@ -0,0 +1,150 @@
+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 .
+
+ Copyright 2018-2019 by Marcel Bokhorst (M66B)
+*/
+
+import android.content.SharedPreferences;
+import android.os.Bundle;
+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.AdapterView;
+import android.widget.CompoundButton;
+import android.widget.Spinner;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.appcompat.widget.SwitchCompat;
+import androidx.preference.PreferenceManager;
+
+public class FragmentOptionsSend extends FragmentBase implements SharedPreferences.OnSharedPreferenceChangeListener {
+ private SwitchCompat swPrefixOnce;
+ private SwitchCompat swAutoSend;
+ private Spinner spSendDelayed;
+
+ private final static String[] RESET_OPTIONS = new String[]{
+ "prefix_once", "autosend", "send_delayed"
+ };
+
+ @Override
+ @Nullable
+ public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
+ setSubtitle(R.string.title_advanced);
+ setHasOptionsMenu(true);
+
+ View view = inflater.inflate(R.layout.fragment_options_send, container, false);
+
+ // Get controls
+
+ swPrefixOnce = view.findViewById(R.id.swPrefixOnce);
+ swAutoSend = view.findViewById(R.id.swAutoSend);
+ spSendDelayed = view.findViewById(R.id.spSendDelayed);
+
+ setOptions();
+
+ // Wire controls
+
+ final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getContext());
+
+ swPrefixOnce.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
+ @Override
+ public void onCheckedChanged(CompoundButton compoundButton, boolean checked) {
+ prefs.edit().putBoolean("prefix_once", checked).apply();
+ }
+ });
+
+ swAutoSend.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
+ @Override
+ public void onCheckedChanged(CompoundButton compoundButton, boolean checked) {
+ prefs.edit().putBoolean("autosend", !checked).apply();
+ }
+ });
+
+ spSendDelayed.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
+ @Override
+ public void onItemSelected(AdapterView> adapterView, View view, int position, long id) {
+ int[] values = getResources().getIntArray(R.array.sendDelayedValues);
+ prefs.edit().putInt("send_delayed", values[position]).apply();
+ }
+
+ @Override
+ public void onNothingSelected(AdapterView> parent) {
+ prefs.edit().remove("send_delayed").apply();
+ }
+ });
+
+ PreferenceManager.getDefaultSharedPreferences(getContext()).registerOnSharedPreferenceChangeListener(this);
+
+ return view;
+ }
+
+ @Override
+ public void onDestroyView() {
+ PreferenceManager.getDefaultSharedPreferences(getContext()).unregisterOnSharedPreferenceChangeListener(this);
+ super.onDestroyView();
+ }
+
+ @Override
+ public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
+ setOptions();
+ }
+
+ @Override
+ public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+ inflater.inflate(R.menu.menu_options, menu);
+ super.onCreateOptionsMenu(menu, inflater);
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case R.id.menu_default:
+ onMenuDefault();
+ return true;
+ default:
+ return super.onOptionsItemSelected(item);
+ }
+ }
+
+ private void onMenuDefault() {
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getContext());
+ SharedPreferences.Editor editor = prefs.edit();
+ for (String option : RESET_OPTIONS)
+ editor.remove(option);
+ editor.apply();
+ }
+
+ private void setOptions() {
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getContext());
+
+ swPrefixOnce.setChecked(prefs.getBoolean("prefix_once", false));
+ swAutoSend.setChecked(!prefs.getBoolean("autosend", false));
+
+ int send_delayed = prefs.getInt("send_delayed", 0);
+ int[] sendDelayedValues = getResources().getIntArray(R.array.sendDelayedValues);
+ for (int pos = 0; pos < sendDelayedValues.length; pos++)
+ if (sendDelayedValues[pos] == send_delayed) {
+ spSendDelayed.setSelection(pos);
+ break;
+ }
+ }
+}
diff --git a/app/src/main/res/layout/fragment_options_behavior.xml b/app/src/main/res/layout/fragment_options_behavior.xml
index c954b38ef0..cae67f4c70 100644
--- a/app/src/main/res/layout/fragment_options_behavior.xml
+++ b/app/src/main/res/layout/fragment_options_behavior.xml
@@ -172,26 +172,6 @@
app:layout_constraintBottom_toBottomOf="@id/spAutoResize"
app:layout_constraintStart_toEndOf="@id/spAutoResize"
app:layout_constraintTop_toTopOf="@id/spAutoResize" />
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_options_send.xml b/app/src/main/res/layout/fragment_options_send.xml
new file mode 100644
index 0000000000..fed2c15f88
--- /dev/null
+++ b/app/src/main/res/layout/fragment_options_send.xml
@@ -0,0 +1,64 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 05b8d97974..8e140a63c5 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -154,6 +154,7 @@
Advanced options
Synchronize
+ Send
Connection
Display
Behavior
@@ -199,8 +200,10 @@
Automatically resize attached and embedded images
< %1$d pixels
Allow editing sender address
+
Prefix subject only once on replying or forwarding
Confirm sending messages
+ Delay sending messages
Group new message notifications
Show message preview in notifications
@@ -470,6 +473,7 @@
Draft saved
Send message to %1$s via %2$s?
Sending message
+ Message will be sent around %1$s
Encrypt
Decrypt
@@ -677,6 +681,26 @@
- 240
+
+ - Never
+ - 15 seconds
+ - 30 seconds
+ - 1 minute
+ - 2 minutes
+ - 5 minutes
+ - 10 minutes
+
+
+
+ - 0
+ - 15
+ - 30
+ - 60
+ - 120
+ - 300
+ - 600
+
+
- unified
- folders