Added option to send messages with a small delay

pull/156/head
M66B 6 years ago
parent b4f31be14d
commit e3b1aa13d6

@ -126,6 +126,8 @@ import java.io.FileWriter;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Date; import java.util.Date;
@ -2647,17 +2649,32 @@ public class FragmentCompose extends FragmentBase {
for (EntityAttachment attachment : attachments) for (EntityAttachment attachment : attachments)
db.attachment().setMessage(attachment.id, draft.id); 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) if (draft.ui_snoozed == null)
EntityOperation.queue(context, db, draft, EntityOperation.SEND); EntityOperation.queue(context, db, draft, EntityOperation.SEND);
if (draft.ui_snoozed == null) { final String feedback;
Handler handler = new Handler(context.getMainLooper()); if (draft.ui_snoozed == null)
handler.post(new Runnable() { feedback = context.getString(R.string.title_queued);
public void run() { else {
Toast.makeText(context, R.string.title_queued, Toast.LENGTH_LONG).show(); 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(); db.setTransactionSuccessful();

@ -76,14 +76,16 @@ public class FragmentOptions extends FragmentBase {
case 0: case 0:
return new FragmentOptionsSynchronize(); return new FragmentOptionsSynchronize();
case 1: case 1:
return new FragmentOptionsConnection(); return new FragmentOptionsSend();
case 2: case 2:
return new FragmentOptionsDisplay(); return new FragmentOptionsConnection();
case 3: case 3:
return new FragmentOptionsBehavior(); return new FragmentOptionsDisplay();
case 4: case 4:
return new FragmentOptionsNotifications(); return new FragmentOptionsBehavior();
case 5: case 5:
return new FragmentOptionsNotifications();
case 6:
return new FragmentOptionsMisc(); return new FragmentOptionsMisc();
default: default:
throw new IllegalArgumentException(); throw new IllegalArgumentException();
@ -92,7 +94,7 @@ public class FragmentOptions extends FragmentBase {
@Override @Override
public int getCount() { public int getCount() {
return 6; return 7;
} }
@Override @Override
@ -101,14 +103,16 @@ public class FragmentOptions extends FragmentBase {
case 0: case 0:
return getString(R.string.title_advanced_section_synchronize); return getString(R.string.title_advanced_section_synchronize);
case 1: case 1:
return getString(R.string.title_advanced_section_connection); return getString(R.string.title_advanced_section_send);
case 2: case 2:
return getString(R.string.title_advanced_section_display); return getString(R.string.title_advanced_section_connection);
case 3: case 3:
return getString(R.string.title_advanced_section_behavior); return getString(R.string.title_advanced_section_display);
case 4: case 4:
return getString(R.string.title_advanced_section_notifications); return getString(R.string.title_advanced_section_behavior);
case 5: case 5:
return getString(R.string.title_advanced_section_notifications);
case 6:
return getString(R.string.title_advanced_section_misc); return getString(R.string.title_advanced_section_misc);
default: default:
throw new IllegalArgumentException(); throw new IllegalArgumentException();

@ -50,12 +50,10 @@ public class FragmentOptionsBehavior extends FragmentBase implements SharedPrefe
private SwitchCompat swAutoResize; private SwitchCompat swAutoResize;
private Spinner spAutoResize; private Spinner spAutoResize;
private TextView tvAutoResize; private TextView tvAutoResize;
private SwitchCompat swPrefixOnce;
private SwitchCompat swAutoSend;
private final static String[] RESET_OPTIONS = new String[]{ private final static String[] RESET_OPTIONS = new String[]{
"pull", "autoscroll", "swipenav", "autoexpand", "autoclose", "autonext", "pull", "autoscroll", "swipenav", "autoexpand", "autoclose", "autonext",
"collapse", "autoread", "automove", "autoresize", "resize", "prefix_once", "autosend" "collapse", "autoread", "automove", "autoresize", "resize"
}; };
@Override @Override
@ -80,8 +78,6 @@ public class FragmentOptionsBehavior extends FragmentBase implements SharedPrefe
swAutoResize = view.findViewById(R.id.swAutoResize); swAutoResize = view.findViewById(R.id.swAutoResize);
spAutoResize = view.findViewById(R.id.spAutoResize); spAutoResize = view.findViewById(R.id.spAutoResize);
tvAutoResize = view.findViewById(R.id.tvAutoResize); tvAutoResize = view.findViewById(R.id.tvAutoResize);
swPrefixOnce = view.findViewById(R.id.swPrefixOnce);
swAutoSend = view.findViewById(R.id.swAutoSend);
setOptions(); 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); PreferenceManager.getDefaultSharedPreferences(getContext()).registerOnSharedPreferenceChangeListener(this);
return view; return view;
@ -254,8 +236,5 @@ public class FragmentOptionsBehavior extends FragmentBase implements SharedPrefe
break; break;
} }
spAutoResize.setEnabled(swAutoResize.isChecked()); spAutoResize.setEnabled(swAutoResize.isChecked());
swPrefixOnce.setChecked(prefs.getBoolean("prefix_once", false));
swAutoSend.setChecked(!prefs.getBoolean("autosend", false));
} }
} }

@ -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 <http://www.gnu.org/licenses/>.
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;
}
}
}

@ -172,26 +172,6 @@
app:layout_constraintBottom_toBottomOf="@id/spAutoResize" app:layout_constraintBottom_toBottomOf="@id/spAutoResize"
app:layout_constraintStart_toEndOf="@id/spAutoResize" app:layout_constraintStart_toEndOf="@id/spAutoResize"
app:layout_constraintTop_toTopOf="@id/spAutoResize" /> app:layout_constraintTop_toTopOf="@id/spAutoResize" />
<androidx.appcompat.widget.SwitchCompat
android:id="@+id/swPrefixOnce"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:text="@string/title_advanced_prefix_once"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/spAutoResize"
app:switchPadding="12dp" />
<androidx.appcompat.widget.SwitchCompat
android:id="@+id/swAutoSend"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:text="@string/title_advanced_autosend"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/swPrefixOnce"
app:switchPadding="12dp" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
</ScrollView> </ScrollView>
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

@ -0,0 +1,64 @@
<?xml version="1.0" encoding="utf-8"?>
<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=".ActivitySetup">
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="12dp">
<androidx.appcompat.widget.SwitchCompat
android:id="@+id/swPrefixOnce"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:text="@string/title_advanced_prefix_once"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:switchPadding="12dp" />
<androidx.appcompat.widget.SwitchCompat
android:id="@+id/swAutoSend"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:text="@string/title_advanced_autosend"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/swPrefixOnce"
app:switchPadding="12dp" />
<TextView
android:id="@+id/tvSendDelayed"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:layout_marginEnd="48dp"
android:text="@string/title_advanced_send_delayed"
android:textAppearance="@style/TextAppearance.AppCompat.Small"
android:textColor="?android:attr/textColorPrimary"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/swAutoSend" />
<Spinner
android:id="@+id/spSendDelayed"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:entries="@array/sendDelayedNames"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tvSendDelayed" />
</androidx.constraintlayout.widget.ConstraintLayout>
</ScrollView>
</androidx.constraintlayout.widget.ConstraintLayout>

@ -154,6 +154,7 @@
<string name="title_advanced">Advanced options</string> <string name="title_advanced">Advanced options</string>
<string name="title_advanced_section_synchronize">Synchronize</string> <string name="title_advanced_section_synchronize">Synchronize</string>
<string name="title_advanced_section_send">Send</string>
<string name="title_advanced_section_connection">Connection</string> <string name="title_advanced_section_connection">Connection</string>
<string name="title_advanced_section_display">Display</string> <string name="title_advanced_section_display">Display</string>
<string name="title_advanced_section_behavior">Behavior</string> <string name="title_advanced_section_behavior">Behavior</string>
@ -199,8 +200,10 @@
<string name="title_advanced_autoresize">Automatically resize attached and embedded images</string> <string name="title_advanced_autoresize">Automatically resize attached and embedded images</string>
<string name="title_advanced_resize_pixels">&lt; %1$d pixels</string> <string name="title_advanced_resize_pixels">&lt; %1$d pixels</string>
<string name="title_advanced_sender">Allow editing sender address</string> <string name="title_advanced_sender">Allow editing sender address</string>
<string name="title_advanced_prefix_once">Prefix subject only once on replying or forwarding</string> <string name="title_advanced_prefix_once">Prefix subject only once on replying or forwarding</string>
<string name="title_advanced_autosend">Confirm sending messages</string> <string name="title_advanced_autosend">Confirm sending messages</string>
<string name="title_advanced_send_delayed">Delay sending messages</string>
<string name="title_advanced_notify_group">Group new message notifications</string> <string name="title_advanced_notify_group">Group new message notifications</string>
<string name="title_advanced_notify_preview">Show message preview in notifications</string> <string name="title_advanced_notify_preview">Show message preview in notifications</string>
@ -470,6 +473,7 @@
<string name="title_draft_saved">Draft saved</string> <string name="title_draft_saved">Draft saved</string>
<string name="title_ask_send_via">Send message to %1$s via %2$s?</string> <string name="title_ask_send_via">Send message to %1$s via %2$s?</string>
<string name="title_queued">Sending message</string> <string name="title_queued">Sending message</string>
<string name="title_queued_at">Message will be sent around %1$s</string>
<string name="title_encrypt">Encrypt</string> <string name="title_encrypt">Encrypt</string>
<string name="title_decrypt">Decrypt</string> <string name="title_decrypt">Decrypt</string>
@ -677,6 +681,26 @@
<item>240</item> <item>240</item>
</integer-array> </integer-array>
<string-array name="sendDelayedNames">
<item>Never</item>
<item>15 seconds</item>
<item>30 seconds</item>
<item>1 minute</item>
<item>2 minutes</item>
<item>5 minutes</item>
<item>10 minutes</item>
</string-array>
<integer-array name="sendDelayedValues" translatable="false">
<item>0</item>
<item>15</item>
<item>30</item>
<item>60</item>
<item>120</item>
<item>300</item>
<item>600</item>
</integer-array>
<string-array name="startupValues" translatable="false"> <string-array name="startupValues" translatable="false">
<item>unified</item> <item>unified</item>
<item>folders</item> <item>folders</item>

Loading…
Cancel
Save