From e3b1aa13d6f6ef16b45c14ed38439652c06d4024 Mon Sep 17 00:00:00 2001 From: M66B Date: Thu, 9 May 2019 08:15:10 +0200 Subject: [PATCH] Added option to send messages with a small delay --- .../eu/faircode/email/FragmentCompose.java | 31 +++- .../eu/faircode/email/FragmentOptions.java | 22 +-- .../email/FragmentOptionsBehavior.java | 23 +-- .../faircode/email/FragmentOptionsSend.java | 150 ++++++++++++++++++ .../res/layout/fragment_options_behavior.xml | 20 --- .../main/res/layout/fragment_options_send.xml | 64 ++++++++ app/src/main/res/values/strings.xml | 24 +++ 7 files changed, 276 insertions(+), 58 deletions(-) create mode 100644 app/src/main/java/eu/faircode/email/FragmentOptionsSend.java create mode 100644 app/src/main/res/layout/fragment_options_send.xml 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