diff --git a/app/src/main/java/eu/faircode/email/EntityRule.java b/app/src/main/java/eu/faircode/email/EntityRule.java index aad717dd4c..ffc0b8b232 100644 --- a/app/src/main/java/eu/faircode/email/EntityRule.java +++ b/app/src/main/java/eu/faircode/email/EntityRule.java @@ -237,6 +237,7 @@ public class EntityRule { // Sender JSONObject jsender = jcondition.optJSONObject("sender"); if (jsender != null) { + boolean not = jsender.optBoolean("not"); String value = jsender.getString("value"); boolean regex = jsender.getBoolean("regex"); boolean known = jsender.optBoolean("known"); @@ -279,13 +280,14 @@ public class EntityRule { } } } - if (!matches) + if (matches == not) return false; } // Recipient JSONObject jrecipient = jcondition.optJSONObject("recipient"); if (jrecipient != null) { + boolean not = jrecipient.optBoolean("not"); String value = jrecipient.getString("value"); boolean regex = jrecipient.getBoolean("regex"); @@ -306,17 +308,18 @@ public class EntityRule { break; } } - if (!matches) + if (matches == not) return false; } // Subject JSONObject jsubject = jcondition.optJSONObject("subject"); if (jsubject != null) { + boolean not = jsubject.optBoolean("not"); String value = jsubject.getString("value"); boolean regex = jsubject.getBoolean("regex"); - if (!matches(context, message, value, message.subject, regex)) + if (matches(context, message, value, message.subject, regex) == not) return false; } @@ -464,6 +467,7 @@ public class EntityRule { // Body JSONObject jbody = jcondition.optJSONObject("body"); if (jbody != null) { + boolean not = jbody.optBoolean("not"); String value = jbody.getString("value"); boolean regex = jbody.getBoolean("regex"); boolean skip_quotes = jbody.optBoolean("skip_quotes"); @@ -493,11 +497,11 @@ public class EntityRule { d.select("blockquote").remove(); if (jsoup) { String selector = value.substring(JSOUP_PREFIX.length()); - if (d.select(selector).size() == 0) + if (d.select(selector).isEmpty() != not) return false; } else { String text = d.body().text(); - if (!matches(context, message, value, text, regex)) + if (matches(context, message, value, text, regex) == not) return false; } } diff --git a/app/src/main/java/eu/faircode/email/FragmentRule.java b/app/src/main/java/eu/faircode/email/FragmentRule.java index e596d52348..594425b628 100644 --- a/app/src/main/java/eu/faircode/email/FragmentRule.java +++ b/app/src/main/java/eu/faircode/email/FragmentRule.java @@ -93,15 +93,18 @@ public class FragmentRule extends FragmentBase { private EditText etAge; private CheckBox cbStop; + private CheckBox cbSenderNot; private EditText etSender; private CheckBox cbSender; private ImageButton ibSender; private CheckBox cbKnownSender; + private CheckBox cbRecipientNot; private EditText etRecipient; private CheckBox cbRecipient; private ImageButton ibRecipient; + private CheckBox cbSubjectNot; private EditText etSubject; private CheckBox cbSubject; @@ -112,6 +115,7 @@ public class FragmentRule extends FragmentBase { private ImageButton ibHeader; private CheckBox cbHeader; + private CheckBox cbBodyNot; private EditText etBody; private CheckBox cbBody; private CheckBox cbSkipQuotes; @@ -288,15 +292,18 @@ public class FragmentRule extends FragmentBase { etAge = view.findViewById(R.id.etAge); cbStop = view.findViewById(R.id.cbStop); + cbSenderNot = view.findViewById(R.id.cbSenderNot); etSender = view.findViewById(R.id.etSender); cbSender = view.findViewById(R.id.cbSender); ibSender = view.findViewById(R.id.ibSender); cbKnownSender = view.findViewById(R.id.cbKnownSender); + cbRecipientNot = view.findViewById(R.id.cbRecipientNot); etRecipient = view.findViewById(R.id.etRecipient); cbRecipient = view.findViewById(R.id.cbRecipient); ibRecipient = view.findViewById(R.id.ibRecipient); + cbSubjectNot = view.findViewById(R.id.cbSubjectNot); etSubject = view.findViewById(R.id.etSubject); cbSubject = view.findViewById(R.id.cbSubject); @@ -307,6 +314,7 @@ public class FragmentRule extends FragmentBase { ibHeader = view.findViewById(R.id.ibHeader); cbHeader = view.findViewById(R.id.cbHeader); + cbBodyNot = view.findViewById(R.id.cbBodyNot); etBody = view.findViewById(R.id.etBody); cbBody = view.findViewById(R.id.cbBody); cbSkipQuotes = view.findViewById(R.id.cbSkipQuotes); @@ -708,8 +716,6 @@ public class FragmentRule extends FragmentBase { npDuration.setMinValue(0); npDuration.setMaxValue(999); - tvActionRemark.setVisibility(View.GONE); - btnColor.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { @@ -915,7 +921,6 @@ public class FragmentRule extends FragmentBase { tvActionRemark.setText( getString(R.string.title_rule_action_remark, data.folder.getDisplayName(getContext()))); - tvActionRemark.setVisibility(View.VISIBLE); loadRule(savedInstanceState); } @@ -1234,6 +1239,7 @@ public class FragmentRule extends FragmentBase { etAge.setText(jgeneral == null ? null : Integer.toString(jgeneral.optInt("age"))); cbStop.setChecked(rule != null && rule.stop); + cbSenderNot.setChecked(jsender != null && jsender.optBoolean("not")); etSender.setText(jsender == null ? args.getString("sender") : jsender.getString("value")); cbSender.setChecked(jsender != null && jsender.getBoolean("regex")); cbKnownSender.setChecked(jsender != null && jsender.optBoolean("known")); @@ -1241,9 +1247,11 @@ public class FragmentRule extends FragmentBase { ibSender.setEnabled(!cbKnownSender.isChecked()); cbSender.setEnabled(!cbKnownSender.isChecked()); + cbRecipientNot.setChecked(jrecipient != null && jrecipient.optBoolean("not")); etRecipient.setText(jrecipient == null ? args.getString("recipient") : jrecipient.getString("value")); cbRecipient.setChecked(jrecipient != null && jrecipient.getBoolean("regex")); + cbSubjectNot.setChecked(jsubject != null && jsubject.optBoolean("not")); etSubject.setText(jsubject == null ? args.getString("subject") : jsubject.getString("value")); cbSubject.setChecked(jsubject != null && jsubject.getBoolean("regex")); @@ -1254,6 +1262,7 @@ public class FragmentRule extends FragmentBase { etHeader.setText(jheader == null ? null : jheader.getString("value")); cbHeader.setChecked(jheader != null && jheader.getBoolean("regex")); + cbBodyNot.setChecked(jbody != null && jbody.optBoolean("not")); etBody.setText(jbody == null ? null : jbody.getString("value")); cbBody.setChecked(jbody != null && jbody.getBoolean("regex")); cbSkipQuotes.setChecked(jbody != null && jbody.optBoolean("skip_quotes")); @@ -1625,6 +1634,7 @@ public class FragmentRule extends FragmentBase { boolean known = cbKnownSender.isChecked(); if (!TextUtils.isEmpty(sender) || known) { JSONObject jsender = new JSONObject(); + jsender.put("not", cbSenderNot.isChecked()); jsender.put("value", sender); jsender.put("regex", cbSender.isChecked()); jsender.put("known", known); @@ -1634,6 +1644,7 @@ public class FragmentRule extends FragmentBase { String recipient = etRecipient.getText().toString(); if (!TextUtils.isEmpty(recipient)) { JSONObject jrecipient = new JSONObject(); + jrecipient.put("not", cbRecipientNot.isChecked()); jrecipient.put("value", recipient); jrecipient.put("regex", cbRecipient.isChecked()); jcondition.put("recipient", jrecipient); @@ -1642,6 +1653,7 @@ public class FragmentRule extends FragmentBase { String subject = etSubject.getText().toString(); if (!TextUtils.isEmpty(subject)) { JSONObject jsubject = new JSONObject(); + jsubject.put("not", cbSubjectNot.isChecked()); jsubject.put("value", subject); jsubject.put("regex", cbSubject.isChecked()); jcondition.put("subject", jsubject); @@ -1661,6 +1673,7 @@ public class FragmentRule extends FragmentBase { String body = etBody.getText().toString(); if (!TextUtils.isEmpty(body)) { JSONObject jbody = new JSONObject(); + jbody.put("not", cbBodyNot.isChecked()); jbody.put("value", body); jbody.put("regex", cbBody.isChecked()); jbody.put("skip_quotes", cbSkipQuotes.isChecked()); diff --git a/app/src/main/res/layout/fragment_rule.xml b/app/src/main/res/layout/fragment_rule.xml index 9e3d0ab689..12f1ff3d5e 100644 --- a/app/src/main/res/layout/fragment_rule.xml +++ b/app/src/main/res/layout/fragment_rule.xml @@ -177,15 +177,27 @@ + + + app:layout_constraintTop_toBottomOf="@id/cbSenderNot" /> + + + app:layout_constraintTop_toBottomOf="@id/cbRecipientNot" /> + + + app:layout_constraintTop_toBottomOf="@id/cbSubjectNot" /> + + + app:layout_constraintTop_toBottomOf="@id/cbBodyNot" /> diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 04f66c83d9..009e6b2707 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -2046,6 +2046,7 @@ Messages younger than (hours) Regex AND + NOT Action This action will be applied to new messages arriving in the folder %1$s Hours