Allow account ordering

pull/155/head
M66B 5 years ago
parent 3764ad2818
commit 2a4ff4b49d

File diff suppressed because it is too large Load Diff

@ -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) {
}
};
}

@ -8,4 +8,9 @@
android:title="@string/title_search"
app:actionViewClass="androidx.appcompat.widget.SearchView"
app:showAsAction="collapseActionView|always" />
<item
android:id="@+id/menu_reset_order"
android:title="@string/title_reset_order"
app:showAsAction="never" />
</menu>

@ -451,6 +451,8 @@
<string name="title_search_device">Search on device</string>
<string name="title_searching">Searching \'%1$s\'</string>
<string name="title_reset_order">Reset order</string>
<string name="title_sort_on">Sort on</string>
<string name="title_sort_on_time">Time</string>
<string name="title_sort_on_unread">Unread</string>

Loading…
Cancel
Save