1
0
Fork 0
mirror of https://github.com/M66B/FairEmail.git synced 2024-12-24 08:44:26 +00:00

Added account categories

This commit is contained in:
M66B 2021-10-03 21:45:18 +02:00
parent 8516de0491
commit 50af1c5fb5
11 changed files with 2746 additions and 6 deletions

File diff suppressed because it is too large Load diff

View file

@ -648,6 +648,13 @@ public class AdapterAccount extends RecyclerView.Adapter<AdapterAccount.ViewHold
return items.get(position).id;
}
public TupleAccountEx getItemAtPosition(int pos) {
if (pos >= 0 && pos < items.size())
return items.get(pos);
else
return null;
}
@Override
public int getItemCount() {
return items.size();

View file

@ -68,7 +68,7 @@ import io.requery.android.database.sqlite.SQLiteDatabase;
// https://developer.android.com/topic/libraries/architecture/room.html
@Database(
version = 212,
version = 213,
entities = {
EntityIdentity.class,
EntityAccount.class,
@ -2169,6 +2169,12 @@ public abstract class DB extends RoomDatabase {
Log.i("DB migration from version " + startVersion + " to " + endVersion);
db.execSQL("ALTER TABLE `search` ADD COLUMN `color` INTEGER");
}
}).addMigrations(new Migration(212, 213) {
@Override
public void migrate(@NonNull SupportSQLiteDatabase db) {
Log.i("DB migration from version " + startVersion + " to " + endVersion);
db.execSQL("ALTER TABLE `account` ADD COLUMN `category` TEXT");
}
}).addMigrations(new Migration(998, 999) {
@Override
public void migrate(@NonNull SupportSQLiteDatabase db) {

View file

@ -72,8 +72,9 @@ public interface DaoAccount {
" LEFT JOIN folder AS sent ON sent.account = account.id AND sent.type = '" + EntityFolder.SENT + "'" +
" WHERE :all OR account.synchronize" +
" GROUP BY account.id" +
" ORDER BY CASE WHEN :all THEN 0 ELSE account.`order` END" +
", CASE WHEN :all THEN 0 ELSE account.`primary` END DESC" +
" ORDER BY account.`order`" +
", account.`primary` DESC" +
", account.category COLLATE NOCASE" +
", account.name COLLATE NOCASE")
LiveData<List<TupleAccountEx>> liveAccountsEx(boolean all);

View file

@ -92,6 +92,7 @@ public class EntityAccount extends EntityOrder implements Serializable {
public String fingerprint;
public String name;
public String category;
public String signature; // obsolete
public Integer color;
@ -255,6 +256,7 @@ public class EntityAccount extends EntityOrder implements Serializable {
json.put("fingerprint", fingerprint);
json.put("name", name);
json.put("category", category);
json.put("color", color);
json.put("synchronize", synchronize);
@ -328,6 +330,8 @@ public class EntityAccount extends EntityOrder implements Serializable {
if (json.has("name") && !json.isNull("name"))
account.name = json.getString("name");
if (json.has("category") && !json.isNull("category"))
account.category = json.getString("category");
if (json.has("color"))
account.color = json.getInt("color");
@ -386,6 +390,7 @@ public class EntityAccount extends EntityOrder implements Serializable {
this.password.equals(other.password) &&
Objects.equals(this.realm, other.realm) &&
Objects.equals(this.name, other.name) &&
Objects.equals(this.category, other.category) &&
Objects.equals(this.color, other.color) &&
this.synchronize.equals(other.synchronize) &&
this.primary.equals(other.primary) &&

View file

@ -103,6 +103,7 @@ public class FragmentAccount extends FragmentBase {
private EditText etRealm;
private EditText etName;
private EditText etCategory;
private ViewButtonColor btnColor;
private TextView tvColorPro;
@ -209,6 +210,7 @@ public class FragmentAccount extends FragmentBase {
etRealm = view.findViewById(R.id.etRealm);
etName = view.findViewById(R.id.etName);
etCategory = view.findViewById(R.id.etCategory);
btnColor = view.findViewById(R.id.btnColor);
tvColorPro = view.findViewById(R.id.tvColorPro);
@ -859,6 +861,7 @@ public class FragmentAccount extends FragmentBase {
args.putString("fingerprint", cbTrust.isChecked() ? (String) cbTrust.getTag() : null);
args.putString("name", etName.getText().toString());
args.putString("category", etCategory.getText().toString());
args.putInt("color", btnColor.getColor());
args.putBoolean("synchronize", cbSynchronize.isChecked());
@ -922,6 +925,7 @@ public class FragmentAccount extends FragmentBase {
String fingerprint = args.getString("fingerprint");
String name = args.getString("name");
String category = args.getString("category");
Integer color = args.getInt("color");
boolean synchronize = args.getBoolean("synchronize");
@ -967,6 +971,8 @@ public class FragmentAccount extends FragmentBase {
realm = null;
if (TextUtils.isEmpty(name))
name = user;
if (TextUtils.isEmpty(category))
category = null;
if (color == Color.TRANSPARENT || !pro)
color = null;
if (!pro)
@ -1003,6 +1009,8 @@ public class FragmentAccount extends FragmentBase {
return true;
if (!Objects.equals(account.name, name))
return true;
if (!Objects.equals(account.category, category))
return true;
if (!Objects.equals(account.color, color))
return true;
if (!Objects.equals(account.synchronize, synchronize))
@ -1141,6 +1149,7 @@ public class FragmentAccount extends FragmentBase {
account.fingerprint = fingerprint;
account.name = name;
account.category = category;
account.color = color;
account.synchronize = synchronize;
@ -1491,6 +1500,7 @@ public class FragmentAccount extends FragmentBase {
}
etName.setText(account == null ? null : account.name);
etCategory.setText(account == null ? null : account.category);
btnColor.setColor(account == null ? null : account.color);
boolean pro = ActivityBilling.isPro(getContext());

View file

@ -19,12 +19,16 @@ package eu.faircode.email;
Copyright 2018-2021 by Marcel Bokhorst (M66B)
*/
import static androidx.recyclerview.widget.RecyclerView.NO_POSITION;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Rect;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.Menu;
@ -33,6 +37,7 @@ import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
@ -54,6 +59,7 @@ import com.google.android.material.snackbar.Snackbar;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import static eu.faircode.email.ServiceAuthenticator.AUTH_TYPE_PASSWORD;
@ -138,6 +144,72 @@ public class FragmentAccounts extends FragmentBase {
rvAccount.addItemDecoration(itemDecorator);
}
DividerItemDecoration dateDecorator = 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;
TupleAccountEx prev = adapter.getItemAtPosition(pos - 1);
TupleAccountEx account = adapter.getItemAtPosition(pos);
if (pos > 0 && prev == null)
return null;
if (account == null)
return null;
if (pos > 0) {
if (Objects.equals(prev.category, account.category))
return null;
} else {
if (account.category == null)
return null;
}
View header = inflater.inflate(R.layout.item_message_date, parent, false);
TextView tvDate = header.findViewById(R.id.tvDate);
if (cards) {
View vSeparatorDate = header.findViewById(R.id.vSeparatorDate);
vSeparatorDate.setVisibility(View.GONE);
}
tvDate.setText(account.category);
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;
}
};
rvAccount.addItemDecoration(dateDecorator);
adapter = new AdapterAccount(this, settings);
rvAccount.setAdapter(adapter);

View file

@ -80,6 +80,7 @@ public class FragmentPop extends FragmentBase {
private TextView tvPasswordStorage;
private EditText etName;
private EditText etCategory;
private ViewButtonColor btnColor;
private TextView tvColorPro;
@ -143,6 +144,7 @@ public class FragmentPop extends FragmentBase {
tvPasswordStorage = view.findViewById(R.id.tvPasswordStorage);
etName = view.findViewById(R.id.etName);
etCategory = view.findViewById(R.id.etCategory);
btnColor = view.findViewById(R.id.btnColor);
tvColorPro = view.findViewById(R.id.tvColorPro);
@ -306,6 +308,7 @@ public class FragmentPop extends FragmentBase {
args.putString("password", tilPassword.getEditText().getText().toString());
args.putString("name", etName.getText().toString());
args.putString("category", etCategory.getText().toString());
args.putInt("color", btnColor.getColor());
args.putBoolean("synchronize", cbSynchronize.isChecked());
@ -355,6 +358,7 @@ public class FragmentPop extends FragmentBase {
String password = args.getString("password");
String name = args.getString("name");
String category = args.getString("category");
Integer color = args.getInt("color");
boolean synchronize = args.getBoolean("synchronize");
@ -393,6 +397,8 @@ public class FragmentPop extends FragmentBase {
if (TextUtils.isEmpty(name))
name = user;
if (TextUtils.isEmpty(category))
category = null;
if (color == Color.TRANSPARENT || !pro)
color = null;
if (!pro)
@ -421,6 +427,8 @@ public class FragmentPop extends FragmentBase {
return true;
if (!Objects.equals(account.name, name))
return true;
if (!Objects.equals(account.category, category))
return true;
if (!Objects.equals(account.color, color))
return true;
if (!Objects.equals(account.synchronize, synchronize))
@ -505,6 +513,7 @@ public class FragmentPop extends FragmentBase {
account.password = password;
account.name = name;
account.category = category;
account.color = color;
account.synchronize = synchronize;
@ -728,6 +737,7 @@ public class FragmentPop extends FragmentBase {
tilPassword.getEditText().setText(account == null ? null : account.password);
etName.setText(account == null ? null : account.name);
etCategory.setText(account == null ? null : account.category);
btnColor.setColor(account == null ? null : account.color);
cbSynchronize.setChecked(account == null ? true : account.synchronize);

View file

@ -392,6 +392,26 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tvNameRemark" />
<eu.faircode.email.FixedTextView
android:id="@+id/tvCategory"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:text="@string/title_account_category"
android:textAppearance="@style/TextAppearance.AppCompat.Small"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/etName" />
<eu.faircode.email.EditTextPlain
android:id="@+id/etCategory"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/title_optional"
android:inputType="textCapSentences|textAutoCorrect"
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tvCategory" />
<eu.faircode.email.FixedTextView
android:id="@+id/tvColor"
android:layout_width="wrap_content"
@ -400,7 +420,7 @@
android:text="@string/title_color"
android:textAppearance="@style/TextAppearance.AppCompat.Small"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/etName" />
app:layout_constraintTop_toBottomOf="@id/etCategory" />
<eu.faircode.email.ViewButtonColor
android:id="@+id/btnColor"
@ -1018,7 +1038,7 @@
tvUser,etUser,tvPassword,tilPassword,tvCaseSensitive,tvAppPassword,tvPasswordStorage,
btnCertificate,tvCertificate,
tvRealm,etRealm,
tvName,tvNameRemark,etName,
tvName,tvNameRemark,etName,etCategory,
tvColor,btnColor,tvColorHint,tvColorPro" />
<androidx.constraintlayout.widget.Group

View file

@ -264,6 +264,26 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tvNameRemark" />
<eu.faircode.email.FixedTextView
android:id="@+id/tvCategory"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:text="@string/title_account_category"
android:textAppearance="@style/TextAppearance.AppCompat.Small"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/etName" />
<eu.faircode.email.EditTextPlain
android:id="@+id/etCategory"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/title_optional"
android:inputType="textCapSentences|textAutoCorrect"
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tvCategory" />
<eu.faircode.email.FixedTextView
android:id="@+id/tvColor"
android:layout_width="wrap_content"
@ -272,7 +292,7 @@
android:text="@string/title_color"
android:textAppearance="@style/TextAppearance.AppCompat.Small"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/etName" />
app:layout_constraintTop_toBottomOf="@id/etCategory" />
<eu.faircode.email.ViewButtonColor
android:id="@+id/btnColor"

View file

@ -784,6 +784,7 @@
<string name="title_recommended">Recommended</string>
<string name="title_account_linked">Linked account</string>
<string name="title_account_name">Account name</string>
<string name="title_account_category">Category</string>
<string name="title_account_name_hint">Used to differentiate folders</string>
<string name="title_account_interval_hint">Frequency of refreshing the connection for push messages or frequency of checking for new messages</string>
<string name="title_account_partial_fetch_hint">Disable this only in case of empty messages or corrupt attachments</string>