Added rule groups

This commit is contained in:
M66B 2023-04-01 18:46:05 +02:00
parent f62fa2ee4c
commit 920fb87dbf
8 changed files with 3079 additions and 2 deletions

File diff suppressed because it is too large Load Diff

View File

@ -709,6 +709,13 @@ public class AdapterRule extends RecyclerView.Adapter<AdapterRule.ViewHolder> {
return selected.get(position).id;
}
public EntityRule getItemAtPosition(int pos) {
if (pos >= 0 && pos < selected.size())
return selected.get(pos);
else
return null;
}
@Override
public int getItemCount() {
return selected.size();

View File

@ -68,7 +68,7 @@ import javax.mail.internet.InternetAddress;
// https://developer.android.com/topic/libraries/architecture/room.html
@Database(
version = 277,
version = 278,
entities = {
EntityIdentity.class,
EntityAccount.class,
@ -2799,6 +2799,12 @@ public abstract class DB extends RoomDatabase {
logMigration(startVersion, endVersion);
db.execSQL("ALTER TABLE `identity` ADD COLUMN `uri` TEXT");
}
}).addMigrations(new Migration(277, 278) {
@Override
public void migrate(@NonNull SupportSQLiteDatabase db) {
logMigration(startVersion, endVersion);
db.execSQL("ALTER TABLE `rule` ADD COLUMN `group` TEXT");
}
}).addMigrations(new Migration(998, 999) {
@Override
public void migrate(@NonNull SupportSQLiteDatabase db) {

View File

@ -92,6 +92,7 @@ public class EntityRule {
public Long folder;
@NonNull
public String name;
public String group;
@NonNull
public int order;
@NonNull
@ -1388,6 +1389,7 @@ public class EntityRule {
return Objects.equals(this.uuid, other.uuid) &&
this.folder.equals(other.folder) &&
this.name.equals(other.name) &&
Objects.equals(this.group, other.group) &&
this.order == other.order &&
this.enabled == other.enabled &&
this.daily == other.daily &&
@ -1440,6 +1442,7 @@ public class EntityRule {
json.put("id", id);
json.put("uuid", uuid);
json.put("name", name);
json.put("group", group);
json.put("order", order);
json.put("enabled", enabled);
json.put("daily", daily);
@ -1457,6 +1460,7 @@ public class EntityRule {
if (json.has("uuid"))
rule.uuid = json.getString("uuid");
rule.name = json.getString("name");
rule.group = json.getString("group");
rule.order = json.getInt("order");
rule.enabled = json.getBoolean("enabled");
rule.daily = json.optBoolean("daily");

View File

@ -86,6 +86,7 @@ public class FragmentRule extends FragmentBase {
private TextView tvFolder;
private EditText etName;
private EditText etGroup;
private EditText etOrder;
private CheckBox cbEnabled;
private CheckBox cbDaily;
@ -268,6 +269,7 @@ public class FragmentRule extends FragmentBase {
tvFolder = view.findViewById(R.id.tvFolder);
etName = view.findViewById(R.id.etName);
etGroup = view.findViewById(R.id.etGroup);
etOrder = view.findViewById(R.id.etOrder);
cbEnabled = view.findViewById(R.id.cbEnabled);
cbDaily = view.findViewById(R.id.cbDaily);
@ -1168,6 +1170,7 @@ public class FragmentRule extends FragmentBase {
JSONObject jschedule = jcondition.optJSONObject("schedule");
etName.setText(rule == null ? args.getString("subject") : rule.name);
etGroup.setText(rule == null ? null : rule.group);
etOrder.setText(rule == null ? null : Integer.toString(rule.order));
cbEnabled.setChecked(rule == null || rule.enabled);
cbDaily.setChecked(rule != null && rule.daily);
@ -1403,6 +1406,7 @@ public class FragmentRule extends FragmentBase {
args.putLong("id", id);
args.putLong("folder", folder);
args.putString("name", etName.getText().toString());
args.putString("group", etGroup.getText().toString().trim());
args.putString("order", etOrder.getText().toString());
args.putBoolean("enabled", cbEnabled.isChecked());
args.putBoolean("daily", cbDaily.isChecked());
@ -1426,6 +1430,7 @@ public class FragmentRule extends FragmentBase {
long id = args.getLong("id");
long folder = args.getLong("folder");
String name = args.getString("name");
String group = args.getString("group");
String order = args.getString("order");
boolean enabled = args.getBoolean("enabled");
boolean daily = args.getBoolean("daily");
@ -1436,6 +1441,9 @@ public class FragmentRule extends FragmentBase {
if (TextUtils.isEmpty(name))
throw new IllegalArgumentException(context.getString(R.string.title_rule_name_missing));
if (TextUtils.isEmpty(group))
group = null;
JSONObject jcondition = new JSONObject(condition);
JSONObject jsender = jcondition.optJSONObject("sender");
JSONObject jrecipient = jcondition.optJSONObject("recipient");
@ -1463,6 +1471,7 @@ public class FragmentRule extends FragmentBase {
EntityRule rule = new EntityRule();
rule.folder = folder;
rule.name = name;
rule.group = group;
rule.order = Integer.parseInt(order);
rule.enabled = enabled;
rule.daily = daily;
@ -1475,6 +1484,7 @@ public class FragmentRule extends FragmentBase {
EntityRule rule = db.rule().getRule(id);
rule.folder = folder;
rule.name = name;
rule.group = group;
rule.order = Integer.parseInt(order);
rule.enabled = enabled;
rule.daily = daily;

View File

@ -21,10 +21,14 @@ package eu.faircode.email;
import static android.app.Activity.RESULT_OK;
import static androidx.recyclerview.widget.RecyclerView.NO_POSITION;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.net.Uri;
import android.os.Bundle;
import android.text.TextUtils;
@ -34,6 +38,7 @@ import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
@ -67,6 +72,7 @@ import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;
public class FragmentRules extends FragmentBase {
private long account;
@ -75,6 +81,7 @@ public class FragmentRules extends FragmentBase {
private String type;
private boolean cards;
private boolean dividers;
private View view;
private RecyclerView rvRule;
@ -105,6 +112,7 @@ public class FragmentRules extends FragmentBase {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getContext());
cards = prefs.getBoolean("cards", true);
dividers = prefs.getBoolean("dividers", true);
}
@Override
@ -127,6 +135,77 @@ public class FragmentRules extends FragmentBase {
LinearLayoutManager llm = new LinearLayoutManager(getContext());
rvRule.setLayoutManager(llm);
DividerItemDecoration groupDecorator = new DividerItemDecoration(getContext(), llm.getOrientation()) {
@Override
public void onDraw(@NonNull Canvas canvas, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {
int count = parent.getChildCount();
for (int i = 0; i < count; i++) {
View view = parent.getChildAt(i);
int pos = parent.getChildAdapterPosition(view);
View header = getView(view, parent, pos);
if (header != null) {
canvas.save();
canvas.translate(0, parent.getChildAt(i).getTop() - header.getMeasuredHeight());
header.draw(canvas);
canvas.restore();
}
}
}
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
int pos = parent.getChildAdapterPosition(view);
View header = getView(view, parent, pos);
if (header == null)
outRect.setEmpty();
else
outRect.top = header.getMeasuredHeight();
}
private View getView(View view, RecyclerView parent, int pos) {
if (pos == NO_POSITION)
return null;
if (!getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.STARTED))
return null;
EntityRule prev = adapter.getItemAtPosition(pos - 1);
EntityRule rule = adapter.getItemAtPosition(pos);
if (pos > 0 && prev == null)
return null;
if (rule == null)
return null;
if (pos > 0) {
if (Objects.equals(prev.group, rule.group))
return null;
} else {
if (rule.group == null)
return null;
}
View header = inflater.inflate(R.layout.item_group, parent, false);
TextView tvCategory = header.findViewById(R.id.tvCategory);
TextView tvDate = header.findViewById(R.id.tvDate);
if (cards || !dividers) {
View vSeparator = header.findViewById(R.id.vSeparator);
vSeparator.setVisibility(View.GONE);
}
tvCategory.setText(rule.group);
tvDate.setVisibility(View.GONE);
header.measure(View.MeasureSpec.makeMeasureSpec(parent.getWidth(), View.MeasureSpec.EXACTLY),
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
header.layout(0, 0, header.getMeasuredWidth(), header.getMeasuredHeight());
return header;
}
};
rvRule.addItemDecoration(groupDecorator);
adapter = new AdapterRule(this);
rvRule.setAdapter(adapter);

View File

@ -70,6 +70,27 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tvName" />
<TextView
android:id="@+id/tvGroup"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:labelFor="@+id/etName"
android:text="@string/title_rule_group"
android:textAppearance="@style/TextAppearance.AppCompat.Small"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/etName" />
<eu.faircode.email.EditTextPlain
android:id="@+id/etGroup"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:inputType="textCapSentences|textAutoCorrect"
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tvGroup" />
<TextView
android:id="@+id/tvOrder"
android:layout_width="wrap_content"
@ -78,7 +99,7 @@
android:text="@string/title_rule_order"
android:textAppearance="@style/TextAppearance.AppCompat.Small"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/etName" />
app:layout_constraintTop_toBottomOf="@id/etGroup" />
<eu.faircode.email.EditTextPlain
android:id="@+id/etOrder"

View File

@ -1860,6 +1860,7 @@
<string name="title_rule_caption">Edit rule</string>
<string name="title_rule_title">Rule applies to</string>
<string name="title_rule_name">Name</string>
<string name="title_rule_group">Group</string>
<string name="title_rule_order">Order</string>
<string name="title_rule_enabled">Enabled</string>
<string name="title_rule_daily">Run daily (only)</string>