diff --git a/app/src/main/java/eu/faircode/email/AdapterNavSearch.java b/app/src/main/java/eu/faircode/email/AdapterNavSearch.java index a2f3a11f99..6f5d0d2da6 100644 --- a/app/src/main/java/eu/faircode/email/AdapterNavSearch.java +++ b/app/src/main/java/eu/faircode/email/AdapterNavSearch.java @@ -51,7 +51,7 @@ public class AdapterNavSearch extends RecyclerView.Adapter items = new ArrayList<>(); - public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener { + public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { private View view; private ImageView ivItem; private ImageView ivBadge; @@ -74,12 +74,10 @@ public class AdapterNavSearch extends RecyclerView.Adapter() { - @Override - protected Void onExecute(Context context, Bundle args) throws Throwable { - long id = args.getLong("id"); - - DB db = DB.getInstance(context); - db.search().deleteSearch(id); - - return null; - } - - @Override - protected void onException(Bundle args, Throwable ex) { - Log.unexpectedError(manager, ex); - } - }.execute(context, owner, args, "search:delete"); - - return true; - } } AdapterNavSearch(Context context, LifecycleOwner owner, FragmentManager manager) { diff --git a/app/src/main/java/eu/faircode/email/BoundaryCallbackMessages.java b/app/src/main/java/eu/faircode/email/BoundaryCallbackMessages.java index 00fdfdc4e1..8f8c5471df 100644 --- a/app/src/main/java/eu/faircode/email/BoundaryCallbackMessages.java +++ b/app/src/main/java/eu/faircode/email/BoundaryCallbackMessages.java @@ -728,6 +728,7 @@ public class BoundaryCallbackMessages extends PagedList.BoundaryCallback 0) { + int[] sizes = getResources().getIntArray(R.array.sizeValues); + criteria.with_size = sizes[pos]; + } + } + + criteria.in_trash = cbSearchTrash.isChecked(); + criteria.in_junk = cbSearchJunk.isChecked(); + + Object after = tvAfter.getTag(); + Object before = tvBefore.getTag(); + + if (after != null) + criteria.after = ((Calendar) after).getTimeInMillis(); + if (before != null) + criteria.before = ((Calendar) before).getTimeInMillis(); if (criteria.query != null) { List searches = new ArrayList<>(); @@ -481,38 +481,6 @@ public class FragmentDialogSearch extends FragmentDialogBase { account, folder, false, criteria); } }) - .setNeutralButton(R.string.title_save, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - try { - BoundaryCallbackMessages.SearchCriteria criteria = getSearchCriteria(); - Bundle args = new Bundle(); - args.putString("name", criteria.getTitle(context)); - args.putString("data", criteria.toJson().toString()); - - new SimpleTask() { - @Override - protected Void onExecute(Context context, Bundle args) { - EntitySearch search = new EntitySearch(); - search.name = args.getString("name"); - search.data = args.getString("data"); - - DB db = DB.getInstance(context); - db.search().insertSearch(search); - - return null; - } - - @Override - protected void onException(Bundle args, Throwable ex) { - Log.unexpectedError(getParentFragmentManager(), ex); - } - }.execute(FragmentDialogSearch.this, args, "search:save"); - } catch (Throwable ex) { - Log.e(ex); - } - } - }) .setNegativeButton(android.R.string.no, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { @@ -578,50 +546,6 @@ public class FragmentDialogSearch extends FragmentDialogBase { getActivity().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN); } - private BoundaryCallbackMessages.SearchCriteria getSearchCriteria() { - BoundaryCallbackMessages.SearchCriteria criteria = new BoundaryCallbackMessages.SearchCriteria(); - - criteria.query = etQuery.getText().toString().trim(); - if (TextUtils.isEmpty(criteria.query)) - criteria.query = null; - - criteria.fts = cbSearchIndex.isChecked(); - if (!criteria.fts) { - criteria.in_senders = cbSenders.isChecked(); - criteria.in_recipients = cbRecipients.isChecked(); - criteria.in_subject = cbSubject.isChecked(); - criteria.in_keywords = cbKeywords.isChecked(); - criteria.in_message = cbMessage.isChecked(); - criteria.in_notes = cbNotes.isChecked(); - criteria.in_headers = cbHeaders.isChecked(); - criteria.in_html = cbHtml.isChecked(); - criteria.with_unseen = cbUnseen.isChecked(); - criteria.with_flagged = cbFlagged.isChecked(); - criteria.with_hidden = cbHidden.isChecked(); - criteria.with_encrypted = cbEncrypted.isChecked(); - criteria.with_attachments = cbAttachments.isChecked(); - - int pos = spMessageSize.getSelectedItemPosition(); - if (pos > 0) { - int[] sizes = getResources().getIntArray(R.array.sizeValues); - criteria.with_size = sizes[pos]; - } - } - - criteria.in_trash = cbSearchTrash.isChecked(); - criteria.in_junk = cbSearchJunk.isChecked(); - - Object after = tvAfter.getTag(); - Object before = tvBefore.getTag(); - - if (after != null) - criteria.after = ((Calendar) after).getTimeInMillis(); - if (before != null) - criteria.before = ((Calendar) before).getTimeInMillis(); - - return criteria; - } - private void pickDate(TextView tv) { Object tag = tv.getTag(); final Calendar cal = (tag == null ? Calendar.getInstance() : (Calendar) tag); diff --git a/app/src/main/java/eu/faircode/email/FragmentMessages.java b/app/src/main/java/eu/faircode/email/FragmentMessages.java index 3254e6cccc..4a8c1f3874 100644 --- a/app/src/main/java/eu/faircode/email/FragmentMessages.java +++ b/app/src/main/java/eu/faircode/email/FragmentMessages.java @@ -111,6 +111,7 @@ import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.CheckBox; import android.widget.CompoundButton; +import android.widget.EditText; import android.widget.ImageButton; import android.widget.SeekBar; import android.widget.TextView; @@ -383,6 +384,7 @@ public class FragmentMessages extends FragmentBase implements SharedPreferences. static final int REQUEST_PICK_CONTACT = 23; static final int REQUEST_BUTTONS = 24; private static final int REQUEST_ALL_READ = 25; + private static final int REQUEST_SAVE_SEARCH = 26; static final String ACTION_STORE_RAW = BuildConfig.APPLICATION_ID + ".STORE_RAW"; static final String ACTION_DECRYPT = BuildConfig.APPLICATION_ID + ".DECRYPT"; @@ -4399,6 +4401,13 @@ public class FragmentMessages extends FragmentBase implements SharedPreferences. MenuItem menuSearch = menu.findItem(R.id.menu_search); menuSearch.setVisible(folder); + menu.findItem(R.id.menu_save_search).setVisible( + viewType == AdapterMessage.ViewType.SEARCH && + criteria != null && criteria.id < 0); + menu.findItem(R.id.menu_delete_search).setVisible( + viewType == AdapterMessage.ViewType.SEARCH && + criteria != null && criteria.id >= 0); + menu.findItem(R.id.menu_folders).setVisible( viewType == AdapterMessage.ViewType.UNIFIED && type == null && primary >= 0); @@ -4490,6 +4499,12 @@ public class FragmentMessages extends FragmentBase implements SharedPreferences. if (itemId == R.id.menu_search) { onMenuSearch(); return true; + } else if (itemId == R.id.menu_save_search) { + onMenuSaveSearch(); + return true; + } else if (itemId == R.id.menu_delete_search) { + onMenuDeleteSearch(); + return true; } else if (itemId == R.id.menu_folders) {// Obsolete onMenuFolders(primary); return true; @@ -4600,6 +4615,43 @@ public class FragmentMessages extends FragmentBase implements SharedPreferences. fragment.show(getParentFragmentManager(), "search"); } + private void onMenuSaveSearch() { + Bundle args = new Bundle(); + args.putSerializable("criteria", criteria); + + FragmentDialogSaveSearch fragment = new FragmentDialogSaveSearch(); + fragment.setArguments(args); + fragment.setTargetFragment(this, REQUEST_SAVE_SEARCH); + fragment.show(getParentFragmentManager(), "search:save"); + } + + private void onMenuDeleteSearch() { + Bundle args = new Bundle(); + args.putLong("id", criteria.id); + + new SimpleTask() { + @Override + protected Void onExecute(Context context, Bundle args) throws Throwable { + long id = args.getLong("id"); + + DB db = DB.getInstance(context); + db.search().deleteSearch(id); + + return null; + } + + @Override + protected void onExecuted(Bundle args, Void data) { + finish(); + } + + @Override + protected void onException(Bundle args, Throwable ex) { + Log.unexpectedError(getParentFragmentManager(), ex); + } + }.execute(this, args, "search:delete"); + } + private void onMenuFolders(long account) { if (!isAdded()) return; @@ -4835,7 +4887,6 @@ public class FragmentMessages extends FragmentBase implements SharedPreferences. ask.setArguments(args); ask.setTargetFragment(FragmentMessages.this, REQUEST_ALL_READ); ask.show(getParentFragmentManager(), "messages:allread"); - } private void onMenuViewThread() { @@ -4898,6 +4949,35 @@ public class FragmentMessages extends FragmentBase implements SharedPreferences. }.execute(FragmentMessages.this, args, "messages:allread"); } + private void onSaveSearch(Bundle args) { + new SimpleTask() { + @Override + protected Void onExecute(Context context, Bundle args) throws Throwable { + BoundaryCallbackMessages.SearchCriteria criteria = + (BoundaryCallbackMessages.SearchCriteria) args.getSerializable("criteria"); + + EntitySearch search = new EntitySearch(); + search.name = args.getString("name"); + search.data = criteria.toJson().toString(); + + DB db = DB.getInstance(context); + search.id = db.search().insertSearch(search); + + return null; + } + + @Override + protected void onExecuted(Bundle args, Void data) { + finish(); + } + + @Override + protected void onException(Bundle args, Throwable ex) { + Log.unexpectedError(getParentFragmentManager(), ex); + } + }.execute(this, args, "search:save"); + } + private void onMenuSyncMore() { Bundle args = new Bundle(); args.putLong("folder", folder); @@ -6609,6 +6689,10 @@ public class FragmentMessages extends FragmentBase implements SharedPreferences. if (resultCode == RESULT_OK) markAllRead(); break; + case REQUEST_SAVE_SEARCH: + if (resultCode == RESULT_OK && data != null) + onSaveSearch(data.getBundleExtra("args")); + break; } } catch (Throwable ex) { Log.e(ex); @@ -8918,4 +9002,35 @@ public class FragmentMessages extends FragmentBase implements SharedPreferences. .create(); } } + + public static class FragmentDialogSaveSearch extends FragmentDialogBase { + @NonNull + @Override + public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) { + final Context context = getContext(); + View dview = LayoutInflater.from(context).inflate(R.layout.dialog_save_search, null); + EditText etName = dview.findViewById(R.id.etName); + + BoundaryCallbackMessages.SearchCriteria criteria = + (BoundaryCallbackMessages.SearchCriteria) getArguments().getSerializable("criteria"); + etName.setText(criteria.getTitle(context)); + + return new AlertDialog.Builder(context) + .setView(dview) + .setPositiveButton(R.string.title_save, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + getArguments().putString("name", etName.getText().toString()); + sendResult(Activity.RESULT_OK); + } + }) + .setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + sendResult(Activity.RESULT_CANCELED); + } + }) + .create(); + } + } } diff --git a/app/src/main/res/layout/dialog_save_search.xml b/app/src/main/res/layout/dialog_save_search.xml new file mode 100644 index 0000000000..c8af041ad5 --- /dev/null +++ b/app/src/main/res/layout/dialog_save_search.xml @@ -0,0 +1,35 @@ + + + + + + + + + + diff --git a/app/src/main/res/menu/menu_messages.xml b/app/src/main/res/menu/menu_messages.xml index d9b3ba5bdb..f85bf931f6 100644 --- a/app/src/main/res/menu/menu_messages.xml +++ b/app/src/main/res/menu/menu_messages.xml @@ -8,6 +8,18 @@ android:title="@string/title_search" app:showAsAction="always" /> + + + +