mirror of
https://github.com/M66B/FairEmail.git
synced 2026-01-03 11:28:41 +01:00
Allow account ordering
This commit is contained in:
@@ -84,14 +84,10 @@ import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URL;
|
||||
import java.text.Collator;
|
||||
import java.text.NumberFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
import java.util.Properties;
|
||||
|
||||
@@ -291,16 +287,6 @@ public class ActivityView extends ActivityBilling implements FragmentManager.OnB
|
||||
if (accounts == null)
|
||||
accounts = new ArrayList<>();
|
||||
|
||||
final Collator collator = Collator.getInstance(Locale.getDefault());
|
||||
collator.setStrength(Collator.SECONDARY); // Case insensitive, process accents etc
|
||||
|
||||
Collections.sort(accounts, new Comparator<EntityAccount>() {
|
||||
@Override
|
||||
public int compare(EntityAccount a1, EntityAccount a2) {
|
||||
return collator.compare(a1.name, a2.name);
|
||||
}
|
||||
});
|
||||
|
||||
boolean changed = false;
|
||||
if (last.size() == accounts.size()) {
|
||||
for (int i = 0; i < accounts.size(); i++) {
|
||||
|
||||
@@ -23,6 +23,7 @@ import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Typeface;
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
@@ -31,23 +32,22 @@ import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.constraintlayout.widget.Group;
|
||||
import androidx.lifecycle.LifecycleOwner;
|
||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
||||
import androidx.recyclerview.widget.DiffUtil;
|
||||
import androidx.recyclerview.widget.ListUpdateCallback;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import java.text.Collator;
|
||||
import java.text.DateFormat;
|
||||
import java.text.NumberFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
public class AdapterAccount extends RecyclerView.Adapter<AdapterAccount.ViewHolder> {
|
||||
private Context context;
|
||||
private LifecycleOwner owner;
|
||||
private boolean settings;
|
||||
private LayoutInflater inflater;
|
||||
|
||||
@@ -167,8 +167,9 @@ public class AdapterAccount extends RecyclerView.Adapter<AdapterAccount.ViewHold
|
||||
}
|
||||
}
|
||||
|
||||
AdapterAccount(Context context, boolean settings) {
|
||||
AdapterAccount(Context context, LifecycleOwner owner, boolean settings) {
|
||||
this.context = context;
|
||||
this.owner = owner;
|
||||
this.settings = settings;
|
||||
this.inflater = LayoutInflater.from(context);
|
||||
|
||||
@@ -181,22 +182,6 @@ public class AdapterAccount extends RecyclerView.Adapter<AdapterAccount.ViewHold
|
||||
public void set(@NonNull List<TupleAccountEx> accounts) {
|
||||
Log.i("Set accounts=" + accounts.size());
|
||||
|
||||
final Collator collator = Collator.getInstance(Locale.getDefault());
|
||||
collator.setStrength(Collator.SECONDARY); // Case insensitive, process accents etc
|
||||
|
||||
Collections.sort(accounts, new Comparator<TupleAccountEx>() {
|
||||
@Override
|
||||
public int compare(TupleAccountEx a1, TupleAccountEx a2) {
|
||||
int n = collator.compare(a1.name, a2.name);
|
||||
if (n != 0)
|
||||
return n;
|
||||
int e = collator.compare(a1.user, a2.user);
|
||||
if (e != 0)
|
||||
return e;
|
||||
return a1.id.compareTo(a2.id);
|
||||
}
|
||||
});
|
||||
|
||||
DiffUtil.DiffResult diff = DiffUtil.calculateDiff(new DiffCallback(items, accounts), false);
|
||||
|
||||
items = accounts;
|
||||
@@ -269,6 +254,47 @@ public class AdapterAccount extends RecyclerView.Adapter<AdapterAccount.ViewHold
|
||||
return items.size();
|
||||
}
|
||||
|
||||
void onMove(int from, int to) {
|
||||
if (from < to)
|
||||
for (int i = from; i < to; i++)
|
||||
Collections.swap(items, i, i + 1);
|
||||
else
|
||||
for (int i = from; i > to; i--)
|
||||
Collections.swap(items, i, i - 1);
|
||||
notifyItemMoved(from, to);
|
||||
|
||||
List<Long> order = new ArrayList<>();
|
||||
for (int i = 0; i < items.size(); i++)
|
||||
order.add(items.get(i).id);
|
||||
|
||||
Bundle args = new Bundle();
|
||||
args.putLongArray("order", Helper.toLongArray(order));
|
||||
|
||||
new SimpleTask<Void>() {
|
||||
@Override
|
||||
protected Void onExecute(Context context, Bundle args) {
|
||||
final long[] order = args.getLongArray("order");
|
||||
|
||||
final DB db = DB.getInstance(context);
|
||||
db.runInTransaction(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
for (int i = 0; i < order.length; i++)
|
||||
db.account().setAccountOrder(order[i], i);
|
||||
}
|
||||
});
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onException(Bundle args, Throwable ex) {
|
||||
Helper.unexpectedError(context, owner, ex);
|
||||
|
||||
}
|
||||
}.execute(context, owner, args, "accounts:order");
|
||||
}
|
||||
|
||||
@Override
|
||||
@NonNull
|
||||
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
|
||||
@@ -51,7 +51,7 @@ import io.requery.android.database.sqlite.RequerySQLiteOpenHelperFactory;
|
||||
// https://developer.android.com/topic/libraries/architecture/room.html
|
||||
|
||||
@Database(
|
||||
version = 72,
|
||||
version = 73,
|
||||
entities = {
|
||||
EntityIdentity.class,
|
||||
EntityAccount.class,
|
||||
@@ -752,6 +752,13 @@ public abstract class DB extends RoomDatabase {
|
||||
db.execSQL("ALTER TABLE `message` ADD COLUMN `list_post` TEXT");
|
||||
}
|
||||
})
|
||||
.addMigrations(new Migration(72, 73) {
|
||||
@Override
|
||||
public void migrate(SupportSQLiteDatabase db) {
|
||||
Log.i("DB migration from version " + startVersion + " to " + endVersion);
|
||||
db.execSQL("ALTER TABLE `account` ADD COLUMN `order` INTEGER");
|
||||
}
|
||||
})
|
||||
.build();
|
||||
}
|
||||
|
||||
|
||||
@@ -64,7 +64,8 @@ public interface DaoAccount {
|
||||
" LEFT JOIN operation ON operation.account = account.id" +
|
||||
" LEFT JOIN folder AS drafts ON drafts.account = account.id AND drafts.type = '" + EntityFolder.DRAFTS + "'" +
|
||||
" WHERE :all OR account.synchronize" +
|
||||
" GROUP BY account.id")
|
||||
" GROUP BY account.id" +
|
||||
" ORDER BY `order`, `primary` DESC, name COLLATE NOCASE")
|
||||
LiveData<List<TupleAccountEx>> liveAccountsEx(boolean all);
|
||||
|
||||
@Query("SELECT * FROM account WHERE id = :id")
|
||||
@@ -110,6 +111,9 @@ public interface DaoAccount {
|
||||
@Query("UPDATE account SET password = :password WHERE id = :id")
|
||||
int setAccountPassword(long id, String password);
|
||||
|
||||
@Query("UPDATE account SET `order` = :order WHERE id = :id")
|
||||
int setAccountOrder(long id, Integer order);
|
||||
|
||||
@Query("UPDATE account SET warning = :warning WHERE id = :id")
|
||||
int setAccountWarning(long id, String warning);
|
||||
|
||||
@@ -125,6 +129,9 @@ public interface DaoAccount {
|
||||
@Query("UPDATE account SET last_connected = NULL")
|
||||
int clearAccountConnected();
|
||||
|
||||
@Query("UPDATE account SET `order` = NULL")
|
||||
int resetAccountOrder();
|
||||
|
||||
@Query("DELETE FROM account WHERE tbd = 1")
|
||||
int deleteAccountsTbd();
|
||||
}
|
||||
|
||||
@@ -70,6 +70,7 @@ public class EntityAccount implements Serializable {
|
||||
public String name;
|
||||
public String signature; // obsolete
|
||||
public Integer color;
|
||||
public Integer order;
|
||||
|
||||
@NonNull
|
||||
public Boolean synchronize;
|
||||
@@ -132,6 +133,7 @@ public class EntityAccount implements Serializable {
|
||||
|
||||
json.put("name", name);
|
||||
json.put("color", color);
|
||||
json.put("order", order);
|
||||
|
||||
json.put("synchronize", synchronize);
|
||||
json.put("primary", primary);
|
||||
@@ -167,6 +169,8 @@ public class EntityAccount implements Serializable {
|
||||
account.name = json.getString("name");
|
||||
if (json.has("color"))
|
||||
account.color = json.getInt("color");
|
||||
if (json.has("order"))
|
||||
account.order = json.getInt("order");
|
||||
|
||||
account.synchronize = json.getBoolean("synchronize");
|
||||
account.primary = json.getBoolean("primary");
|
||||
|
||||
@@ -40,6 +40,7 @@ import androidx.fragment.app.FragmentTransaction;
|
||||
import androidx.lifecycle.Observer;
|
||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
||||
import androidx.recyclerview.widget.DividerItemDecoration;
|
||||
import androidx.recyclerview.widget.ItemTouchHelper;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
@@ -92,8 +93,9 @@ public class FragmentAccounts extends FragmentBase {
|
||||
itemDecorator.setDrawable(getContext().getDrawable(R.drawable.divider));
|
||||
rvAccount.addItemDecoration(itemDecorator);
|
||||
|
||||
adapter = new AdapterAccount(getContext(), settings);
|
||||
adapter = new AdapterAccount(getContext(), getViewLifecycleOwner(), settings);
|
||||
rvAccount.setAdapter(adapter);
|
||||
new ItemTouchHelper(touchHelper).attachToRecyclerView(rvAccount);
|
||||
|
||||
fab.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
@@ -218,7 +220,7 @@ public class FragmentAccounts extends FragmentBase {
|
||||
|
||||
@Override
|
||||
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
||||
inflater.inflate(R.menu.menu_folders, menu);
|
||||
inflater.inflate(R.menu.menu_accounts, menu);
|
||||
|
||||
final MenuItem menuSearch = menu.findItem(R.id.menu_search);
|
||||
SearchView searchView = (SearchView) menuSearch.getActionView();
|
||||
@@ -251,7 +253,63 @@ public class FragmentAccounts extends FragmentBase {
|
||||
@Override
|
||||
public void onPrepareOptionsMenu(Menu menu) {
|
||||
menu.findItem(R.id.menu_search).setVisible(!settings);
|
||||
menu.findItem(R.id.menu_reset_order).setVisible(settings);
|
||||
|
||||
super.onPrepareOptionsMenu(menu);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case R.id.menu_reset_order:
|
||||
onResetOrder();
|
||||
return true;
|
||||
default:
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
}
|
||||
|
||||
private void onResetOrder() {
|
||||
Bundle args = new Bundle();
|
||||
|
||||
new SimpleTask<Void>() {
|
||||
@Override
|
||||
protected Void onExecute(Context context, Bundle args) {
|
||||
DB db = DB.getInstance(context);
|
||||
db.account().resetAccountOrder();
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onException(Bundle args, Throwable ex) {
|
||||
Helper.unexpectedError(getContext(), getViewLifecycleOwner(), ex);
|
||||
}
|
||||
}.execute(getContext(), getViewLifecycleOwner(), args, "accounts:reset");
|
||||
}
|
||||
|
||||
private ItemTouchHelper.Callback touchHelper = new ItemTouchHelper.Callback() {
|
||||
@Override
|
||||
public int getMovementFlags(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder) {
|
||||
int flags = 0;
|
||||
int pos = viewHolder.getAdapterPosition();
|
||||
if (pos != RecyclerView.NO_POSITION) {
|
||||
if (pos - 1 >= 0)
|
||||
flags |= ItemTouchHelper.UP;
|
||||
if (pos + 1 < rvAccount.getAdapter().getItemCount())
|
||||
flags |= ItemTouchHelper.DOWN;
|
||||
}
|
||||
|
||||
return makeMovementFlags(flags, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder source, @NonNull RecyclerView.ViewHolder target) {
|
||||
((AdapterAccount) rvAccount.getAdapter()).onMove(source.getAdapterPosition(), target.getAdapterPosition());
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user