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:
parent
8516de0491
commit
50af1c5fb5
11 changed files with 2746 additions and 6 deletions
2588
app/schemas/eu.faircode.email.DB/213.json
Normal file
2588
app/schemas/eu.faircode.email.DB/213.json
Normal file
File diff suppressed because it is too large
Load diff
|
@ -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();
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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) &&
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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>
|
||||
|
|
Loading…
Reference in a new issue