diff --git a/CHANGELOG.md b/CHANGELOG.md index 5e0f29b19a..9c209b292e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,11 @@ For support you can use [the contact form](https://contact.faircode.eu/?product= ### [Ubirajara](https://en.wikipedia.org/wiki/Ubirajara_jubatus) +### Next version + +* Added rule action to add local notes +* Updated [translations](https://crowdin.com/project/open-source-email) + ### 1.2093 - 2023-08-14 * Small improvements and minor bug fixes diff --git a/FAQ.md b/FAQ.md index 3b7345a562..ba18d8b03c 100644 --- a/FAQ.md +++ b/FAQ.md @@ -2676,6 +2676,7 @@ You can select one of these actions to apply to matching messages: * Add star * Set importance (local priority) * Add keyword +* Add local notes (since version 1.2094) * Move * Copy (Gmail: label) * Delete permanently (since version 1.1801) diff --git a/app/src/main/assets/CHANGELOG.md b/app/src/main/assets/CHANGELOG.md index 5e0f29b19a..9c209b292e 100644 --- a/app/src/main/assets/CHANGELOG.md +++ b/app/src/main/assets/CHANGELOG.md @@ -6,6 +6,11 @@ For support you can use [the contact form](https://contact.faircode.eu/?product= ### [Ubirajara](https://en.wikipedia.org/wiki/Ubirajara_jubatus) +### Next version + +* Added rule action to add local notes +* Updated [translations](https://crowdin.com/project/open-source-email) + ### 1.2093 - 2023-08-14 * Small improvements and minor bug fixes diff --git a/app/src/main/java/eu/faircode/email/AdapterRule.java b/app/src/main/java/eu/faircode/email/AdapterRule.java index 5807b5f864..87806364e8 100644 --- a/app/src/main/java/eu/faircode/email/AdapterRule.java +++ b/app/src/main/java/eu/faircode/email/AdapterRule.java @@ -207,6 +207,9 @@ public class AdapterRule extends RecyclerView.Adapter { resend = jaction.optBoolean("resend"); setAction(resend ? R.string.title_rule_resend : getAction(type), to); } + } else if (type == EntityRule.TYPE_NOTES) { + String notes = jaction.getString("notes"); + setAction(getAction(type), notes); } else setAction(getAction(type), null); @@ -557,6 +560,8 @@ public class AdapterRule extends RecyclerView.Adapter { return R.string.title_rule_sound; case EntityRule.TYPE_LOCAL_ONLY: return R.string.title_rule_local_only; + case EntityRule.TYPE_NOTES: + return R.string.title_rule_notes; default: throw new IllegalArgumentException("Unknown action type=" + type); } diff --git a/app/src/main/java/eu/faircode/email/EntityRule.java b/app/src/main/java/eu/faircode/email/EntityRule.java index c282e949be..94cee8b0d4 100644 --- a/app/src/main/java/eu/faircode/email/EntityRule.java +++ b/app/src/main/java/eu/faircode/email/EntityRule.java @@ -126,6 +126,7 @@ public class EntityRule { static final int TYPE_DELETE = 15; static final int TYPE_SOUND = 16; static final int TYPE_LOCAL_ONLY = 17; + static final int TYPE_NOTES = 18; static final String ACTION_AUTOMATION = BuildConfig.APPLICATION_ID + ".AUTOMATION"; static final String EXTRA_RULE = "rule"; @@ -603,6 +604,8 @@ public class EntityRule { return onActionSound(context, message, jaction); case TYPE_LOCAL_ONLY: return onActionLocalOnly(context, message, jaction); + case TYPE_NOTES: + return onActionNotes(context, message, jaction); default: throw new IllegalArgumentException("Unknown rule type=" + type + " name=" + name); } @@ -681,6 +684,11 @@ public class EntityRule { return; case TYPE_LOCAL_ONLY: return; + case TYPE_NOTES: + String notes = jargs.optString("notes"); + if (TextUtils.isEmpty(notes)) + throw new IllegalArgumentException(context.getString(R.string.title_rule_notes_missing)); + return; default: throw new IllegalArgumentException("Unknown rule type=" + type); } @@ -1317,6 +1325,16 @@ public class EntityRule { return true; } + private boolean onActionNotes(Context context, EntityMessage message, JSONObject jargs) throws JSONException { + String notes = jargs.getString("notes"); + Integer color = (jargs.has("color") ? jargs.getInt("color") : null); + + DB db = DB.getInstance(context); + db.message().setMessageNotes(message.id, notes, color); + + return true; + } + private static Calendar getRelativeCalendar(boolean all, int minutes, long reference) { int d = minutes / (24 * 60); int h = minutes / 60 % 24; diff --git a/app/src/main/java/eu/faircode/email/FragmentRule.java b/app/src/main/java/eu/faircode/email/FragmentRule.java index 7cb4f0674c..1fc72f7d69 100644 --- a/app/src/main/java/eu/faircode/email/FragmentRule.java +++ b/app/src/main/java/eu/faircode/email/FragmentRule.java @@ -169,6 +169,9 @@ public class FragmentRule extends FragmentBase { private TextView tvAutomation; + private EditText etNotes; + private ViewButtonColor btnColorNotes; + private BottomNavigationView bottom_navigation; private ContentLoadingProgressBar pbWait; @@ -186,6 +189,7 @@ public class FragmentRule extends FragmentBase { private Group grpAutomation; private Group grpDelete; private Group grpLocalOnly; + private Group grpNotes; private ArrayAdapter adapterGroup; private ArrayAdapter adapterDay; @@ -215,6 +219,7 @@ public class FragmentRule extends FragmentBase { private final static int REQUEST_DATE_AFTER = 11; private final static int REQUEST_DATE_BEFORE = 12; private final static int REQUEST_FOLDER = 13; + private final static int REQUEST_COLOR_NOTES = 14; private static final List HEADER_CONDITIONS = Collections.unmodifiableList(Arrays.asList( "$$seen$", @@ -354,6 +359,9 @@ public class FragmentRule extends FragmentBase { tvAutomation = view.findViewById(R.id.tvAutomation); + etNotes = view.findViewById(R.id.etNotes); + btnColorNotes = view.findViewById(R.id.btnColorNotes); + bottom_navigation = view.findViewById(R.id.bottom_navigation); pbWait = view.findViewById(R.id.pbWait); @@ -372,6 +380,7 @@ public class FragmentRule extends FragmentBase { grpAutomation = view.findViewById(R.id.grpAutomation); grpDelete = view.findViewById(R.id.grpDelete); grpLocalOnly = view.findViewById(R.id.grpLocalOnly); + grpNotes = view.findViewById(R.id.grpNotes); adapterGroup = new ArrayAdapter<>(getContext(), R.layout.spinner_item1_dropdown, android.R.id.text1); etGroup.setThreshold(1); @@ -625,8 +634,10 @@ public class FragmentRule extends FragmentBase { actions.add(new Action(EntityRule.TYPE_SNOOZE, getString(R.string.title_rule_snooze))); actions.add(new Action(EntityRule.TYPE_FLAG, getString(R.string.title_rule_flag))); actions.add(new Action(EntityRule.TYPE_IMPORTANCE, getString(R.string.title_rule_importance))); - if (protocol == EntityAccount.TYPE_IMAP) { + if (protocol == EntityAccount.TYPE_IMAP) actions.add(new Action(EntityRule.TYPE_KEYWORD, getString(R.string.title_rule_keyword))); + actions.add(new Action(EntityRule.TYPE_NOTES, getString(R.string.title_rule_notes))); + if (protocol == EntityAccount.TYPE_IMAP) { actions.add(new Action(EntityRule.TYPE_MOVE, getString(R.string.title_rule_move))); actions.add(new Action(EntityRule.TYPE_COPY, getString(R.string.title_rule_copy))); } @@ -787,6 +798,21 @@ public class FragmentRule extends FragmentBase { EntityRule.EXTRA_SENDER, EntityRule.EXTRA_SUBJECT}))); + btnColorNotes.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Bundle args = new Bundle(); + args.putInt("color", btnColorNotes.getColor()); + args.putString("title", getString(R.string.title_rule_notes)); + args.putBoolean("reset", true); + + FragmentDialogColor fragment = new FragmentDialogColor(); + fragment.setArguments(args); + fragment.setTargetFragment(FragmentRule.this, REQUEST_COLOR_NOTES); + fragment.show(getParentFragmentManager(), "rule:color:notes"); + } + }); + bottom_navigation.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() { @Override public boolean onNavigationItemSelected(@NonNull MenuItem menuItem) { @@ -822,6 +848,7 @@ public class FragmentRule extends FragmentBase { grpAutomation.setVisibility(View.GONE); grpDelete.setVisibility(View.GONE); grpLocalOnly.setVisibility(View.GONE); + grpNotes.setVisibility(View.GONE); pbWait.setVisibility(View.VISIBLE); @@ -991,6 +1018,12 @@ public class FragmentRule extends FragmentBase { if (resultCode == RESULT_OK && data != null) onFolderSelected(data.getBundleExtra("args")); break; + case REQUEST_COLOR_NOTES: + if (resultCode == RESULT_OK && data != null) { + Bundle args = data.getBundleExtra("args"); + btnColorNotes.setColor(args.getInt("color")); + } + break; } } catch (Throwable ex) { Log.e(ex); @@ -1319,6 +1352,13 @@ public class FragmentRule extends FragmentBase { etAlarmDuration.setEnabled(alarm); etAlarmDuration.setText(duration == 0 ? null : Integer.toString(duration)); break; + + case EntityRule.TYPE_NOTES: + etNotes.setText(jaction.getString("notes")); + btnColorNotes.setColor( + !jaction.has("color") || jaction.isNull("color") + ? null : jaction.getInt("color")); + break; } for (int pos = 0; pos < adapterAction.getCount(); pos++) @@ -1376,6 +1416,7 @@ public class FragmentRule extends FragmentBase { grpAutomation.setVisibility(type == EntityRule.TYPE_AUTOMATION ? View.VISIBLE : View.GONE); grpDelete.setVisibility(type == EntityRule.TYPE_DELETE ? View.VISIBLE : View.GONE); grpLocalOnly.setVisibility(type == EntityRule.TYPE_LOCAL_ONLY ? View.VISIBLE : View.GONE); + grpNotes.setVisibility(type == EntityRule.TYPE_NOTES ? View.VISIBLE : View.GONE); } private void onActionDelete() { @@ -1706,6 +1747,13 @@ public class FragmentRule extends FragmentBase { Log.e(ex); } break; + + case EntityRule.TYPE_NOTES: + jaction.put("notes", etNotes.getText().toString()); + int ncolor = btnColorNotes.getColor(); + if (ncolor != Color.TRANSPARENT) + jaction.put("color", ncolor); + break; } } diff --git a/app/src/main/res/layout/fragment_rule.xml b/app/src/main/res/layout/fragment_rule.xml index bf4808392f..501be8107c 100644 --- a/app/src/main/res/layout/fragment_rule.xml +++ b/app/src/main/res/layout/fragment_rule.xml @@ -1239,6 +1239,48 @@ app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/tvDelete" /> + + + + + + + + + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 5503d235ac..556be12069 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1895,6 +1895,7 @@ Keyword Add Delete + Local notes Move Copy (label) Reply/forward @@ -1955,6 +1956,7 @@ Template missing Keyword missing This will send the intent \'%1$s\' with the extras \'%2$s\' + Local notes missing Permanent deletion is irreversible, so make sure the rule conditions are correct! Try to avoid bridging notifications to other devices, such as smartwatches. Not all devices support this. Edit group … diff --git a/metadata/en-US/changelogs/2093.txt b/metadata/en-US/changelogs/2093.txt index 89c15a8041..c1e421be30 100644 --- a/metadata/en-US/changelogs/2093.txt +++ b/metadata/en-US/changelogs/2093.txt @@ -6,6 +6,11 @@ For support you can use the contact form. Ubirajara +Next version + +* Added rule action to add local notes +* Updated translations + 1.2093 - 2023-08-14 * Small improvements and minor bug fixes