Rule refactoring

pull/147/head
M66B 7 years ago
parent 2709a66e34
commit 0bfc49c1e5

@ -130,6 +130,7 @@ public class ActivityView extends ActivityBilling implements FragmentManager.OnB
static final String ACTION_STORE_RAW = BuildConfig.APPLICATION_ID + ".STORE_RAW"; static final String ACTION_STORE_RAW = BuildConfig.APPLICATION_ID + ".STORE_RAW";
static final String ACTION_EDIT_FOLDER = BuildConfig.APPLICATION_ID + ".EDIT_FOLDER"; static final String ACTION_EDIT_FOLDER = BuildConfig.APPLICATION_ID + ".EDIT_FOLDER";
static final String ACTION_EDIT_ANSWER = BuildConfig.APPLICATION_ID + ".EDIT_ANSWER"; static final String ACTION_EDIT_ANSWER = BuildConfig.APPLICATION_ID + ".EDIT_ANSWER";
static final String ACTION_EDIT_RULES = BuildConfig.APPLICATION_ID + ".EDIT_RULES";
static final String ACTION_EDIT_RULE = BuildConfig.APPLICATION_ID + ".EDIT_RULE"; static final String ACTION_EDIT_RULE = BuildConfig.APPLICATION_ID + ".EDIT_RULE";
static final String ACTION_STORE_ATTACHMENT = BuildConfig.APPLICATION_ID + ".STORE_ATTACHMENT"; static final String ACTION_STORE_ATTACHMENT = BuildConfig.APPLICATION_ID + ".STORE_ATTACHMENT";
static final String ACTION_STORE_ATTACHMENTS = BuildConfig.APPLICATION_ID + ".STORE_ATTACHMENTS"; static final String ACTION_STORE_ATTACHMENTS = BuildConfig.APPLICATION_ID + ".STORE_ATTACHMENTS";
@ -184,9 +185,6 @@ public class ActivityView extends ActivityBilling implements FragmentManager.OnB
case R.string.menu_answers: case R.string.menu_answers:
onMenuAnswers(); onMenuAnswers();
break; break;
case R.string.menu_rules:
onMenuRules();
break;
case R.string.menu_operations: case R.string.menu_operations:
onMenuOperations(); onMenuOperations();
break; break;
@ -304,7 +302,6 @@ public class ActivityView extends ActivityBilling implements FragmentManager.OnB
drawerArray.add(new DrawerItem(R.layout.item_drawer_separator)); drawerArray.add(new DrawerItem(R.layout.item_drawer_separator));
drawerArray.add(new DrawerItem(ActivityView.this, R.layout.item_drawer, R.drawable.baseline_reply_24, R.string.menu_answers)); drawerArray.add(new DrawerItem(ActivityView.this, R.layout.item_drawer, R.drawable.baseline_reply_24, R.string.menu_answers));
drawerArray.add(new DrawerItem(ActivityView.this, R.layout.item_drawer, R.drawable.baseline_filter_list_24, R.string.menu_rules));
drawerArray.add(new DrawerItem(ActivityView.this, R.layout.item_drawer, R.drawable.baseline_list_24, R.string.menu_operations)); drawerArray.add(new DrawerItem(ActivityView.this, R.layout.item_drawer, R.drawable.baseline_list_24, R.string.menu_operations));
drawerArray.add(new DrawerItem(ActivityView.this, R.layout.item_drawer, R.drawable.baseline_settings_applications_24, R.string.menu_setup)); drawerArray.add(new DrawerItem(ActivityView.this, R.layout.item_drawer, R.drawable.baseline_settings_applications_24, R.string.menu_setup));
@ -479,6 +476,7 @@ public class ActivityView extends ActivityBilling implements FragmentManager.OnB
iff.addAction(ACTION_STORE_RAW); iff.addAction(ACTION_STORE_RAW);
iff.addAction(ACTION_EDIT_FOLDER); iff.addAction(ACTION_EDIT_FOLDER);
iff.addAction(ACTION_EDIT_ANSWER); iff.addAction(ACTION_EDIT_ANSWER);
iff.addAction(ACTION_EDIT_RULES);
iff.addAction(ACTION_EDIT_RULE); iff.addAction(ACTION_EDIT_RULE);
iff.addAction(ACTION_STORE_ATTACHMENT); iff.addAction(ACTION_STORE_ATTACHMENT);
iff.addAction(ACTION_STORE_ATTACHMENTS); iff.addAction(ACTION_STORE_ATTACHMENTS);
@ -877,12 +875,6 @@ public class ActivityView extends ActivityBilling implements FragmentManager.OnB
fragmentTransaction.commit(); fragmentTransaction.commit();
} }
private void onMenuRules() {
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.content_frame, new FragmentRules()).addToBackStack("rules");
fragmentTransaction.commit();
}
private void onMenuOperations() { private void onMenuOperations() {
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction(); FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.content_frame, new FragmentOperations()).addToBackStack("operations"); fragmentTransaction.replace(R.id.content_frame, new FragmentOperations()).addToBackStack("operations");
@ -1021,6 +1013,8 @@ public class ActivityView extends ActivityBilling implements FragmentManager.OnB
onEditFolder(intent); onEditFolder(intent);
else if (ACTION_EDIT_ANSWER.equals(action)) else if (ACTION_EDIT_ANSWER.equals(action))
onEditAnswer(intent); onEditAnswer(intent);
else if (ACTION_EDIT_RULES.equals(action))
onEditRules(intent);
else if (ACTION_EDIT_RULE.equals(action)) else if (ACTION_EDIT_RULE.equals(action))
onEditRule(intent); onEditRule(intent);
else if (ACTION_STORE_ATTACHMENT.equals(action)) else if (ACTION_STORE_ATTACHMENT.equals(action))
@ -1115,6 +1109,14 @@ public class ActivityView extends ActivityBilling implements FragmentManager.OnB
fragmentTransaction.commit(); fragmentTransaction.commit();
} }
private void onEditRules(Intent intent) {
FragmentRules fragment = new FragmentRules();
fragment.setArguments(intent.getExtras());
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.content_frame, fragment).addToBackStack("rules");
fragmentTransaction.commit();
}
private void onEditRule(Intent intent) { private void onEditRule(Intent intent) {
FragmentRule fragment = new FragmentRule(); FragmentRule fragment = new FragmentRule();
fragment.setArguments(intent.getExtras()); fragment.setArguments(intent.getExtras());

@ -84,6 +84,7 @@ public class AdapterFolder extends RecyclerView.Adapter<AdapterFolder.ViewHolder
private final static int action_delete_local = 2; private final static int action_delete_local = 2;
private final static int action_empty_trash = 3; private final static int action_empty_trash = 3;
private final static int action_edit_properties = 4; private final static int action_edit_properties = 4;
private final static int action_edit_rules = 5;
ViewHolder(View itemView) { ViewHolder(View itemView) {
super(itemView); super(itemView);
@ -236,8 +237,10 @@ public class AdapterFolder extends RecyclerView.Adapter<AdapterFolder.ViewHolder
if (EntityFolder.TRASH.equals(folder.type)) if (EntityFolder.TRASH.equals(folder.type))
popupMenu.getMenu().add(Menu.NONE, action_empty_trash, 3, R.string.title_empty_trash); popupMenu.getMenu().add(Menu.NONE, action_empty_trash, 3, R.string.title_empty_trash);
if (folder.account != null) if (folder.account != null) {
popupMenu.getMenu().add(Menu.NONE, action_edit_properties, 4, R.string.title_edit_properties); popupMenu.getMenu().add(Menu.NONE, action_edit_properties, 4, R.string.title_edit_properties);
popupMenu.getMenu().add(Menu.NONE, action_edit_rules, 5, R.string.title_edit_rules);
}
popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() { popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
@Override @Override
@ -259,6 +262,10 @@ public class AdapterFolder extends RecyclerView.Adapter<AdapterFolder.ViewHolder
onActionEditProperties(); onActionEditProperties();
return true; return true;
case action_edit_rules:
onActionEditRules();
return true;
default: default:
return false; return false;
} }
@ -371,6 +378,14 @@ public class AdapterFolder extends RecyclerView.Adapter<AdapterFolder.ViewHolder
new Intent(ActivityView.ACTION_EDIT_FOLDER) new Intent(ActivityView.ACTION_EDIT_FOLDER)
.putExtra("id", folder.id)); .putExtra("id", folder.id));
} }
private void onActionEditRules() {
LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(context);
lbm.sendBroadcast(
new Intent(ActivityView.ACTION_EDIT_RULES)
.putExtra("account", folder.account)
.putExtra("folder", folder.id));
}
}); });
popupMenu.show(); popupMenu.show();

@ -51,14 +51,14 @@ public class AdapterRule extends RecyclerView.Adapter<AdapterRule.ViewHolder> {
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
private View itemView; private View itemView;
private TextView tvName; private TextView tvName;
private TextView tvFolder; private TextView tvOrder;
ViewHolder(View itemView) { ViewHolder(View itemView) {
super(itemView); super(itemView);
this.itemView = itemView.findViewById(R.id.clItem); this.itemView = itemView.findViewById(R.id.clItem);
tvName = itemView.findViewById(R.id.tvName); tvName = itemView.findViewById(R.id.tvName);
tvFolder = itemView.findViewById(R.id.tvFolder); tvOrder = itemView.findViewById(R.id.tvOrder);
} }
private void wire() { private void wire() {
@ -72,7 +72,7 @@ public class AdapterRule extends RecyclerView.Adapter<AdapterRule.ViewHolder> {
private void bindTo(TupleRuleEx rule) { private void bindTo(TupleRuleEx rule) {
itemView.setActivated(!rule.enabled); itemView.setActivated(!rule.enabled);
tvName.setText(rule.name); tvName.setText(rule.name);
tvFolder.setText(rule.folderName + "/" + rule.accountName); tvOrder.setText(Integer.toString(rule.order));
} }
@Override @Override
@ -86,7 +86,9 @@ public class AdapterRule extends RecyclerView.Adapter<AdapterRule.ViewHolder> {
LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(context); LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(context);
lbm.sendBroadcast( lbm.sendBroadcast(
new Intent(ActivityView.ACTION_EDIT_RULE) new Intent(ActivityView.ACTION_EDIT_RULE)
.putExtra("id", rule.id)); .putExtra("id", rule.id)
.putExtra("account", rule.account)
.putExtra("folder", rule.folder));
} }
} }

@ -43,8 +43,9 @@ public interface DaoRule {
@Query("SELECT rule.*, folder.account, folder.name AS folderName, account.name AS accountName FROM rule" + @Query("SELECT rule.*, folder.account, folder.name AS folderName, account.name AS accountName FROM rule" +
" JOIN folder ON folder.id = rule.folder" + " JOIN folder ON folder.id = rule.folder" +
" JOIN account ON account.id = folder.account") " JOIN account ON account.id = folder.account" +
LiveData<List<TupleRuleEx>> liveRules(); " WHERE rule.folder = :folder")
LiveData<List<TupleRuleEx>> liveRules(long folder);
@Insert @Insert
long insertRule(EntityRule rule); long insertRule(EntityRule rule);

@ -72,7 +72,6 @@ public class EntityRule {
JSONObject jcondition = new JSONObject(condition); JSONObject jcondition = new JSONObject(condition);
String sender = jcondition.optString("sender", null); String sender = jcondition.optString("sender", null);
String subject = jcondition.optString("subject", null); String subject = jcondition.optString("subject", null);
String text = jcondition.optString("text", null);
boolean regex = jcondition.optBoolean("regex", false); boolean regex = jcondition.optBoolean("regex", false);
if (sender != null && message.from != null) { if (sender != null && message.from != null) {
@ -84,13 +83,6 @@ public class EntityRule {
if (matches(subject, message.subject, regex)) if (matches(subject, message.subject, regex))
return true; return true;
} }
if (text != null && message.content) {
String body = message.read(context);
String santized = HtmlHelper.sanitize(body, true);
if (matches(text, santized, regex))
return true;
}
} catch (JSONException ex) { } catch (JSONException ex) {
Log.e(ex); Log.e(ex);
} }

@ -52,11 +52,8 @@ public class FragmentRule extends FragmentBase {
private EditText etName; private EditText etName;
private EditText etOrder; private EditText etOrder;
private CheckBox cbEnabled; private CheckBox cbEnabled;
private Spinner spAccount;
private Spinner spFolder;
private EditText etSender; private EditText etSender;
private EditText etSubject; private EditText etSubject;
private EditText etText;
private Spinner spAction; private Spinner spAction;
private Spinner spTarget; private Spinner spTarget;
private BottomNavigationView bottom_navigation; private BottomNavigationView bottom_navigation;
@ -64,12 +61,12 @@ public class FragmentRule extends FragmentBase {
private Group grpReady; private Group grpReady;
private Group grpMove; private Group grpMove;
private ArrayAdapter<EntityAccount> adapterAccount;
private ArrayAdapter<EntityFolder> adapterFolder;
private ArrayAdapter<Action> adapterAction; private ArrayAdapter<Action> adapterAction;
private ArrayAdapter<EntityFolder> adapterTarget; private ArrayAdapter<EntityFolder> adapterTarget;
private long id = -1; private long id = -1;
private long account = -1;
private long folder = -1;
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
@ -77,7 +74,9 @@ public class FragmentRule extends FragmentBase {
// Get arguments // Get arguments
Bundle args = getArguments(); Bundle args = getArguments();
id = (args == null ? -1 : args.getLong("id", -1)); id = args.getLong("id", -1);
account = args.getLong("account", -1);
folder = args.getLong("folder", -1);
} }
@Override @Override
@ -89,11 +88,8 @@ public class FragmentRule extends FragmentBase {
etName = view.findViewById(R.id.etName); etName = view.findViewById(R.id.etName);
etOrder = view.findViewById(R.id.etOrder); etOrder = view.findViewById(R.id.etOrder);
cbEnabled = view.findViewById(R.id.cbEnabled); cbEnabled = view.findViewById(R.id.cbEnabled);
spAccount = view.findViewById(R.id.spAccount);
spFolder = view.findViewById(R.id.spFolder);
etSender = view.findViewById(R.id.etSender); etSender = view.findViewById(R.id.etSender);
etSubject = view.findViewById(R.id.etSubject); etSubject = view.findViewById(R.id.etSubject);
etText = view.findViewById(R.id.etText);
spAction = view.findViewById(R.id.spAction); spAction = view.findViewById(R.id.spAction);
spTarget = view.findViewById(R.id.spTarget); spTarget = view.findViewById(R.id.spTarget);
bottom_navigation = view.findViewById(R.id.bottom_navigation); bottom_navigation = view.findViewById(R.id.bottom_navigation);
@ -101,14 +97,6 @@ public class FragmentRule extends FragmentBase {
grpReady = view.findViewById(R.id.grpReady); grpReady = view.findViewById(R.id.grpReady);
grpMove = view.findViewById(R.id.grpMove); grpMove = view.findViewById(R.id.grpMove);
adapterAccount = new ArrayAdapter<>(getContext(), R.layout.spinner_item1, android.R.id.text1, new ArrayList<EntityAccount>());
adapterAccount.setDropDownViewResource(R.layout.spinner_item1_dropdown);
spAccount.setAdapter(adapterAccount);
adapterFolder = new ArrayAdapter<>(getContext(), R.layout.spinner_item1, android.R.id.text1, new ArrayList<EntityFolder>());
adapterFolder.setDropDownViewResource(R.layout.spinner_item1_dropdown);
spFolder.setAdapter(adapterFolder);
adapterAction = new ArrayAdapter<>(getContext(), R.layout.spinner_item1, android.R.id.text1, new ArrayList<Action>()); adapterAction = new ArrayAdapter<>(getContext(), R.layout.spinner_item1, android.R.id.text1, new ArrayList<Action>());
adapterAction.setDropDownViewResource(R.layout.spinner_item1_dropdown); adapterAction.setDropDownViewResource(R.layout.spinner_item1_dropdown);
spAction.setAdapter(adapterAction); spAction.setAdapter(adapterAction);
@ -123,19 +111,6 @@ public class FragmentRule extends FragmentBase {
actions.add(new Action(EntityRule.TYPE_MOVE, getString(R.string.title_move))); actions.add(new Action(EntityRule.TYPE_MOVE, getString(R.string.title_move)));
adapterAction.addAll(actions); adapterAction.addAll(actions);
spAccount.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> adapterView, View view, int position, long id) {
EntityAccount account = (EntityAccount) adapterView.getAdapter().getItem(position);
onAccountSelected(account.id);
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
onAccountSelected(-1);
}
});
spAction.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { spAction.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override @Override
public void onItemSelected(AdapterView<?> adapterView, View view, int position, long id) { public void onItemSelected(AdapterView<?> adapterView, View view, int position, long id) {
@ -190,18 +165,23 @@ public class FragmentRule extends FragmentBase {
public void onActivityCreated(@Nullable final Bundle savedInstanceState) { public void onActivityCreated(@Nullable final Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState); super.onActivityCreated(savedInstanceState);
new SimpleTask<List<EntityAccount>>() { Bundle args = new Bundle();
args.putLong("account", account);
new SimpleTask<List<EntityFolder>>() {
@Override @Override
protected List<EntityAccount> onExecute(Context context, Bundle args) { protected List<EntityFolder> onExecute(Context context, Bundle args) {
return DB.getInstance(context).account().getAccounts(true); long account = args.getLong("account");
return DB.getInstance(context).folder().getFolders(account);
} }
@Override @Override
protected void onExecuted(Bundle args, List<EntityAccount> accounts) { protected void onExecuted(Bundle args, List<EntityFolder> folders) {
if (accounts == null) if (folders == null)
accounts = new ArrayList<>(); folders = new ArrayList<>();
adapterAccount.addAll(accounts); adapterTarget.clear();
adapterTarget.addAll(folders);
Bundle rargs = new Bundle(); Bundle rargs = new Bundle();
rargs.putLong("id", id); rargs.putLong("id", id);
@ -224,7 +204,6 @@ public class FragmentRule extends FragmentBase {
cbEnabled.setChecked(rule == null ? true : rule.enabled); cbEnabled.setChecked(rule == null ? true : rule.enabled);
etSender.setText(jcondition.optString("sender")); etSender.setText(jcondition.optString("sender"));
etSubject.setText(jcondition.optString("subject")); etSubject.setText(jcondition.optString("subject"));
etText.setText(jcondition.optString("text"));
int type = jaction.optInt("type", -1); int type = jaction.optInt("type", -1);
for (int pos = 0; pos < adapterAction.getCount(); pos++) for (int pos = 0; pos < adapterAction.getCount(); pos++)
@ -233,26 +212,26 @@ public class FragmentRule extends FragmentBase {
break; break;
} }
bottom_navigation.findViewById(R.id.action_delete).setVisibility(rule == null ? View.GONE : View.VISIBLE);
if (rule == null) { if (rule == null) {
grpReady.setVisibility(View.VISIBLE); grpReady.setVisibility(View.VISIBLE);
bottom_navigation.setVisibility(View.VISIBLE); bottom_navigation.setVisibility(View.VISIBLE);
pbWait.setVisibility(View.GONE); pbWait.setVisibility(View.GONE);
} else { } else {
spAccount.setTag(rule.account); if (type == EntityRule.TYPE_MOVE) {
spFolder.setTag(rule.folder); long target = jaction.optLong("target", -1);
for (int pos = 0; pos < adapterTarget.getCount(); pos++)
if (type == EntityRule.TYPE_MOVE) if (adapterTarget.getItem(pos).id.equals(target)) {
spTarget.setTag(jaction.getLong("target")); spTarget.setSelection(pos);
break;
for (int pos = 0; pos < adapterAccount.getCount(); pos++) }
if (adapterAccount.getItem(pos).id.equals(rule.account)) { grpMove.setVisibility(View.VISIBLE);
spAccount.setSelection(pos); }
onAccountSelected(rule.account);
break;
}
} }
grpReady.setVisibility(View.VISIBLE);
bottom_navigation.findViewById(R.id.action_delete).setVisibility(rule == null ? View.GONE : View.VISIBLE);
bottom_navigation.setVisibility(View.VISIBLE);
pbWait.setVisibility(View.GONE);
} catch (JSONException ex) { } catch (JSONException ex) {
Log.e(ex); Log.e(ex);
} }
@ -269,58 +248,7 @@ public class FragmentRule extends FragmentBase {
protected void onException(Bundle args, Throwable ex) { protected void onException(Bundle args, Throwable ex) {
Helper.unexpectedError(getContext(), getViewLifecycleOwner(), ex); Helper.unexpectedError(getContext(), getViewLifecycleOwner(), ex);
} }
}.execute(this, null, "rule:accounts"); }.execute(this, args, "rule:accounts");
}
private void onAccountSelected(long account) {
Bundle args = new Bundle();
args.putLong("account", account);
new SimpleTask<List<EntityFolder>>() {
@Override
protected List<EntityFolder> onExecute(Context context, Bundle args) {
long account = args.getLong("account");
return DB.getInstance(context).folder().getFolders(account);
}
@Override
protected void onExecuted(Bundle args, List<EntityFolder> folders) {
adapterFolder.clear();
adapterFolder.addAll(folders);
adapterTarget.clear();
adapterTarget.addAll(folders);
long account = args.getLong("account");
if (account == (Long) spAccount.getTag()) {
Long folder = (Long) spFolder.getTag();
for (int pos = 0; pos < folders.size(); pos++)
if (folders.get(pos).id.equals(folder)) {
spFolder.setSelection(pos);
break;
}
Long target = (Long) spTarget.getTag();
for (int pos = 0; pos < folders.size(); pos++)
if (folders.get(pos).id.equals(target)) {
spTarget.setSelection(pos);
break;
}
} else {
spFolder.setSelection(0);
spTarget.setSelection(0);
}
grpReady.setVisibility(View.VISIBLE);
bottom_navigation.setVisibility(View.VISIBLE);
pbWait.setVisibility(View.GONE);
}
@Override
protected void onException(Bundle args, Throwable ex) {
Helper.unexpectedError(getContext(), getViewLifecycleOwner(), ex);
}
}.execute(FragmentRule.this, args, "rule:folders");
} }
private void onActionTrash() { private void onActionTrash() {
@ -370,19 +298,14 @@ public class FragmentRule extends FragmentBase {
try { try {
Helper.setViewsEnabled(view, false); Helper.setViewsEnabled(view, false);
EntityFolder folder = (EntityFolder) spFolder.getSelectedItem();
String sender = etSender.getText().toString(); String sender = etSender.getText().toString();
String subject = etSubject.getText().toString(); String subject = etSubject.getText().toString();
String text = etText.getText().toString();
JSONObject jcondition = new JSONObject(); JSONObject jcondition = new JSONObject();
if (!TextUtils.isEmpty(sender)) if (!TextUtils.isEmpty(sender))
jcondition.put("sender", sender); jcondition.put("sender", sender);
if (!TextUtils.isEmpty(subject)) if (!TextUtils.isEmpty(subject))
jcondition.put("subject", subject); jcondition.put("subject", subject);
if (!TextUtils.isEmpty(text))
jcondition.put("text", text);
Action action = (Action) spAction.getSelectedItem(); Action action = (Action) spAction.getSelectedItem();
@ -397,7 +320,7 @@ public class FragmentRule extends FragmentBase {
Bundle args = new Bundle(); Bundle args = new Bundle();
args.putLong("id", id); args.putLong("id", id);
args.putLong("folder", folder == null ? -1 : folder.id); args.putLong("folder", folder);
args.putString("name", etName.getText().toString()); args.putString("name", etName.getText().toString());
args.putString("order", etOrder.getText().toString()); args.putString("order", etOrder.getText().toString());
args.putBoolean("enabled", cbEnabled.isChecked()); args.putBoolean("enabled", cbEnabled.isChecked());

@ -45,10 +45,23 @@ public class FragmentRules extends FragmentBase {
private AdapterRule adapter; private AdapterRule adapter;
private long account;
private long folder;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Get arguments
Bundle args = getArguments();
account = args.getLong("account", -1);
folder = args.getLong("folder", -1);
}
@Override @Override
@Nullable @Nullable
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
setSubtitle(R.string.menu_rules); setSubtitle(R.string.title_edit_rules);
View view = inflater.inflate(R.layout.fragment_rules, container, false); View view = inflater.inflate(R.layout.fragment_rules, container, false);
@ -70,8 +83,15 @@ public class FragmentRules extends FragmentBase {
fab.setOnClickListener(new View.OnClickListener() { fab.setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View view) { public void onClick(View view) {
Bundle args = new Bundle();
args.putLong("account", account);
args.putLong("folder", folder);
FragmentRule fragment = new FragmentRule();
fragment.setArguments(args);
FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction(); FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.content_frame, new FragmentRule()).addToBackStack("rule"); fragmentTransaction.replace(R.id.content_frame, fragment).addToBackStack("rule");
fragmentTransaction.commit(); fragmentTransaction.commit();
} }
}); });
@ -88,7 +108,7 @@ public class FragmentRules extends FragmentBase {
super.onActivityCreated(savedInstanceState); super.onActivityCreated(savedInstanceState);
DB db = DB.getInstance(getContext()); DB db = DB.getInstance(getContext());
db.rule().liveRules().observe(getViewLifecycleOwner(), new Observer<List<TupleRuleEx>>() { db.rule().liveRules(folder).observe(getViewLifecycleOwner(), new Observer<List<TupleRuleEx>>() {
@Override @Override
public void onChanged(List<TupleRuleEx> rules) { public void onChanged(List<TupleRuleEx> rules) {
if (rules == null) if (rules == null)

@ -1027,7 +1027,9 @@ public class ServiceSynchronize extends LifecycleService {
db.beginTransaction(); db.beginTransaction();
message = synchronizeMessage( message = synchronizeMessage(
ServiceSynchronize.this, ServiceSynchronize.this,
folder, ifolder, (IMAPMessage) imessage, false); folder, ifolder, (IMAPMessage) imessage,
false,
db.rule().getEnabledRules(folder.id));
db.setTransactionSuccessful(); db.setTransactionSuccessful();
} finally { } finally {
db.endTransaction(); db.endTransaction();
@ -1038,8 +1040,7 @@ public class ServiceSynchronize extends LifecycleService {
downloadMessage(ServiceSynchronize.this, downloadMessage(ServiceSynchronize.this,
folder, ifolder, (IMAPMessage) imessage, folder, ifolder, (IMAPMessage) imessage,
message.id, message.id,
db.folder().getFolderDownload(folder.id), db.folder().getFolderDownload(folder.id));
db.rule().getEnabledRules(folder.id));
db.setTransactionSuccessful(); db.setTransactionSuccessful();
} finally { } finally {
db.endTransaction(); db.endTransaction();
@ -1116,7 +1117,9 @@ public class ServiceSynchronize extends LifecycleService {
db.beginTransaction(); db.beginTransaction();
message = synchronizeMessage( message = synchronizeMessage(
ServiceSynchronize.this, ServiceSynchronize.this,
folder, ifolder, (IMAPMessage) e.getMessage(), false); folder, ifolder, (IMAPMessage) e.getMessage(),
false,
db.rule().getEnabledRules(folder.id));
db.setTransactionSuccessful(); db.setTransactionSuccessful();
} finally { } finally {
db.endTransaction(); db.endTransaction();
@ -1127,8 +1130,7 @@ public class ServiceSynchronize extends LifecycleService {
downloadMessage(ServiceSynchronize.this, downloadMessage(ServiceSynchronize.this,
folder, ifolder, (IMAPMessage) e.getMessage(), folder, ifolder, (IMAPMessage) e.getMessage(),
message.id, message.id,
db.folder().getFolderDownload(folder.id), db.folder().getFolderDownload(folder.id));
db.rule().getEnabledRules(folder.id));
db.setTransactionSuccessful(); db.setTransactionSuccessful();
} finally { } finally {
db.endTransaction(); db.endTransaction();
@ -2232,6 +2234,8 @@ public class ServiceSynchronize extends LifecycleService {
Log.i(folder.name + " delete local uid=" + uid + " count=" + count); Log.i(folder.name + " delete local uid=" + uid + " count=" + count);
} }
List<EntityRule> rules = db.rule().getEnabledRules(folder.id);
fp.add(FetchProfile.Item.ENVELOPE); fp.add(FetchProfile.Item.ENVELOPE);
// fp.add(FetchProfile.Item.FLAGS); // fp.add(FetchProfile.Item.FLAGS);
fp.add(FetchProfile.Item.CONTENT_INFO); // body structure fp.add(FetchProfile.Item.CONTENT_INFO); // body structure
@ -2269,7 +2273,8 @@ public class ServiceSynchronize extends LifecycleService {
EntityMessage message = synchronizeMessage( EntityMessage message = synchronizeMessage(
this, this,
folder, ifolder, (IMAPMessage) isub[j], folder, ifolder, (IMAPMessage) isub[j],
false); false,
rules);
ids[from + j] = message.id; ids[from + j] = message.id;
db.setTransactionSuccessful(); db.setTransactionSuccessful();
} catch (MessageRemovedException ex) { } catch (MessageRemovedException ex) {
@ -2304,8 +2309,6 @@ public class ServiceSynchronize extends LifecycleService {
db.folder().setFolderSyncState(folder.id, "downloading"); db.folder().setFolderSyncState(folder.id, "downloading");
List<EntityRule> rules = db.rule().getEnabledRules(folder.id);
//fp.add(IMAPFolder.FetchProfileItem.MESSAGE); //fp.add(IMAPFolder.FetchProfileItem.MESSAGE);
// Download messages/attachments // Download messages/attachments
@ -2323,7 +2326,8 @@ public class ServiceSynchronize extends LifecycleService {
downloadMessage( downloadMessage(
this, this,
folder, ifolder, (IMAPMessage) isub[j], folder, ifolder, (IMAPMessage) isub[j],
ids[from + j], download, rules); ids[from + j],
download);
db.setTransactionSuccessful(); db.setTransactionSuccessful();
} catch (FolderClosedException ex) { } catch (FolderClosedException ex) {
throw ex; throw ex;
@ -2358,7 +2362,8 @@ public class ServiceSynchronize extends LifecycleService {
static EntityMessage synchronizeMessage( static EntityMessage synchronizeMessage(
Context context, Context context,
EntityFolder folder, IMAPFolder ifolder, IMAPMessage imessage, EntityFolder folder, IMAPFolder ifolder, IMAPMessage imessage,
boolean browsed) throws MessagingException, IOException { boolean browsed,
List<EntityRule> rules) throws MessagingException, IOException {
long uid = ifolder.getUID(imessage); long uid = ifolder.getUID(imessage);
if (imessage.isExpunged()) { if (imessage.isExpunged()) {
@ -2375,6 +2380,7 @@ public class ServiceSynchronize extends LifecycleService {
boolean answered = helper.getAnsered(); boolean answered = helper.getAnsered();
boolean flagged = helper.getFlagged(); boolean flagged = helper.getFlagged();
String[] keywords = helper.getKeywords(); String[] keywords = helper.getKeywords();
boolean filter = false;
DB db = DB.getInstance(context); DB db = DB.getInstance(context);
@ -2405,6 +2411,7 @@ public class ServiceSynchronize extends LifecycleService {
if (dup.uid == null) { if (dup.uid == null) {
Log.i(folder.name + " set uid=" + uid); Log.i(folder.name + " set uid=" + uid);
dup.uid = uid; dup.uid = uid;
filter = true;
} else if (dup.uid != uid) { } else if (dup.uid != uid) {
if (EntityFolder.DRAFTS.equals(folder.type)) { if (EntityFolder.DRAFTS.equals(folder.type)) {
Log.i(folder.name + " deleting previous uid=" + dup.uid); Log.i(folder.name + " deleting previous uid=" + dup.uid);
@ -2429,6 +2436,9 @@ public class ServiceSynchronize extends LifecycleService {
message = dup; message = dup;
} }
} }
if (message == null)
filter = true;
} }
if (message == null) { if (message == null) {
@ -2575,13 +2585,18 @@ public class ServiceSynchronize extends LifecycleService {
db.folder().setFolderKeywords(folder.id, DB.Converters.fromStringArray(fkeywords.toArray(new String[0]))); db.folder().setFolderKeywords(folder.id, DB.Converters.fromStringArray(fkeywords.toArray(new String[0])));
} }
if (filter)
for (EntityRule rule : rules)
if (rule.matches(context, message))
rule.execute(context, db, message);
return message; return message;
} }
static void downloadMessage( static void downloadMessage(
Context context, Context context,
EntityFolder folder, IMAPFolder ifolder, IMAPMessage imessage, EntityFolder folder, IMAPFolder ifolder, IMAPMessage imessage,
long id, boolean download, List<EntityRule> rules) throws MessagingException, IOException { long id, boolean download) throws MessagingException, IOException {
DB db = DB.getInstance(context); DB db = DB.getInstance(context);
EntityMessage message = db.message().getMessage(id); EntityMessage message = db.message().getMessage(id);
if (message == null) if (message == null)
@ -2590,7 +2605,7 @@ public class ServiceSynchronize extends LifecycleService {
if (message.setContactInfo(context)) if (message.setContactInfo(context))
db.message().updateMessage(message); db.message().updateMessage(message);
if (download || rules.size() > 0) { if (download) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
long maxSize = prefs.getInt("download", 32768); long maxSize = prefs.getInt("download", 32768);
if (maxSize == 0) if (maxSize == 0)
@ -2638,10 +2653,6 @@ public class ServiceSynchronize extends LifecycleService {
db.message().setMessageWarning(message.id, parts.getWarnings()); db.message().setMessageWarning(message.id, parts.getWarnings());
Log.i(folder.name + " downloaded message id=" + message.id + " size=" + message.size); Log.i(folder.name + " downloaded message id=" + message.id + " size=" + message.size);
} }
for (EntityRule rule : rules)
if (rule.matches(context, message))
rule.execute(context, db, message);
} }
for (int i = 0; i < attachments.size(); i++) { for (int i = 0; i < attachments.size(); i++) {

@ -229,10 +229,12 @@ public class ViewModelBrowse extends ViewModel {
EntityMessage message = db.message().getMessageByUid(state.fid, uid); EntityMessage message = db.message().getMessageByUid(state.fid, uid);
if (message == null) { if (message == null) {
message = ServiceSynchronize.synchronizeMessage(state.context, message = ServiceSynchronize.synchronizeMessage(state.context,
folder, state.ifolder, (IMAPMessage) isub[j], true); folder, state.ifolder, (IMAPMessage) isub[j],
true,
new ArrayList<EntityRule>());
ServiceSynchronize.downloadMessage(state.context, ServiceSynchronize.downloadMessage(state.context,
folder, state.ifolder, (IMAPMessage) isub[j], message.id, folder, state.ifolder, (IMAPMessage) isub[j], message.id,
false, new ArrayList<EntityRule>()); false);
count++; count++;
} }
db.message().setMessageFound(message.account, message.thread); db.message().setMessageFound(message.account, message.thread);

@ -67,56 +67,6 @@
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/etOrder" /> app:layout_constraintTop_toBottomOf="@id/etOrder" />
<!-- account -->
<TextView
android:id="@+id/tvAccount"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:text="@string/title_rule_account"
android:textAppearance="@style/TextAppearance.AppCompat.Small"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/cbEnabled" />
<Spinner
android:id="@+id/spAccount"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tvAccount" />
<!-- folder -->
<TextView
android:id="@+id/tvFolder"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:text="@string/title_rule_folder"
android:textAppearance="@style/TextAppearance.AppCompat.Small"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/spAccount" />
<Spinner
android:id="@+id/spFolder"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tvFolder" />
<TextView
android:id="@+id/tvFolderRemark"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/title_rule_folder_remark"
android:textAppearance="@style/TextAppearance.AppCompat.Small"
android:textStyle="italic"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/spFolder" />
<!-- condition --> <!-- condition -->
<TextView <TextView
@ -127,7 +77,7 @@
android:text="@string/title_rule_sender" android:text="@string/title_rule_sender"
android:textAppearance="@style/TextAppearance.AppCompat.Small" android:textAppearance="@style/TextAppearance.AppCompat.Small"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tvFolderRemark" /> app:layout_constraintTop_toBottomOf="@id/cbEnabled" />
<EditText <EditText
android:id="@+id/etSender" android:id="@+id/etSender"
@ -159,26 +109,6 @@
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tvSubject" /> app:layout_constraintTop_toBottomOf="@id/tvSubject" />
<TextView
android:id="@+id/tvText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:text="@string/title_rule_text"
android:textAppearance="@style/TextAppearance.AppCompat.Small"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/etSubject" />
<EditText
android:id="@+id/etText"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:inputType="textCapSentences"
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tvText" />
<TextView <TextView
android:id="@+id/tvAction" android:id="@+id/tvAction"
android:layout_width="wrap_content" android:layout_width="wrap_content"
@ -187,7 +117,7 @@
android:text="@string/title_rule_action" android:text="@string/title_rule_action"
android:textAppearance="@style/TextAppearance.AppCompat.Small" android:textAppearance="@style/TextAppearance.AppCompat.Small"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/etText" /> app:layout_constraintTop_toBottomOf="@id/etSubject" />
<Spinner <Spinner
android:id="@+id/spAction" android:id="@+id/spAction"

@ -21,25 +21,21 @@
android:maxLines="1" android:maxLines="1"
android:text="Name" android:text="Name"
android:textAppearance="@style/TextAppearance.AppCompat.Medium" android:textAppearance="@style/TextAppearance.AppCompat.Medium"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toStartOf="@+id/tvOrder"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" /> app:layout_constraintTop_toTopOf="parent" />
<TextView <TextView
android:id="@+id/tvFolder" android:id="@+id/tvOrder"
android:layout_width="0dp" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="6dp" android:layout_marginStart="6dp"
android:layout_marginTop="6dp" android:layout_marginTop="6dp"
android:layout_marginEnd="6dp" android:layout_marginEnd="6dp"
android:ellipsize="end" android:text="Order"
android:gravity="end" android:textAppearance="@style/TextAppearance.AppCompat.Medium"
android:maxLines="1"
android:text="Name"
android:textAppearance="@style/TextAppearance.AppCompat.Small"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" />
app:layout_constraintTop_toBottomOf="@id/tvName" />
<View <View
android:id="@+id/vSeparator" android:id="@+id/vSeparator"
@ -49,6 +45,6 @@
android:layout_marginBottom="6dp" android:layout_marginBottom="6dp"
android:background="?attr/colorSeparator" android:background="?attr/colorSeparator"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tvFolder" /> app:layout_constraintTop_toBottomOf="@id/tvName" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
</FrameLayout> </FrameLayout>

@ -50,7 +50,6 @@
<string name="menu_setup">Setup</string> <string name="menu_setup">Setup</string>
<string name="menu_answers">Templates</string> <string name="menu_answers">Templates</string>
<string name="menu_rules">Rules</string>
<string name="menu_operations">Operations</string> <string name="menu_operations">Operations</string>
<string name="menu_legend">Legend</string> <string name="menu_legend">Legend</string>
<string name="menu_faq">Support</string> <string name="menu_faq">Support</string>
@ -224,6 +223,7 @@
<string name="title_delete_local">Delete local messages</string> <string name="title_delete_local">Delete local messages</string>
<string name="title_empty_trash">Empty trash</string> <string name="title_empty_trash">Empty trash</string>
<string name="title_edit_properties">Edit properties</string> <string name="title_edit_properties">Edit properties</string>
<string name="title_edit_rules">Edit rules</string>
<string name="title_empty_trash_ask">Delete all trashed messages permanently?</string> <string name="title_empty_trash_ask">Delete all trashed messages permanently?</string>
<string name="title_delete_operation">Delete operations with an error message?</string> <string name="title_delete_operation">Delete operations with an error message?</string>
@ -382,17 +382,14 @@
<string name="title_answer_template_email">$email$ will be replaced by the sender email address</string> <string name="title_answer_template_email">$email$ will be replaced by the sender email address</string>
<string name="title_rule_name">Name</string> <string name="title_rule_name">Name</string>
<string name="title_rule_account">Account</string>
<string name="title_rule_folder">Folder</string>
<string name="title_rule_folder_remark">The texts of messages in the selected folder will always be downloaded</string>
<string name="title_rule_order">Order</string> <string name="title_rule_order">Order</string>
<string name="title_rule_enabled">Enabled</string> <string name="title_rule_enabled">Enabled</string>
<string name="title_rule_sender">Sender</string> <string name="title_rule_sender">Sender</string>
<string name="title_rule_subject">Subject</string> <string name="title_rule_subject">Subject</string>
<string name="title_rule_text">Text</string>
<string name="title_rule_action">Action</string> <string name="title_rule_action">Action</string>
<string name="title_rule_target">Target</string> <string name="title_rule_target">Target</string>
<string name="title_rule_seen">Mark as read</string> <string name="title_rule_seen">Mark as read</string>
<string name="title_rule_folder">Folder</string>
<string name="title_rule_name_missing">Rule name missing</string> <string name="title_rule_name_missing">Rule name missing</string>
<string name="title_action_seen">Mark read</string> <string name="title_action_seen">Mark read</string>

Loading…
Cancel
Save