Delay autoclose until after undo move

pull/146/head
M66B 6 years ago
parent bd087e7ab8
commit 7d65e2ee9a

@ -35,7 +35,6 @@ import android.net.NetworkCapabilities;
import android.net.NetworkInfo; import android.net.NetworkInfo;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler;
import android.os.ParcelFileDescriptor; import android.os.ParcelFileDescriptor;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import android.text.TextUtils; import android.text.TextUtils;
@ -128,7 +127,6 @@ public class ActivityView extends ActivityBilling implements FragmentManager.OnB
static final String ACTION_VIEW_MESSAGES = BuildConfig.APPLICATION_ID + ".VIEW_MESSAGES"; static final String ACTION_VIEW_MESSAGES = BuildConfig.APPLICATION_ID + ".VIEW_MESSAGES";
static final String ACTION_VIEW_THREAD = BuildConfig.APPLICATION_ID + ".VIEW_THREAD"; static final String ACTION_VIEW_THREAD = BuildConfig.APPLICATION_ID + ".VIEW_THREAD";
static final String ACTION_VIEW_FULL = BuildConfig.APPLICATION_ID + ".VIEW_FULL"; static final String ACTION_VIEW_FULL = BuildConfig.APPLICATION_ID + ".VIEW_FULL";
static final String ACTION_UNDO_MOVE = BuildConfig.APPLICATION_ID + ".UNDO_MOVE";
static final String ACTION_EDIT_FOLDER = BuildConfig.APPLICATION_ID + ".EDIT_FOLDER"; static final String ACTION_EDIT_FOLDER = BuildConfig.APPLICATION_ID + ".EDIT_FOLDER";
static final String ACTION_EDIT_ANSWER = BuildConfig.APPLICATION_ID + ".EDIT_ANSWER"; static final String ACTION_EDIT_ANSWER = BuildConfig.APPLICATION_ID + ".EDIT_ANSWER";
static final String ACTION_STORE_ATTACHMENT = BuildConfig.APPLICATION_ID + ".STORE_ATTACHMENT"; static final String ACTION_STORE_ATTACHMENT = BuildConfig.APPLICATION_ID + ".STORE_ATTACHMENT";
@ -136,8 +134,6 @@ public class ActivityView extends ActivityBilling implements FragmentManager.OnB
static final String ACTION_SHOW_PRO = BuildConfig.APPLICATION_ID + ".SHOW_PRO"; static final String ACTION_SHOW_PRO = BuildConfig.APPLICATION_ID + ".SHOW_PRO";
static final String ACTION_SHOW_LEGEND = BuildConfig.APPLICATION_ID + ".SHOW_LEGEND"; static final String ACTION_SHOW_LEGEND = BuildConfig.APPLICATION_ID + ".SHOW_LEGEND";
private static final int UNDO_TIMEOUT = 5000; // milliseconds
static final String UPDATE_LATEST_API = "https://api.github.com/repos/M66B/open-source-email/releases/latest"; static final String UPDATE_LATEST_API = "https://api.github.com/repos/M66B/open-source-email/releases/latest";
static final long UPDATE_INTERVAL = 12 * 3600 * 1000L; // milliseconds static final long UPDATE_INTERVAL = 12 * 3600 * 1000L; // milliseconds
@ -363,7 +359,6 @@ public class ActivityView extends ActivityBilling implements FragmentManager.OnB
iff.addAction(ACTION_VIEW_MESSAGES); iff.addAction(ACTION_VIEW_MESSAGES);
iff.addAction(ACTION_VIEW_THREAD); iff.addAction(ACTION_VIEW_THREAD);
iff.addAction(ACTION_VIEW_FULL); iff.addAction(ACTION_VIEW_FULL);
iff.addAction(ACTION_UNDO_MOVE);
iff.addAction(ACTION_EDIT_FOLDER); iff.addAction(ACTION_EDIT_FOLDER);
iff.addAction(ACTION_EDIT_ANSWER); iff.addAction(ACTION_EDIT_ANSWER);
iff.addAction(ACTION_STORE_ATTACHMENT); iff.addAction(ACTION_STORE_ATTACHMENT);
@ -1193,8 +1188,6 @@ public class ActivityView extends ActivityBilling implements FragmentManager.OnB
onViewThread(intent); onViewThread(intent);
else if (ACTION_VIEW_FULL.equals(action)) else if (ACTION_VIEW_FULL.equals(action))
onViewFull(intent); onViewFull(intent);
else if (ACTION_UNDO_MOVE.equals(action))
onUndoMove(intent);
else if (ACTION_EDIT_FOLDER.equals(action)) else if (ACTION_EDIT_FOLDER.equals(action))
onEditFolder(intent); onEditFolder(intent);
else if (ACTION_EDIT_ANSWER.equals(action)) else if (ACTION_EDIT_ANSWER.equals(action))
@ -1261,93 +1254,6 @@ public class ActivityView extends ActivityBilling implements FragmentManager.OnB
fragmentTransaction.commit(); fragmentTransaction.commit();
} }
private void onUndoMove(Intent intent) {
final MessageTarget result = (MessageTarget) intent.getSerializableExtra("target");
// Show undo snackbar
final Snackbar snackbar = Snackbar.make(
getVisibleView(),
getString(R.string.title_moving, result.target.getDisplayName(this)),
Snackbar.LENGTH_INDEFINITE);
snackbar.setAction(R.string.title_undo, new View.OnClickListener() {
@Override
public void onClick(View v) {
snackbar.dismiss();
Bundle args = new Bundle();
args.putSerializable("result", result);
// Show message again
new SimpleTask<Void>() {
@Override
protected Void onLoad(Context context, Bundle args) {
MessageTarget result = (MessageTarget) args.getSerializable("result");
for (long id : result.ids) {
Log.i(Helper.TAG, "Move undo id=" + id);
DB.getInstance(context).message().setMessageUiHide(id, false);
}
return null;
}
@Override
protected void onException(Bundle args, Throwable ex) {
super.onException(args, ex);
}
}.load(ActivityView.this, args);
}
});
snackbar.show();
// Wait
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
Log.i(Helper.TAG, "Move timeout");
// Remove snackbar
if (snackbar.isShown())
snackbar.dismiss();
Bundle args = new Bundle();
args.putSerializable("result", result);
// Process move in a thread
// - the activity could be gone
new SimpleTask<Void>() {
@Override
protected Void onLoad(Context context, Bundle args) {
MessageTarget result = (MessageTarget) args.getSerializable("result");
DB db = DB.getInstance(context);
try {
db.beginTransaction();
for (long id : result.ids) {
EntityMessage message = db.message().getMessage(id);
if (message != null && message.ui_hide) {
Log.i(Helper.TAG, "Move id=" + id + " target=" + result.target.name);
EntityFolder folder = db.folder().getFolderByName(message.account, result.target.name);
EntityOperation.queue(db, message, EntityOperation.MOVE, folder.id);
}
}
db.setTransactionSuccessful();
} finally {
db.endTransaction();
}
return null;
}
@Override
protected void onException(Bundle args, Throwable ex) {
Helper.unexpectedError(ActivityView.this, ActivityView.this, ex);
}
}.load(ActivityView.this, args);
}
}, UNDO_TIMEOUT);
}
private void onEditFolder(Intent intent) { private void onEditFolder(Intent intent) {
FragmentFolder fragment = new FragmentFolder(); FragmentFolder fragment = new FragmentFolder();
fragment.setArguments(intent.getExtras()); fragment.setArguments(intent.getExtras());

@ -27,6 +27,7 @@ import android.graphics.Canvas;
import android.graphics.Color; import android.graphics.Color;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.Log; import android.util.Log;
@ -44,6 +45,7 @@ import com.google.android.material.bottomnavigation.BottomNavigationView;
import com.google.android.material.floatingactionbutton.FloatingActionButton; import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.android.material.snackbar.Snackbar; import com.google.android.material.snackbar.Snackbar;
import java.io.Serializable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -107,6 +109,9 @@ public class FragmentMessages extends FragmentEx {
private List<Long> archives = new ArrayList<>(); private List<Long> archives = new ArrayList<>();
private List<Long> trashes = new ArrayList<>(); private List<Long> trashes = new ArrayList<>();
private boolean moving = false;
private boolean closing = false;
private AdapterMessage.ViewType viewType; private AdapterMessage.ViewType viewType;
private SelectionTracker<Long> selectionTracker = null; private SelectionTracker<Long> selectionTracker = null;
private LiveData<PagedList<TupleMessageEx>> messages = null; private LiveData<PagedList<TupleMessageEx>> messages = null;
@ -122,6 +127,7 @@ public class FragmentMessages extends FragmentEx {
private static final int LOCAL_PAGE_SIZE = 100; private static final int LOCAL_PAGE_SIZE = 100;
private static final int REMOTE_PAGE_SIZE = 10; private static final int REMOTE_PAGE_SIZE = 10;
private static final int UNDO_TIMEOUT = 5000; // milliseconds
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
@ -341,6 +347,8 @@ public class FragmentMessages extends FragmentEx {
@Override @Override
public void move(long id, String name, boolean type) { public void move(long id, String name, boolean type) {
moving = true;
Bundle args = new Bundle(); Bundle args = new Bundle();
args.putLong("id", id); args.putLong("id", id);
args.putString("name", name); args.putString("name", name);
@ -509,6 +517,8 @@ public class FragmentMessages extends FragmentEx {
return; return;
Log.i(Helper.TAG, "Swiped dir=" + direction + " message=" + message.id); Log.i(Helper.TAG, "Swiped dir=" + direction + " message=" + message.id);
moving = true;
Bundle args = new Bundle(); Bundle args = new Bundle();
args.putLong("id", message.id); args.putLong("id", message.id);
args.putBoolean("thread", viewType != AdapterMessage.ViewType.THREAD); args.putBoolean("thread", viewType != AdapterMessage.ViewType.THREAD);
@ -601,6 +611,8 @@ public class FragmentMessages extends FragmentEx {
} }
private void onActionMove(String folderType) { private void onActionMove(String folderType) {
moving = true;
Bundle args = new Bundle(); Bundle args = new Bundle();
args.putLong("account", account); args.putLong("account", account);
args.putString("thread", thread); args.putString("thread", thread);
@ -974,6 +986,8 @@ public class FragmentMessages extends FragmentEx {
} }
private void onActionMove(String type) { private void onActionMove(String type) {
moving = true;
Bundle args = new Bundle(); Bundle args = new Bundle();
args.putString("type", type); args.putString("type", type);
args.putLongArray("ids", getSelection()); args.putLongArray("ids", getSelection());
@ -1066,6 +1080,8 @@ public class FragmentMessages extends FragmentEx {
popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() { popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
@Override @Override
public boolean onMenuItemClick(final MenuItem target) { public boolean onMenuItemClick(final MenuItem target) {
moving = true;
args.putLong("target", target.getItemId()); args.putLong("target", target.getItemId());
selectionTracker.clearSelection(); selectionTracker.clearSelection();
@ -1616,9 +1632,13 @@ public class FragmentMessages extends FragmentEx {
public void onChanged(@Nullable PagedList<TupleMessageEx> messages) { public void onChanged(@Nullable PagedList<TupleMessageEx> messages) {
if (messages == null || if (messages == null ||
(viewType == AdapterMessage.ViewType.THREAD && messages.size() == 0 && autoclose)) { (viewType == AdapterMessage.ViewType.THREAD && messages.size() == 0 && autoclose)) {
if (moving)
closing = true;
else {
finish(); finish();
return; return;
} }
}
if (viewType == AdapterMessage.ViewType.THREAD) { if (viewType == AdapterMessage.ViewType.THREAD) {
if (autoExpand) { if (autoExpand) {
@ -1688,7 +1708,12 @@ public class FragmentMessages extends FragmentEx {
// - no more non archived/trashed/outgoing messages // - no more non archived/trashed/outgoing messages
if (count == 0) if (count == 0)
if (moving)
closing = true;
else {
finish(); finish();
return;
}
} }
} }
} else { } else {
@ -1753,11 +1778,82 @@ public class FragmentMessages extends FragmentEx {
}.load(this, args); }.load(this, args);
} }
private void moveUndo(MessageTarget target) { private void moveUndo(final MessageTarget result) {
LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(getContext()); // Show undo snackbar
lbm.sendBroadcast( final Snackbar snackbar = Snackbar.make(
new Intent(ActivityView.ACTION_UNDO_MOVE) view,
.putExtra("target", target)); getString(R.string.title_moving, result.target.getDisplayName(getContext())),
Snackbar.LENGTH_INDEFINITE);
snackbar.setAction(R.string.title_undo, new View.OnClickListener() {
@Override
public void onClick(View v) {
snackbar.dismiss();
moving = false;
closing = false;
Bundle args = new Bundle();
args.putSerializable("result", result);
// Show message again
new SimpleTask<Void>() {
@Override
protected Void onLoad(Context context, Bundle args) {
MessageTarget result = (MessageTarget) args.getSerializable("result");
for (long id : result.ids) {
Log.i(Helper.TAG, "Move undo id=" + id);
DB.getInstance(context).message().setMessageUiHide(id, false);
}
return null;
}
@Override
protected void onException(Bundle args, Throwable ex) {
super.onException(args, ex);
}
}.load(FragmentMessages.this, args);
}
});
snackbar.show();
// Wait
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
Log.i(Helper.TAG, "Move timeout");
moving = false;
if (closing)
finish();
// Remove snackbar
if (snackbar.isShown())
snackbar.dismiss();
final DB db = DB.getInstance(getContext());
new Thread(new Runnable() {
@Override
public void run() {
try {
db.beginTransaction();
for (long id : result.ids) {
EntityMessage message = db.message().getMessage(id);
if (message != null && message.ui_hide) {
Log.i(Helper.TAG, "Move id=" + id + " target=" + result.target.name);
EntityFolder folder = db.folder().getFolderByName(message.account, result.target.name);
EntityOperation.queue(db, message, EntityOperation.MOVE, folder.id);
}
}
db.setTransactionSuccessful();
} finally {
db.endTransaction();
}
}
}).start();
}
}, UNDO_TIMEOUT);
} }
private ActivityBase.IBackPressedListener onBackPressedListener = new ActivityBase.IBackPressedListener() { private ActivityBase.IBackPressedListener onBackPressedListener = new ActivityBase.IBackPressedListener() {
@ -1770,4 +1866,9 @@ public class FragmentMessages extends FragmentEx {
return false; return false;
} }
}; };
class MessageTarget implements Serializable {
List<Long> ids = new ArrayList<>();
EntityFolder target;
}
} }

@ -1,10 +0,0 @@
package eu.faircode.email;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
class MessageTarget implements Serializable {
List<Long> ids = new ArrayList<>();
EntityFolder target;
}
Loading…
Cancel
Save