diff --git a/app/src/main/java/eu/faircode/email/BoundaryCallbackMessages.java b/app/src/main/java/eu/faircode/email/BoundaryCallbackMessages.java index d8c48ed7b5..b3399d2114 100644 --- a/app/src/main/java/eu/faircode/email/BoundaryCallbackMessages.java +++ b/app/src/main/java/eu/faircode/email/BoundaryCallbackMessages.java @@ -42,6 +42,7 @@ import com.sun.mail.imap.protocol.SearchSequence; import java.io.File; import java.io.IOException; import java.io.Serializable; +import java.lang.reflect.Constructor; import java.nio.charset.StandardCharsets; import java.text.Normalizer; import java.util.ArrayList; @@ -66,6 +67,7 @@ import javax.mail.search.BodyTerm; import javax.mail.search.ComparisonTerm; import javax.mail.search.FlagTerm; import javax.mail.search.FromStringTerm; +import javax.mail.search.NotTerm; import javax.mail.search.OrTerm; import javax.mail.search.ReceivedDateTerm; import javax.mail.search.RecipientStringTerm; @@ -192,6 +194,8 @@ public class BoundaryCallbackMessages extends PagedList.BoundaryCallback 1 && "+-?".indexOf(w.charAt(0)) >= 0) + return true; + + return false; + } + SearchTerm getTerms(boolean utf8, Flags flags, String[] keywords) { List or = new ArrayList<>(); List and = new ArrayList<>(); @@ -689,6 +704,39 @@ public class BoundaryCallbackMessages extends PagedList.BoundaryCallback word = new ArrayList<>(); + List plus = new ArrayList<>(); + List minus = new ArrayList<>(); + List opt = new ArrayList<>(); + StringBuilder sb = new StringBuilder(); + for (String w : search.trim().split("\\s+")) { + if (sb.length() > 0) + sb.append(' '); + + if (w.length() > 1 && w.startsWith("+")) { + plus.add(w.substring(1)); + sb.append(w.substring(1)); + } else if (w.length() > 1 && w.startsWith("-")) { + minus.add(w.substring(1)); + sb.append(w.substring(1)); + } else if (w.length() > 1 && w.startsWith("?")) { + opt.add(w.substring(1)); + sb.append(w.substring(1)); + } else { + word.add(w); + sb.append(w); + } + } + + if (plus.size() + minus.size() + opt.size() > 0) { + search = sb.toString(); + Log.i("SEARCH word=" + TextUtils.join(",", word)); + Log.i("SEARCH plus=" + TextUtils.join(",", plus)); + Log.i("SEARCH minus=" + TextUtils.join(",", minus)); + Log.i("SEARCH opt=" + TextUtils.join(",", opt)); + Log.i("SEARCH full=" + search); + } + // Yahoo! does not support keyword search, but uses the flags $Forwarded $Junk $NotJunk boolean hasKeywords = false; for (String keyword : keywords) @@ -704,12 +752,31 @@ public class BoundaryCallbackMessages extends PagedList.BoundaryCallback word, + List plus, + List minus, + List opt, + Class clazz) throws ReflectiveOperationException { + SearchTerm term = null; + Constructor ctor = clazz.getConstructor(String.class); + + if (word.size() > 0) + term = (SearchTerm) ctor.newInstance(TextUtils.join(" ", word)); + + for (String p : plus) + if (term == null) + term = (SearchTerm) ctor.newInstance(p); + else + term = new AndTerm(term, (SearchTerm) ctor.newInstance(p)); + + for (String m : minus) + if (term == null) + term = new NotTerm((SearchTerm) ctor.newInstance(m)); + else + term = new AndTerm(term, new NotTerm((SearchTerm) ctor.newInstance(m))); + + for (String o : opt) + if (term == null) + term = (SearchTerm) ctor.newInstance(o); + else + term = new OrTerm(term, (SearchTerm) ctor.newInstance(o)); + + return term; + } + String getTitle(Context context) { List flags = new ArrayList<>(); if (with_unseen) diff --git a/app/src/main/java/eu/faircode/email/FragmentDialogSearch.java b/app/src/main/java/eu/faircode/email/FragmentDialogSearch.java index dae96f5881..8608e71892 100644 --- a/app/src/main/java/eu/faircode/email/FragmentDialogSearch.java +++ b/app/src/main/java/eu/faircode/email/FragmentDialogSearch.java @@ -295,7 +295,7 @@ public class FragmentDialogSearch extends FragmentDialogBase { if (criteria.query != null && criteria.query.startsWith("raw:")) new SimpleTask() { @Override - protected EntityFolder onExecute(Context context, Bundle args) throws Throwable { + protected EntityFolder onExecute(Context context, Bundle args) { long aid = args.getLong("account", -1); DB db = DB.getInstance(context); @@ -334,6 +334,10 @@ public class FragmentDialogSearch extends FragmentDialogBase { Log.unexpectedError(getParentFragmentManager(), ex); } }.execute(getContext(), getViewLifecycleOwner(), getArguments(), "search:raw"); + else if (criteria.isExpression() && folder > 0) + FragmentMessages.search( + getContext(), getViewLifecycleOwner(), getParentFragmentManager(), + account, folder, true, criteria); else FragmentMessages.search( getContext(), getViewLifecycleOwner(), getParentFragmentManager(),