From 0d33077b194e3958eb81db95bca51355a7f95185 Mon Sep 17 00:00:00 2001 From: M66B Date: Sun, 30 Jun 2019 17:44:53 +0200 Subject: [PATCH] Use dialog fragment to select folder/duration --- .../eu/faircode/email/AdapterMessage.java | 62 +- .../java/eu/faircode/email/DialogFolder.java | 101 ---- .../eu/faircode/email/FragmentCompose.java | 84 +-- ...logDuration.java => FragmentDuration.java} | 64 +- .../eu/faircode/email/FragmentMessages.java | 555 ++++++++++-------- .../faircode/email/FragmentSelectFolder.java | 142 +++++ .../java/eu/faircode/email/TwoStateOwner.java | 4 + 7 files changed, 565 insertions(+), 447 deletions(-) delete mode 100644 app/src/main/java/eu/faircode/email/DialogFolder.java rename app/src/main/java/eu/faircode/email/{DialogDuration.java => FragmentDuration.java} (65%) create mode 100644 app/src/main/java/eu/faircode/email/FragmentSelectFolder.java diff --git a/app/src/main/java/eu/faircode/email/AdapterMessage.java b/app/src/main/java/eu/faircode/email/AdapterMessage.java index d05eb8ea55..ff5cd01772 100644 --- a/app/src/main/java/eu/faircode/email/AdapterMessage.java +++ b/app/src/main/java/eu/faircode/email/AdapterMessage.java @@ -3079,55 +3079,21 @@ public class AdapterMessage extends RecyclerView.Adapter() { - @Override - protected Void onExecute(Context context, Bundle args) { - long id = args.getLong("id"); - long target = args.getLong("target"); - - DB db = DB.getInstance(context); - try { - db.beginTransaction(); - - EntityMessage message = db.message().getMessage(id); - if (message == null) - return null; - - EntityOperation.queue(context, message, EntityOperation.COPY, target); - - db.setTransactionSuccessful(); - } finally { - db.endTransaction(); - } - - return null; - } + Bundle args = new Bundle(); + args.putString("title", context.getString(copy ? R.string.title_copy_to : R.string.title_move_to_folder)); + args.putLong("account", message.account); + args.putLongArray("disabled", new long[]{message.folder}); + args.putLong("message", message.id); + args.putBoolean("copy", copy); - @Override - protected void onException(Bundle args, Throwable ex) { - Helper.unexpectedError(context, owner, ex); - } - }.execute(context, owner, args, "message:copy"); - } else - properties.move(message.id, folder.name, false); - } - }); + FragmentSelectFolder fragment = new FragmentSelectFolder(); + fragment.setArguments(args); + fragment.setTargetFragment(parentFragment, FragmentMessages.REQUEST_MESSAGE_MOVE); + fragment.show(parentFragment.getFragmentManager(), "message:move"); } private void onActionMoveOutbox(ActionData data) { @@ -3195,11 +3161,11 @@ public class AdapterMessage extends RecyclerView.Adapter. - - Copyright 2018-2019 by Marcel Bokhorst (M66B) -*/ - -import android.app.Dialog; -import android.content.Context; -import android.os.Bundle; -import android.view.LayoutInflater; -import android.view.View; - -import androidx.lifecycle.LifecycleOwner; -import androidx.recyclerview.widget.LinearLayoutManager; -import androidx.recyclerview.widget.RecyclerView; - -import java.util.ArrayList; -import java.util.List; - -public class DialogFolder { - static void show( - final Context context, final LifecycleOwner owner, View parentView, int title, - long account, final List disabled, - final IDialogFolder intf) { - final View dview = LayoutInflater.from(context).inflate(R.layout.dialog_folder_select, null); - final RecyclerView rvFolder = dview.findViewById(R.id.rvFolder); - final ContentLoadingProgressBar pbWait = dview.findViewById(R.id.pbWait); - - final Dialog dialog = new DialogBuilderLifecycle(context, owner) - .setTitle(title) - .setView(dview) - .create(); - - rvFolder.setHasFixedSize(false); - LinearLayoutManager llm = new LinearLayoutManager(context); - rvFolder.setLayoutManager(llm); - - final AdapterFolder adapter = new AdapterFolder(context, owner, parentView, account, false, - new AdapterFolder.IFolderSelectedListener() { - @Override - public void onFolderSelected(TupleFolderEx folder) { - dialog.dismiss(); - intf.onFolderSelected(folder); - } - }); - - rvFolder.setAdapter(adapter); - - rvFolder.setVisibility(View.GONE); - pbWait.setVisibility(View.VISIBLE); - dialog.show(); - - Bundle args = new Bundle(); - args.putLong("account", account); - - new SimpleTask>() { - @Override - protected List onExecute(Context context, Bundle args) { - long account = args.getLong("account"); - - DB db = DB.getInstance(context); - return db.folder().getFoldersEx(account); - } - - @Override - protected void onExecuted(final Bundle args, List folders) { - if (folders == null) - folders = new ArrayList<>(); - - adapter.setDisabled(disabled); - adapter.set(folders); - pbWait.setVisibility(View.GONE); - rvFolder.setVisibility(View.VISIBLE); - } - - @Override - protected void onException(Bundle args, Throwable ex) { - Helper.unexpectedError(context, owner, ex); - } - }.execute(context, owner, args, "folder:select"); - } - - interface IDialogFolder { - void onFolderSelected(TupleFolderEx folder); - } -} diff --git a/app/src/main/java/eu/faircode/email/FragmentCompose.java b/app/src/main/java/eu/faircode/email/FragmentCompose.java index 80a01c6a49..1f10bebd57 100644 --- a/app/src/main/java/eu/faircode/email/FragmentCompose.java +++ b/app/src/main/java/eu/faircode/email/FragmentCompose.java @@ -214,6 +214,7 @@ public class FragmentCompose extends FragmentBase { private static final int REQUEST_RECORD_AUDIO = 7; private static final int REQUEST_ENCRYPT = 8; private static final int REQUEST_COLOR = 9; + private static final int REQUEST_SEND_AFTER = 10; @Override public void onCreate(Bundle savedInstanceState) { @@ -1079,44 +1080,13 @@ public class FragmentCompose extends FragmentBase { } private void onMenuSendAfter() { - DialogDuration.show(getContext(), getViewLifecycleOwner(), R.string.title_send_at, - new DialogDuration.IDialogDuration() { - @Override - public void onDurationSelected(long duration, long time) { - if (!Helper.isPro(getContext())) { - LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(getContext()); - lbm.sendBroadcast(new Intent(ActivityCompose.ACTION_SHOW_PRO)); - return; - } - - Bundle args = new Bundle(); - args.putLong("id", working); - args.putLong("wakeup", time); - - new SimpleTask() { - @Override - protected Void onExecute(Context context, Bundle args) { - long id = args.getLong("id"); - Long wakeup = args.getLong("wakeup"); - - DB db = DB.getInstance(context); - db.message().setMessageSnoozed(id, wakeup); - - return null; - } - - @Override - protected void onExecuted(Bundle args, Void data) { - onAction(R.id.action_send); - } + Bundle args = new Bundle(); + args.putString("title", getString(R.string.title_send_at)); - @Override - protected void onException(Bundle args, Throwable ex) { - Helper.unexpectedError(getContext(), getViewLifecycleOwner(), ex); - } - }.execute(FragmentCompose.this, args, "compose:send:after"); - } - }); + FragmentDuration fragment = new FragmentDuration(); + fragment.setArguments(args); + fragment.setTargetFragment(this, REQUEST_SEND_AFTER); + fragment.show(getFragmentManager(), "send:after"); } private void onActionRecordAudio() { @@ -1602,12 +1572,52 @@ public class FragmentCompose extends FragmentBase { etBody.setSelection(end); } break; + case REQUEST_SEND_AFTER: + if (resultCode == RESULT_OK && data != null) { + Bundle args = data.getBundleExtra("args"); + onSendAfter(args.getLong("time")); + } default: if (resultCode == RESULT_OK && data != null) handlePickContact(requestCode, data); } } + private void onSendAfter(long time) { + if (!Helper.isPro(getContext())) { + LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(getContext()); + lbm.sendBroadcast(new Intent(ActivityCompose.ACTION_SHOW_PRO)); + return; + } + + Bundle args = new Bundle(); + args.putLong("id", working); + args.putLong("wakeup", time); + + new SimpleTask() { + @Override + protected Void onExecute(Context context, Bundle args) { + long id = args.getLong("id"); + Long wakeup = args.getLong("wakeup"); + + DB db = DB.getInstance(context); + db.message().setMessageSnoozed(id, wakeup); + + return null; + } + + @Override + protected void onExecuted(Bundle args, Void data) { + onAction(R.id.action_send); + } + + @Override + protected void onException(Bundle args, Throwable ex) { + Helper.unexpectedError(getContext(), getViewLifecycleOwner(), ex); + } + }.execute(FragmentCompose.this, args, "compose:send:after"); + } + private void handlePickContact(int requestCode, Intent data) { Uri uri = data.getData(); if (uri == null) diff --git a/app/src/main/java/eu/faircode/email/DialogDuration.java b/app/src/main/java/eu/faircode/email/FragmentDuration.java similarity index 65% rename from app/src/main/java/eu/faircode/email/DialogDuration.java rename to app/src/main/java/eu/faircode/email/FragmentDuration.java index 11bfc0374e..3116b0f2f8 100644 --- a/app/src/main/java/eu/faircode/email/DialogDuration.java +++ b/app/src/main/java/eu/faircode/email/FragmentDuration.java @@ -19,37 +19,60 @@ package eu.faircode.email; Copyright 2018-2019 by Marcel Bokhorst (M66B) */ -import android.content.Context; +import android.app.AlertDialog; +import android.app.Dialog; import android.content.DialogInterface; +import android.content.Intent; import android.os.Build; +import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.widget.DatePicker; import android.widget.TextView; import android.widget.TimePicker; -import androidx.lifecycle.LifecycleOwner; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.DialogFragment; +import androidx.fragment.app.Fragment; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; -public class DialogDuration { - static void show(Context context, LifecycleOwner owner, int title, final IDialogDuration intf) { - final View dview = LayoutInflater.from(context).inflate(R.layout.dialog_duration, null); +import static android.app.Activity.RESULT_CANCELED; +import static android.app.Activity.RESULT_OK; + +public class FragmentDuration extends DialogFragment { + private Calendar cal = Calendar.getInstance(); + + @Override + public void onSaveInstanceState(@NonNull Bundle outState) { + outState.putLong("fair:time", cal.getTimeInMillis()); + super.onSaveInstanceState(outState); + } + + @NonNull + @Override + public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) { + String title = getArguments().getString("title"); + + final View dview = LayoutInflater.from(getContext()).inflate(R.layout.dialog_duration, null); final TextView tvDuration = dview.findViewById(R.id.tvDuration); final TimePicker timePicker = dview.findViewById(R.id.timePicker); final DatePicker datePicker = dview.findViewById(R.id.datePicker); - final Calendar cal = Calendar.getInstance(); - cal.setTimeInMillis((new Date().getTime() / (3600 * 1000L) + 1) * (3600 * 1000L)); + if (savedInstanceState == null) + cal.setTimeInMillis((new Date().getTime() / (3600 * 1000L) + 1) * (3600 * 1000L)); + else + cal.setTimeInMillis(savedInstanceState.getLong("fair:time")); Log.i("Set init=" + new Date(cal.getTimeInMillis())); final DateFormat df = SimpleDateFormat.getDateTimeInstance(SimpleDateFormat.FULL, SimpleDateFormat.SHORT); tvDuration.setText(df.format(cal.getTime())); - timePicker.setIs24HourView(android.text.format.DateFormat.is24HourFormat(context)); + timePicker.setIs24HourView(android.text.format.DateFormat.is24HourFormat(getContext())); if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { timePicker.setCurrentHour(cal.get(Calendar.HOUR_OF_DAY)); timePicker.setCurrentMinute(cal.get(Calendar.MINUTE)); @@ -86,7 +109,7 @@ public class DialogDuration { } ); - new DialogBuilderLifecycle(context, owner) + return new AlertDialog.Builder(getContext()) .setTitle(title) .setView(dview) .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { @@ -97,13 +120,28 @@ public class DialogDuration { if (duration < 0) duration = 0; Log.i("Set duration=" + duration + " time=" + new Date(cal.getTimeInMillis())); - intf.onDurationSelected(duration, cal.getTimeInMillis()); + sendResult(RESULT_OK, duration, cal.getTimeInMillis()); } }) - .show(); + .setOnDismissListener(new DialogInterface.OnDismissListener() { + @Override + public void onDismiss(DialogInterface dialogInterface) { + sendResult(RESULT_CANCELED, 0, 0); + } + }) + .create(); } - interface IDialogDuration { - void onDurationSelected(long duration, long time); + private void sendResult(int result, long duration, long time) { + Bundle args = getArguments(); + args.putLong("duration", duration); + args.putLong("time", time); + + Fragment target = getTargetFragment(); + if (target != null) { + Intent data = new Intent(); + data.putExtra("args", args); + target.onActivityResult(getTargetRequestCode(), result, data); + } } } diff --git a/app/src/main/java/eu/faircode/email/FragmentMessages.java b/app/src/main/java/eu/faircode/email/FragmentMessages.java index 3dde508e5f..bfe968a231 100644 --- a/app/src/main/java/eu/faircode/email/FragmentMessages.java +++ b/app/src/main/java/eu/faircode/email/FragmentMessages.java @@ -230,6 +230,11 @@ public class FragmentMessages extends FragmentBase implements SharedPreferences. private static final int REQUEST_MOVE_ACROSS = 8; static final int REQUEST_MESSAGE_COLOR = 9; private static final int REQUEST_MESSAGES_COLOR = 10; + private static final int REQUEST_MESSAGE_SNOOZE = 11; + private static final int REQUEST_MESSAGES_SNOOZE = 12; + static final int REQUEST_MESSAGE_MOVE = 13; + private static final int REQUEST_MESSAGES_MOVE = 14; + private static final int REQUEST_SEARCH = 15; static final String ACTION_STORE_RAW = BuildConfig.APPLICATION_ID + ".STORE_RAW"; static final String ACTION_STORE_ATTACHMENT = BuildConfig.APPLICATION_ID + ".STORE_ATTACHMENT"; @@ -559,6 +564,78 @@ public class FragmentMessages extends FragmentBase implements SharedPreferences. return false; } } + + private void onActionMove(String folderType) { + Bundle args = new Bundle(); + args.putLong("account", account); + args.putString("thread", thread); + args.putLong("id", id); + args.putString("type", folderType); + + new SimpleTask>() { + @Override + protected ArrayList onExecute(Context context, Bundle args) { + long aid = args.getLong("account"); + String thread = args.getString("thread"); + long id = args.getLong("id"); + String type = args.getString("type"); + + ArrayList result = new ArrayList<>(); + + DB db = DB.getInstance(context); + try { + db.beginTransaction(); + + EntityFolder target = db.folder().getFolderByType(aid, type); + if (target != null) { + EntityAccount account = db.account().getAccount(target.account); + List messages = db.message().getMessageByThread( + aid, thread, threading ? null : id, null); + for (EntityMessage threaded : messages) { + EntityFolder folder = db.folder().getFolder(threaded.folder); + if (!target.id.equals(threaded.folder) && + !EntityFolder.DRAFTS.equals(folder.type) && + !EntityFolder.OUTBOX.equals(folder.type) && + (!EntityFolder.SENT.equals(folder.type) || EntityFolder.TRASH.equals(target.type)) && + !EntityFolder.TRASH.equals(folder.type) && + !EntityFolder.JUNK.equals(folder.type)) + result.add(new MessageTarget(threaded, account, target)); + } + } + + db.setTransactionSuccessful(); + } finally { + db.endTransaction(); + } + + return result; + } + + @Override + protected void onExecuted(Bundle args, ArrayList result) { + moveAsk(result); + } + + @Override + protected void onException(Bundle args, Throwable ex) { + Helper.unexpectedError(getContext(), getViewLifecycleOwner(), ex); + } + }.execute(FragmentMessages.this, args, "messages:move"); + } + + private void onActionSnooze() { + Bundle args = new Bundle(); + args.putString("title", getString(R.string.title_snooze)); + args.putLong("account", account); + args.putString("thread", thread); + args.putLong("id", id); + args.putBoolean("finish", true); + + FragmentDuration fragment = new FragmentDuration(); + fragment.setArguments(args); + fragment.setTargetFragment(FragmentMessages.this, REQUEST_MESSAGE_SNOOZE); + fragment.show(getFragmentManager(), "message:snooze"); + } }); fab.setOnClickListener(new View.OnClickListener() { @@ -641,21 +718,16 @@ public class FragmentMessages extends FragmentBase implements SharedPreferences. if (intent == null) return false; - long account = intent.getLongExtra("account", -1); - DialogFolder.show( - getContext(), getViewLifecycleOwner(), view, - R.string.title_search_in, - account, - new ArrayList(), - new DialogFolder.IDialogFolder() { - @Override - public void onFolderSelected(TupleFolderEx folder) { - search( - getContext(), getViewLifecycleOwner(), getFragmentManager(), - folder.id, true, query); - } - } - ); + Bundle args = new Bundle(); + args.putString("title", getString(R.string.title_move_to_folder)); + args.putLong("account", intent.getLongExtra("account", -1)); + args.putLongArray("disabled", new long[]{}); + args.putString("query", query); + + FragmentSelectFolder fragment = new FragmentSelectFolder(); + fragment.setArguments(args); + fragment.setTargetFragment(FragmentMessages.this, FragmentMessages.REQUEST_SEARCH); + fragment.show(getFragmentManager(), "messages:search"); return true; } @@ -1035,18 +1107,16 @@ public class FragmentMessages extends FragmentBase implements SharedPreferences. } @Override - public void move(long id, String name, boolean type) { + public void move(long id, String type) { Bundle args = new Bundle(); args.putLong("id", id); - args.putString("name", name); - args.putBoolean("type", type); + args.putString("type", type); new SimpleTask>() { @Override protected ArrayList onExecute(Context context, Bundle args) { long id = args.getLong("id"); - String name = args.getString("name"); - boolean type = args.getBoolean("type"); + String type = args.getString("type"); ArrayList result = new ArrayList<>(); @@ -1058,10 +1128,7 @@ public class FragmentMessages extends FragmentBase implements SharedPreferences. EntityFolder target = null; if (message != null) - if (type) - target = db.folder().getFolderByType(message.account, name); - else - target = db.folder().getFolderByName(message.account, name); + target = db.folder().getFolderByType(message.account, type); if (target != null) { EntityAccount account = db.account().getAccount(target.account); @@ -1078,10 +1145,7 @@ public class FragmentMessages extends FragmentBase implements SharedPreferences. @Override protected void onExecuted(Bundle args, ArrayList result) { - if (args.getBoolean("type")) - moveAsk(result); - else - moveAskConfirmed(result); + moveAsk(result); } @Override @@ -1243,7 +1307,7 @@ public class FragmentMessages extends FragmentBase implements SharedPreferences. onActionSeenSelection(false, message.id); return true; case R.string.title_snooze: - onActionSnoozeSelection(message.id); + onMenuSnooze(); return true; case R.string.title_flag_color: onMenuColor(); @@ -1256,6 +1320,20 @@ public class FragmentMessages extends FragmentBase implements SharedPreferences. } } + private void onMenuSnooze() { + Bundle args = new Bundle(); + args.putString("title", getString(R.string.title_snooze)); + args.putLong("account", message.account); + args.putString("thread", message.thread); + args.putLong("id", message.id); + args.putBoolean("finish", false); + + FragmentDuration fragment = new FragmentDuration(); + fragment.setArguments(args); + fragment.setTargetFragment(FragmentMessages.this, REQUEST_MESSAGE_SNOOZE); + fragment.show(getFragmentManager(), "message:snooze"); + } + private void onMenuColor() { int color = (message.color == null ? Color.TRANSPARENT : message.color); @@ -1270,31 +1348,16 @@ public class FragmentMessages extends FragmentBase implements SharedPreferences. private void onMenuMove() { Bundle args = new Bundle(); + args.putString("title", getString(R.string.title_move_to_folder)); args.putLong("account", message.account); - - new SimpleTask>() { - @Override - protected List onExecute(Context context, Bundle args) { - long account = args.getLong("account"); - - DB db = DB.getInstance(context); - return db.folder().getFoldersEx(account); - } - - @Override - protected void onExecuted(Bundle args, List folders) { - onActionMoveSelectionAccount( - message.account, - folders, - Arrays.asList(new Long[]{message.folder}), - message.id); - } - - @Override - protected void onException(Bundle args, Throwable ex) { - Helper.unexpectedError(getContext(), getViewLifecycleOwner(), ex); - } - }.execute(getContext(), getViewLifecycleOwner(), args, "message:move"); + args.putLongArray("disabled", new long[]{message.folder}); + args.putLong("message", message.id); + args.putBoolean("copy", false); + + FragmentSelectFolder fragment = new FragmentSelectFolder(); + fragment.setArguments(args); + fragment.setTargetFragment(FragmentMessages.this, FragmentMessages.REQUEST_MESSAGE_MOVE); + fragment.show(getFragmentManager(), "message:move"); } }); @@ -1384,126 +1447,6 @@ public class FragmentMessages extends FragmentBase implements SharedPreferences. } }; - private void onActionMove(String folderType) { - Bundle args = new Bundle(); - args.putLong("account", account); - args.putString("thread", thread); - args.putLong("id", id); - args.putString("type", folderType); - - new SimpleTask>() { - @Override - protected ArrayList onExecute(Context context, Bundle args) { - long aid = args.getLong("account"); - String thread = args.getString("thread"); - long id = args.getLong("id"); - String type = args.getString("type"); - - ArrayList result = new ArrayList<>(); - - DB db = DB.getInstance(context); - try { - db.beginTransaction(); - - EntityFolder target = db.folder().getFolderByType(aid, type); - if (target != null) { - EntityAccount account = db.account().getAccount(target.account); - List messages = db.message().getMessageByThread( - aid, thread, threading ? null : id, null); - for (EntityMessage threaded : messages) { - EntityFolder folder = db.folder().getFolder(threaded.folder); - if (!target.id.equals(threaded.folder) && - !EntityFolder.DRAFTS.equals(folder.type) && - !EntityFolder.OUTBOX.equals(folder.type) && - (!EntityFolder.SENT.equals(folder.type) || EntityFolder.TRASH.equals(target.type)) && - !EntityFolder.TRASH.equals(folder.type) && - !EntityFolder.JUNK.equals(folder.type)) - result.add(new MessageTarget(threaded, account, target)); - } - } - - db.setTransactionSuccessful(); - } finally { - db.endTransaction(); - } - - return result; - } - - @Override - protected void onExecuted(Bundle args, ArrayList result) { - moveAsk(result); - } - - @Override - protected void onException(Bundle args, Throwable ex) { - Helper.unexpectedError(getContext(), getViewLifecycleOwner(), ex); - } - }.execute(FragmentMessages.this, args, "messages:move"); - } - - private void onActionSnooze() { - DialogDuration.show(getContext(), getViewLifecycleOwner(), R.string.title_snooze, - new DialogDuration.IDialogDuration() { - @Override - public void onDurationSelected(long duration, long time) { - if (!Helper.isPro(getContext())) { - LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(getContext()); - lbm.sendBroadcast(new Intent(ActivityView.ACTION_SHOW_PRO)); - return; - } - - Bundle args = new Bundle(); - args.putLong("account", account); - args.putString("thread", thread); - args.putLong("id", id); - args.putLong("wakeup", duration == 0 ? -1 : time); - - new SimpleTask() { - @Override - protected Long onExecute(Context context, Bundle args) { - long account = args.getLong("account"); - String thread = args.getString("thread"); - long id = args.getLong("id"); - Long wakeup = args.getLong("wakeup"); - if (wakeup < 0) - wakeup = null; - - DB db = DB.getInstance(context); - try { - db.beginTransaction(); - - List messages = db.message().getMessageByThread( - account, thread, threading ? null : id, null); - for (EntityMessage threaded : messages) { - db.message().setMessageSnoozed(threaded.id, wakeup); - EntityMessage.snooze(context, threaded.id, wakeup); - EntityOperation.queue(context, threaded, EntityOperation.SEEN, true); - } - - db.setTransactionSuccessful(); - } finally { - db.endTransaction(); - } - - return wakeup; - } - - @Override - protected void onExecuted(Bundle args, Long wakeup) { - if (wakeup != null) - finish(); - } - - @Override - protected void onException(Bundle args, Throwable ex) { - Helper.unexpectedError(getContext(), getViewLifecycleOwner(), ex); - } - }.execute(getContext(), getViewLifecycleOwner(), args, "message:snooze"); - } - }); - } - private void onMore() { Bundle args = new Bundle(); args.putLongArray("ids", getSelection()); @@ -1567,9 +1510,6 @@ public class FragmentMessages extends FragmentBase implements SharedPreferences. result.accounts = db.account().getSynchronizingAccounts(); - for (EntityAccount account : result.accounts) - result.targets.put(account.id, db.folder().getFoldersEx(account.id)); - return result; } @@ -1622,7 +1562,7 @@ public class FragmentMessages extends FragmentBase implements SharedPreferences. onActionSeenSelection(false, null); return true; case R.string.title_snooze: - onActionSnoozeSelection(null); + onActionSnoozeSelection(); return true; case R.string.title_flag: onActionFlagSelection(true, null); @@ -1647,7 +1587,7 @@ public class FragmentMessages extends FragmentBase implements SharedPreferences. return true; case R.string.title_move_to_account: long account = target.getIntent().getLongExtra("account", -1); - onActionMoveSelectionAccount(account, result.targets.get(account), result.folders, null); + onActionMoveSelectionAccount(account, result.folders); return true; default: return false; @@ -1718,63 +1658,14 @@ public class FragmentMessages extends FragmentBase implements SharedPreferences. }.execute(FragmentMessages.this, args, "messages:seen"); } - private void onActionSnoozeSelection(final Long id) { - DialogDuration.show(getContext(), getViewLifecycleOwner(), R.string.title_snooze, - new DialogDuration.IDialogDuration() { - @Override - public void onDurationSelected(long duration, long time) { - if (!Helper.isPro(getContext())) { - LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(getContext()); - lbm.sendBroadcast(new Intent(ActivityView.ACTION_SHOW_PRO)); - return; - } - - Bundle args = new Bundle(); - args.putLongArray("ids", id == null ? getSelection() : new long[]{id}); - args.putLong("wakeup", duration == 0 ? -1 : time); - - selectionTracker.clearSelection(); - - new SimpleTask() { - @Override - protected Void onExecute(Context context, Bundle args) { - long[] ids = args.getLongArray("ids"); - Long wakeup = args.getLong("wakeup"); - if (wakeup < 0) - wakeup = null; - - DB db = DB.getInstance(context); - try { - db.beginTransaction(); - - for (long id : ids) { - EntityMessage message = db.message().getMessage(id); - if (message != null) { - List messages = db.message().getMessageByThread( - message.account, message.thread, threading ? null : id, message.folder); - for (EntityMessage threaded : messages) { - db.message().setMessageSnoozed(threaded.id, wakeup); - EntityMessage.snooze(context, threaded.id, wakeup); - EntityOperation.queue(context, threaded, EntityOperation.SEEN, true); - } - } - } - - db.setTransactionSuccessful(); - } finally { - db.endTransaction(); - } - - return null; - } + private void onActionSnoozeSelection() { + Bundle args = new Bundle(); + args.putString("title", getString(R.string.title_snooze)); - @Override - protected void onException(Bundle args, Throwable ex) { - Helper.unexpectedError(getContext(), getViewLifecycleOwner(), ex); - } - }.execute(FragmentMessages.this, args, "messages:snooze"); - } - }); + FragmentDuration fragment = new FragmentDuration(); + fragment.setArguments(args); + fragment.setTargetFragment(this, REQUEST_MESSAGES_SNOOZE); + fragment.show(getFragmentManager(), "messages:snooze"); } private void onActionFlagSelection(boolean flagged, Integer color) { @@ -1947,22 +1838,21 @@ public class FragmentMessages extends FragmentBase implements SharedPreferences. }.execute(FragmentMessages.this, args, "messages:move"); } - private void onActionMoveSelectionAccount(long account, List folders, List disabled, final Long id) { - DialogFolder.show( - getContext(), getViewLifecycleOwner(), view, - R.string.title_move_to_folder, - account, disabled, - new DialogFolder.IDialogFolder() { - @Override - public void onFolderSelected(TupleFolderEx folder) { - onActionMoveSelection(folder.id, id); - } - }); + private void onActionMoveSelectionAccount(long account, List disabled) { + Bundle args = new Bundle(); + args.putString("title", getString(R.string.title_move_to_folder)); + args.putLong("account", account); + args.putLongArray("disabled", Helper.toLongArray(disabled)); + + FragmentSelectFolder fragment = new FragmentSelectFolder(); + fragment.setArguments(args); + fragment.setTargetFragment(FragmentMessages.this, FragmentMessages.REQUEST_MESSAGES_MOVE); + fragment.show(getFragmentManager(), "messages:move"); } - private void onActionMoveSelection(long target, Long id) { + private void onActionMoveSelection(long target) { Bundle args = new Bundle(); - args.putLongArray("ids", id == null ? getSelection() : new long[]{id}); + args.putLongArray("ids", getSelection()); args.putLong("target", target); new SimpleTask>() { @@ -3688,6 +3578,32 @@ public class FragmentMessages extends FragmentBase implements SharedPreferences. onActionFlagSelection(true, color); } break; + case REQUEST_MESSAGE_SNOOZE: + if (resultCode == RESULT_OK && data != null) + onSnooze(data.getBundleExtra("args")); + break; + case REQUEST_MESSAGES_SNOOZE: + if (resultCode == RESULT_OK && data != null) + onSnoozeSelection(data.getBundleExtra("args")); + break; + case REQUEST_MESSAGE_MOVE: + if (resultCode == RESULT_OK && data != null) + onMove(data.getBundleExtra("args")); + break; + case REQUEST_MESSAGES_MOVE: + if (resultCode == RESULT_OK && data != null) { + Bundle args = data.getBundleExtra("args"); + onActionMoveSelection(args.getLong("folder")); + } + break; + case REQUEST_SEARCH: + if (resultCode == RESULT_OK && data != null) { + Bundle args = data.getBundleExtra("args"); + search( + getContext(), getViewLifecycleOwner(), getFragmentManager(), + args.getLong("folder"), true, args.getString("query")); + } + break; } } @@ -3727,6 +3643,150 @@ public class FragmentMessages extends FragmentBase implements SharedPreferences. }.execute(FragmentMessages.this, args, "messages:delete:execute"); } + private void onSnooze(Bundle args) { + if (!Helper.isPro(getContext())) { + LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(getContext()); + lbm.sendBroadcast(new Intent(ActivityView.ACTION_SHOW_PRO)); + return; + } + + long duration = args.getLong("duration"); + long time = args.getLong("time"); + args.putLong("wakeup", duration == 0 ? -1 : time); + + new SimpleTask() { + @Override + protected Long onExecute(Context context, Bundle args) { + long account = args.getLong("account"); + String thread = args.getString("thread"); + long id = args.getLong("id"); + Long wakeup = args.getLong("wakeup"); + if (wakeup < 0) + wakeup = null; + + DB db = DB.getInstance(context); + try { + db.beginTransaction(); + + List messages = db.message().getMessageByThread( + account, thread, threading ? null : id, null); + for (EntityMessage threaded : messages) { + db.message().setMessageSnoozed(threaded.id, wakeup); + EntityMessage.snooze(context, threaded.id, wakeup); + EntityOperation.queue(context, threaded, EntityOperation.SEEN, true); + } + + db.setTransactionSuccessful(); + } finally { + db.endTransaction(); + } + + return wakeup; + } + + @Override + protected void onExecuted(Bundle args, Long wakeup) { + if (wakeup != null && args.getBoolean("finish")) + finish(); + } + + @Override + protected void onException(Bundle args, Throwable ex) { + Helper.unexpectedError(getContext(), getViewLifecycleOwner(), ex); + } + }.execute(getContext(), getViewLifecycleOwner(), args, "message:snooze"); + } + + private void onSnoozeSelection(Bundle args) { + if (!Helper.isPro(getContext())) { + LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(getContext()); + lbm.sendBroadcast(new Intent(ActivityView.ACTION_SHOW_PRO)); + return; + } + + long duration = args.getLong("duration"); + long time = args.getLong("time"); + args.putLong("wakeup", duration == 0 ? -1 : time); + args.putLongArray("ids", getSelection()); + + selectionTracker.clearSelection(); + + new SimpleTask() { + @Override + protected Void onExecute(Context context, Bundle args) { + long[] ids = args.getLongArray("ids"); + Long wakeup = args.getLong("wakeup"); + if (wakeup < 0) + wakeup = null; + + DB db = DB.getInstance(context); + try { + db.beginTransaction(); + + for (long id : ids) { + EntityMessage message = db.message().getMessage(id); + if (message != null) { + List messages = db.message().getMessageByThread( + message.account, message.thread, threading ? null : id, message.folder); + for (EntityMessage threaded : messages) { + db.message().setMessageSnoozed(threaded.id, wakeup); + EntityMessage.snooze(context, threaded.id, wakeup); + EntityOperation.queue(context, threaded, EntityOperation.SEEN, true); + } + } + } + + db.setTransactionSuccessful(); + } finally { + db.endTransaction(); + } + + return null; + } + + @Override + protected void onException(Bundle args, Throwable ex) { + Helper.unexpectedError(getContext(), getViewLifecycleOwner(), ex); + } + }.execute(FragmentMessages.this, args, "messages:snooze"); + } + + private void onMove(Bundle args) { + new SimpleTask() { + @Override + protected Void onExecute(Context context, Bundle args) { + long id = args.getLong("message"); + boolean copy = args.getBoolean("copy"); + long target = args.getLong("folder"); + + DB db = DB.getInstance(context); + try { + db.beginTransaction(); + + EntityMessage message = db.message().getMessage(id); + if (message == null) + return null; + + if (copy) + EntityOperation.queue(context, message, EntityOperation.COPY, target); + else + EntityOperation.queue(context, message, EntityOperation.MOVE, target); + + db.setTransactionSuccessful(); + } finally { + db.endTransaction(); + } + + return null; + } + + @Override + protected void onException(Bundle args, Throwable ex) { + Helper.unexpectedError(getContext(), getViewLifecycleOwner(), ex); + } + }.execute(getContext(), getViewLifecycleOwner(), args, "message:copy"); + } + private void saveRaw(Intent data) { Bundle args = new Bundle(); args.putLong("id", message); @@ -4024,7 +4084,6 @@ public class FragmentMessages extends FragmentBase implements SharedPreferences. Boolean isDrafts; List folders; List accounts; - Map> targets = new HashMap<>(); } private static class MessageTarget implements Parcelable { diff --git a/app/src/main/java/eu/faircode/email/FragmentSelectFolder.java b/app/src/main/java/eu/faircode/email/FragmentSelectFolder.java new file mode 100644 index 0000000000..6053391136 --- /dev/null +++ b/app/src/main/java/eu/faircode/email/FragmentSelectFolder.java @@ -0,0 +1,142 @@ +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.app.AlertDialog; +import android.app.Dialog; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.DialogFragment; +import androidx.fragment.app.Fragment; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import java.util.ArrayList; +import java.util.List; + +import static android.app.Activity.RESULT_CANCELED; +import static android.app.Activity.RESULT_OK; + +public class FragmentSelectFolder extends DialogFragment { + private TwoStateOwner owner = new TwoStateOwner("folder:select"); + + @NonNull + @Override + public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) { + String title = getArguments().getString("title"); + + final View dview = LayoutInflater.from(getContext()).inflate(R.layout.dialog_folder_select, null); + final RecyclerView rvFolder = dview.findViewById(R.id.rvFolder); + final ContentLoadingProgressBar pbWait = dview.findViewById(R.id.pbWait); + + rvFolder.setHasFixedSize(false); + LinearLayoutManager llm = new LinearLayoutManager(getContext()); + rvFolder.setLayoutManager(llm); + + rvFolder.setVisibility(View.GONE); + pbWait.setVisibility(View.VISIBLE); + + Bundle args = new Bundle(); + args.putLong("account", getArguments().getLong("account")); + + new SimpleTask>() { + @Override + protected List onExecute(Context context, Bundle args) { + long account = args.getLong("account"); + + DB db = DB.getInstance(context); + return db.folder().getFoldersEx(account); + } + + @Override + protected void onExecuted(final Bundle args, List folders) { + if (folders == null) + folders = new ArrayList<>(); + + long account = args.getLong("account"); + AdapterFolder adapter = new AdapterFolder(getContext(), owner, getView(), account, false, + new AdapterFolder.IFolderSelectedListener() { + @Override + public void onFolderSelected(TupleFolderEx folder) { + dismiss(); + sendResult(RESULT_OK, folder.id); + } + }); + + rvFolder.setAdapter(adapter); + + adapter.setDisabled(Helper.fromLongArray(getArguments().getLongArray("disabled"))); + adapter.set(folders); + + pbWait.setVisibility(View.GONE); + rvFolder.setVisibility(View.VISIBLE); + } + + @Override + protected void onException(Bundle args, Throwable ex) { + Helper.unexpectedError(getContext(), owner, ex); + } + }.execute(getContext(), owner, args, "folder:select"); + + return new AlertDialog.Builder(getContext()) + .setTitle(title) + .setView(dview) + .setOnDismissListener(new DialogInterface.OnDismissListener() { + @Override + public void onDismiss(DialogInterface dialogInterface) { + sendResult(RESULT_CANCELED, -1); + } + }) + .create(); + } + + @Override + public void onStart() { + super.onStart(); + Log.i("Folder select resume"); + owner.resume(); + } + + @Override + public void onDestroyView() { + Log.i("Folder select destroy"); + owner.destroy(); + super.onDestroyView(); + } + + private void sendResult(int result, long folder) { + Bundle args = getArguments(); + args.putLong("folder", folder); + + Fragment target = getTargetFragment(); + if (target != null) { + Intent data = new Intent(); + data.putExtra("args", args); + target.onActivityResult(getTargetRequestCode(), result, data); + } + } +} diff --git a/app/src/main/java/eu/faircode/email/TwoStateOwner.java b/app/src/main/java/eu/faircode/email/TwoStateOwner.java index aaa8c22d1f..9bbad3e84e 100644 --- a/app/src/main/java/eu/faircode/email/TwoStateOwner.java +++ b/app/src/main/java/eu/faircode/email/TwoStateOwner.java @@ -69,6 +69,10 @@ public class TwoStateOwner implements LifecycleOwner { registry.setCurrentState(Lifecycle.State.STARTED); } + void resume() { + registry.setCurrentState(Lifecycle.State.RESUMED); + } + void stop() { registry.setCurrentState(Lifecycle.State.CREATED); }