Use dialog fragment to select folder/duration

pull/157/head
M66B 6 years ago
parent 0f7f0e1ad3
commit 0d33077b19

@ -3079,55 +3079,21 @@ public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHold
.setNegativeButton(android.R.string.cancel, null)
.show();
} else
properties.move(data.message.id, EntityFolder.TRASH, true);
properties.move(data.message.id, EntityFolder.TRASH);
}
private void onActionMove(final TupleMessageEx message, final boolean copy) {
DialogFolder.show(
context, owner, parentFragment.getView(),
copy ? R.string.title_copy_to : R.string.title_move_to_folder,
message.account, Arrays.asList(message.folder),
new DialogFolder.IDialogFolder() {
@Override
public void onFolderSelected(TupleFolderEx folder) {
if (copy) {
Bundle args = new Bundle();
args.putLong("id", message.id);
args.putLong("target", folder.id);
new SimpleTask<Void>() {
@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<AdapterMessage.ViewHold
}
private void onActionArchive(ActionData data) {
properties.move(data.message.id, EntityFolder.ARCHIVE, true);
properties.move(data.message.id, EntityFolder.ARCHIVE);
}
private void onActionMoveJunk(ActionData data) {
properties.move(data.message.id, EntityFolder.INBOX, true);
properties.move(data.message.id, EntityFolder.INBOX);
}
private void onActionReplyMenu(final ActionData data) {
@ -3837,7 +3803,7 @@ public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHold
void scrollBy(int dx, int dy);
void move(long id, String target, boolean type);
void move(long id, String type);
void finish();
}

@ -1,101 +0,0 @@
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.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<Long> 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<List<TupleFolderEx>>() {
@Override
protected List<TupleFolderEx> 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<TupleFolderEx> 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);
}
}

@ -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<Void>() {
@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<Void>() {
@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)

@ -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);
}
}
}

@ -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<ArrayList<MessageTarget>>() {
@Override
protected ArrayList<MessageTarget> 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<MessageTarget> 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<EntityMessage> 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<MessageTarget> 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<Long>(),
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<ArrayList<MessageTarget>>() {
@Override
protected ArrayList<MessageTarget> 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<MessageTarget> 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<MessageTarget> 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<List<TupleFolderEx>>() {
@Override
protected List<TupleFolderEx> 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<TupleFolderEx> 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<ArrayList<MessageTarget>>() {
@Override
protected ArrayList<MessageTarget> 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<MessageTarget> 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<EntityMessage> 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<MessageTarget> 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<Long>() {
@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<EntityMessage> 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<Void>() {
@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<EntityMessage> 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<TupleFolderEx> folders, List<Long> 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<Long> 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<ArrayList<MessageTarget>>() {
@ -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<Long>() {
@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<EntityMessage> 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<Void>() {
@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<EntityMessage> 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<Void>() {
@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<Long> folders;
List<EntityAccount> accounts;
Map<Long, List<TupleFolderEx>> targets = new HashMap<>();
}
private static class MessageTarget implements Parcelable {

@ -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 <http://www.gnu.org/licenses/>.
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<List<TupleFolderEx>>() {
@Override
protected List<TupleFolderEx> 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<TupleFolderEx> 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);
}
}
}

@ -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);
}

Loading…
Cancel
Save