Some order

This commit is contained in:
M66B 2019-05-06 22:34:18 +02:00
parent 1f8a472131
commit 567aeffe46
20 changed files with 278 additions and 152 deletions

11
FAQ.md
View File

@ -986,13 +986,12 @@ Note that searching through a lot of messages stored locally would only delay se
<a name="faq51"></a> <a name="faq51"></a>
**(51) How are folders sorted?** **(51) How are folders sorted?**
Folders are sorted with special, system folders on top, followed by folders set to synchronize. Folders are first sorted on account order (by default on account name)
Within each category the folders are sorted on name. and within an account with special, system folders on top, followed by folders set to synchronize.
Within each category the folders are sorted on (display) name.
You can set the display name by long pressing a folder in the folder list and selecting *Edit properties*.
Some providers prefix some folders with INBOX, but these folders are in fact just user folders, so they are sorted below the special, system folders. The navigation (hamburger) menu item *Order folders* in the setup can be used to manually order the folders.
It is not possible to make an exception for this because some other providers prefix all folders with INBOX.
Note that you can give folders a display name by long pressing on a folder name, which can be useful because the display name will be used for sorting.
<br /> <br />

View File

@ -58,7 +58,6 @@ import java.text.Collator;
import java.text.NumberFormat; import java.text.NumberFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.Comparator;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
@ -671,36 +670,8 @@ public class AdapterFolder extends RecyclerView.Adapter<AdapterFolder.ViewHolder
final Collator collator = Collator.getInstance(Locale.getDefault()); final Collator collator = Collator.getInstance(Locale.getDefault());
collator.setStrength(Collator.SECONDARY); // Case insensitive, process accents etc collator.setStrength(Collator.SECONDARY); // Case insensitive, process accents etc
Collections.sort(folders, new Comparator<TupleFolderEx>() { if (folders.size() > 0)
@Override Collections.sort(folders, folders.get(0).getComparator(context));
public int compare(TupleFolderEx f1, TupleFolderEx f2) {
if (account < 0) {
int o = Integer.compare(
f1.order == null ? -1 : f1.order,
f2.order == null ? -1 : f2.order);
if (o != 0)
return o;
String name1 = f1.getDisplayName(context);
String name2 = f2.getDisplayName(context);
return collator.compare(name1, name2);
} else {
int i1 = EntityFolder.FOLDER_SORT_ORDER.indexOf(f1.type);
int i2 = EntityFolder.FOLDER_SORT_ORDER.indexOf(f2.type);
int s = Integer.compare(i1, i2);
if (s != 0)
return s;
int c = -f1.synchronize.compareTo(f2.synchronize);
if (c != 0)
return c;
String name1 = f1.getDisplayName(context);
String name2 = f2.getDisplayName(context);
return collator.compare(name1, name2);
}
}
});
DiffUtil.DiffResult diff = DiffUtil.calculateDiff(new DiffCallback(items, folders), false); DiffUtil.DiffResult diff = DiffUtil.calculateDiff(new DiffCallback(items, folders), false);

View File

@ -2155,7 +2155,8 @@ public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHold
if (folders == null) if (folders == null)
return null; return null;
EntityFolder.sort(context, folders, true); if (folders.size() > 0)
Collections.sort(folders, folders.get(0).getComparator(context));
return folders; return folders;
} }
@ -2850,7 +2851,8 @@ public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHold
!EntityFolder.JUNK.equals(folder.type)) !EntityFolder.JUNK.equals(folder.type))
targets.add(folder); targets.add(folder);
EntityFolder.sort(context, targets, true); if (targets.size() > 0)
Collections.sort(targets, targets.get(0).getComparator(context));
return targets; return targets;
} }

View File

@ -36,6 +36,7 @@ import androidx.recyclerview.widget.RecyclerView;
import java.text.NumberFormat; import java.text.NumberFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
@ -120,6 +121,9 @@ public class AdapterNavAccount extends RecyclerView.Adapter<AdapterNavAccount.Vi
public void set(@NonNull List<TupleAccountEx> accounts) { public void set(@NonNull List<TupleAccountEx> accounts) {
Log.i("Set nav accounts=" + accounts.size()); Log.i("Set nav accounts=" + accounts.size());
if (accounts.size() > 0)
Collections.sort(accounts, accounts.get(0).getComparator(context));
DiffUtil.DiffResult diff = DiffUtil.calculateDiff(new DiffCallback(items, accounts), false); DiffUtil.DiffResult diff = DiffUtil.calculateDiff(new DiffCallback(items, accounts), false);
items = accounts; items = accounts;

View File

@ -34,13 +34,10 @@ import androidx.recyclerview.widget.DiffUtil;
import androidx.recyclerview.widget.ListUpdateCallback; import androidx.recyclerview.widget.ListUpdateCallback;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import java.text.Collator;
import java.text.NumberFormat; import java.text.NumberFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.Comparator;
import java.util.List; import java.util.List;
import java.util.Locale;
import java.util.Objects; import java.util.Objects;
public class AdapterNavFolder extends RecyclerView.Adapter<AdapterNavFolder.ViewHolder> { public class AdapterNavFolder extends RecyclerView.Adapter<AdapterNavFolder.ViewHolder> {
@ -93,10 +90,10 @@ public class AdapterNavFolder extends RecyclerView.Adapter<AdapterNavFolder.View
? R.drawable.baseline_folder_24 ? R.drawable.baseline_folder_24
: R.drawable.baseline_folder_open_24); : R.drawable.baseline_folder_open_24);
if (folder.color == null) if (folder.accountColor == null)
ivItem.clearColorFilter(); ivItem.clearColorFilter();
else else
ivItem.setColorFilter(folder.color); ivItem.setColorFilter(folder.accountColor);
} }
int count = (EntityFolder.OUTBOX.equals(folder.type) ? folder.operations : folder.unseen); int count = (EntityFolder.OUTBOX.equals(folder.type) ? folder.operations : folder.unseen);
@ -141,25 +138,8 @@ public class AdapterNavFolder extends RecyclerView.Adapter<AdapterNavFolder.View
public void set(@NonNull List<TupleFolderNav> folders) { public void set(@NonNull List<TupleFolderNav> folders) {
Log.i("Set nav folders=" + folders.size()); Log.i("Set nav folders=" + folders.size());
final Collator collator = Collator.getInstance(Locale.getDefault()); if (folders.size() > 0)
collator.setStrength(Collator.SECONDARY); // Case insensitive, process accents etc Collections.sort(folders, folders.get(0).getComparator(context));
Collections.sort(folders, new Comparator<TupleFolderNav>() {
@Override
public int compare(TupleFolderNav f1, TupleFolderNav f2) {
int s = Boolean.compare(EntityFolder.OUTBOX.equals(f1.type), EntityFolder.OUTBOX.equals(f2.type));
if (s != 0)
return s;
int o = Integer.compare(f1.order == null ? -1 : f1.order, f2.order == null ? -1 : f2.order);
if (o != 0)
return o;
String name1 = f1.getDisplayName(context);
String name2 = f2.getDisplayName(context);
return collator.compare(name1, name2);
}
});
DiffUtil.DiffResult diff = DiffUtil.calculateDiff(new DiffCallback(items, folders), false); DiffUtil.DiffResult diff = DiffUtil.calculateDiff(new DiffCallback(items, folders), false);
@ -222,8 +202,9 @@ public class AdapterNavFolder extends RecyclerView.Adapter<AdapterNavFolder.View
return (f1.name.equals(f2.name) && return (f1.name.equals(f2.name) &&
f1.type.equals(f2.type) && f1.type.equals(f2.type) &&
Objects.equals(f1.display, f2.display) && Objects.equals(f1.display, f2.display) &&
Objects.equals(f1.color, f2.color) && Objects.equals(f1.accountColor, f2.accountColor) &&
Objects.equals(f1.state, f2.state) && Objects.equals(f1.state, f2.state) &&
Objects.equals(f1.sync_state, f2.sync_state) &&
f1.unseen == f2.unseen && f1.unseen == f2.unseen &&
f1.operations == f2.operations); f1.operations == f2.operations);
} }

View File

@ -31,12 +31,9 @@ import androidx.recyclerview.widget.DiffUtil;
import androidx.recyclerview.widget.ListUpdateCallback; import androidx.recyclerview.widget.ListUpdateCallback;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import java.text.Collator;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.Comparator;
import java.util.List; import java.util.List;
import java.util.Locale;
import java.util.Objects; import java.util.Objects;
public class AdapterOrder extends RecyclerView.Adapter<AdapterOrder.ViewHolder> { public class AdapterOrder extends RecyclerView.Adapter<AdapterOrder.ViewHolder> {
@ -76,21 +73,8 @@ public class AdapterOrder extends RecyclerView.Adapter<AdapterOrder.ViewHolder>
public void set(@NonNull List<EntityOrder> items) { public void set(@NonNull List<EntityOrder> items) {
Log.i("Set sort items=" + items.size()); Log.i("Set sort items=" + items.size());
final Collator collator = Collator.getInstance(Locale.getDefault()); if (items.size() > 0)
collator.setStrength(Collator.SECONDARY); // Case insensitive, process accents etc Collections.sort(items, items.get(0).getComparator(context));
Collections.sort(items, new Comparator<EntityOrder>() {
@Override
public int compare(EntityOrder s1, EntityOrder s2) {
int o = Integer.compare(s1.order == null ? -1 : s1.order, s2.order == null ? -1 : s2.order);
if (o != 0)
return o;
String name1 = s1.getSortKey(context);
String name2 = s2.getSortKey(context);
return collator.compare(name1, name2);
}
});
DiffUtil.DiffResult diff = DiffUtil.calculateDiff(new DiffCallback(this.items, items), false); DiffUtil.DiffResult diff = DiffUtil.calculateDiff(new DiffCallback(this.items, items), false);

View File

@ -52,14 +52,14 @@ public interface DaoFolder {
EntityFolder getBrowsableFolder(long folder, boolean search); EntityFolder getBrowsableFolder(long folder, boolean search);
@Query("SELECT folder.*" + @Query("SELECT folder.*" +
", account.name AS accountName" + ", account.`order` AS accountOrder, account.name AS accountName" +
" FROM folder" + " FROM folder" +
" JOIN account ON account.id = folder.account" + " JOIN account ON account.id = folder.account" +
" WHERE account.`synchronize`") " WHERE account.`synchronize`")
LiveData<List<TupleFolderSort>> liveSort(); LiveData<List<TupleFolderSort>> liveSort();
@Query("SELECT folder.*" + @Query("SELECT folder.*" +
", account.name AS accountName, account.color AS accountColor, account.state AS accountState" + ", account.`order` AS accountOrder, account.name AS accountName, account.color AS accountColor, account.state AS accountState" +
", COUNT(message.id) AS messages" + ", COUNT(message.id) AS messages" +
", SUM(CASE WHEN message.content = 1 THEN 1 ELSE 0 END) AS content" + ", SUM(CASE WHEN message.content = 1 THEN 1 ELSE 0 END) AS content" +
", SUM(CASE WHEN message.ui_seen = 0 THEN 1 ELSE 0 END) AS unseen" + ", SUM(CASE WHEN message.ui_seen = 0 THEN 1 ELSE 0 END) AS unseen" +
@ -76,7 +76,7 @@ public interface DaoFolder {
LiveData<List<TupleFolderEx>> liveFolders(Long account, Long parent); LiveData<List<TupleFolderEx>> liveFolders(Long account, Long parent);
@Query("SELECT folder.*" + @Query("SELECT folder.*" +
", account.name AS accountName, account.color AS accountColor, account.state AS accountState" + ", account.`order` AS accountOrder, account.name AS accountName, account.color AS accountColor, account.state AS accountState" +
", COUNT(message.id) AS messages" + ", COUNT(message.id) AS messages" +
", SUM(CASE WHEN message.content = 1 THEN 1 ELSE 0 END) AS content" + ", SUM(CASE WHEN message.content = 1 THEN 1 ELSE 0 END) AS content" +
", SUM(CASE WHEN message.ui_seen = 0 THEN 1 ELSE 0 END) AS unseen" + ", SUM(CASE WHEN message.ui_seen = 0 THEN 1 ELSE 0 END) AS unseen" +
@ -90,7 +90,7 @@ public interface DaoFolder {
LiveData<List<TupleFolderEx>> liveUnified(); LiveData<List<TupleFolderEx>> liveUnified();
@Query("SELECT folder.*" + @Query("SELECT folder.*" +
", account.color" + ", account.`order` AS accountOrder, account.name AS accountName, account.color AS accountColor" +
", SUM(CASE WHEN message.ui_seen = 0 THEN 1 ELSE 0 END) AS unseen" + ", SUM(CASE WHEN message.ui_seen = 0 THEN 1 ELSE 0 END) AS unseen" +
", (SELECT COUNT(*) FROM operation WHERE operation.folder = folder.id) AS operations" + ", (SELECT COUNT(*) FROM operation WHERE operation.folder = folder.id) AS operations" +
" FROM folder" + " FROM folder" +
@ -114,7 +114,7 @@ public interface DaoFolder {
LiveData<Integer> liveSynchronizing(); LiveData<Integer> liveSynchronizing();
@Query("SELECT folder.*" + @Query("SELECT folder.*" +
", account.name AS accountName, account.color AS accountColor, account.state AS accountState" + ", account.`order` AS accountOrder, account.name AS accountName, account.color AS accountColor, account.state AS accountState" +
", COUNT(message.id) AS messages" + ", COUNT(message.id) AS messages" +
", SUM(CASE WHEN message.content = 1 THEN 1 ELSE 0 END) AS content" + ", SUM(CASE WHEN message.content = 1 THEN 1 ELSE 0 END) AS content" +
", SUM(CASE WHEN message.ui_seen = 0 THEN 1 ELSE 0 END) AS unseen" + ", SUM(CASE WHEN message.ui_seen = 0 THEN 1 ELSE 0 END) AS unseen" +

View File

@ -34,6 +34,9 @@ import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
import java.io.Serializable; import java.io.Serializable;
import java.text.Collator;
import java.util.Comparator;
import java.util.Locale;
import java.util.Objects; import java.util.Objects;
@Entity( @Entity(
@ -123,11 +126,6 @@ public class EntityAccount extends EntityOrder implements Serializable {
return id; return id;
} }
@Override
String getSortKey(Context context) {
return name;
}
@Override @Override
String[] getSortTitle(Context context) { String[] getSortTitle(Context context) {
return new String[]{name, null}; return new String[]{name, null};
@ -238,6 +236,30 @@ public class EntityAccount extends EntityOrder implements Serializable {
return false; return false;
} }
@Override
Comparator getComparator(final Context context) {
final Collator collator = Collator.getInstance(Locale.getDefault());
collator.setStrength(Collator.SECONDARY); // Case insensitive, process accents etc
return new Comparator() {
@Override
public int compare(Object o1, Object o2) {
EntityAccount a1 = (EntityAccount) o1;
EntityAccount a2 = (EntityAccount) o2;
int o = Integer.compare(
a1.order == null ? -1 : a1.order,
a2.order == null ? -1 : a2.order);
if (o != 0)
return o;
String name1 = (a1.name == null ? "" : a1.name);
String name2 = (a2.name == null ? "" : a2.name);
return collator.compare(name1, name2);
}
};
}
@NonNull @NonNull
@Override @Override
public String toString() { public String toString() {

View File

@ -234,11 +234,6 @@ public class EntityFolder extends EntityOrder implements Serializable {
return id; return id;
} }
@Override
String getSortKey(Context context) {
return getDisplayName(context);
}
@Override @Override
String[] getSortTitle(Context context) { String[] getSortTitle(Context context) {
return new String[]{getDisplayName(context), null}; return new String[]{getDisplayName(context), null};
@ -388,29 +383,37 @@ public class EntityFolder extends EntityOrder implements Serializable {
return folder; return folder;
} }
static void sort(final Context context, List<EntityFolder> folders, final boolean menu) { @Override
Comparator getComparator(final Context context) {
final Collator collator = Collator.getInstance(Locale.getDefault()); final Collator collator = Collator.getInstance(Locale.getDefault());
collator.setStrength(Collator.SECONDARY); // Case insensitive, process accents etc collator.setStrength(Collator.SECONDARY); // Case insensitive, process accents etc
Collections.sort(folders, new Comparator<EntityFolder>() { return new Comparator() {
@Override @Override
public int compare(EntityFolder f1, EntityFolder f2) { public int compare(Object o1, Object o2) {
EntityFolder f1 = (EntityFolder) o1;
EntityFolder f2 = (EntityFolder) o2;
int o = Integer.compare(
f1.order == null ? -1 : f1.order,
f2.order == null ? -1 : f2.order);
if (o != 0)
return o;
int i1 = EntityFolder.FOLDER_SORT_ORDER.indexOf(f1.type); int i1 = EntityFolder.FOLDER_SORT_ORDER.indexOf(f1.type);
int i2 = EntityFolder.FOLDER_SORT_ORDER.indexOf(f2.type); int i2 = EntityFolder.FOLDER_SORT_ORDER.indexOf(f2.type);
int s = Integer.compare(i1, i2); int s = Integer.compare(i1, i2);
if (s != 0) if (s != 0)
return s; return s;
if (!menu) { int c = -f1.synchronize.compareTo(f2.synchronize);
int c = -f1.synchronize.compareTo(f2.synchronize); if (c != 0)
if (c != 0) return c;
return c;
}
String name1 = f1.getDisplayName(context); String name1 = f1.getDisplayName(context);
String name2 = f2.getDisplayName(context); String name2 = f2.getDisplayName(context);
return collator.compare(name1, name2); return collator.compare(name1, name2);
} }
}); };
} }
} }

View File

@ -21,12 +21,14 @@ package eu.faircode.email;
import android.content.Context; import android.content.Context;
import java.util.Comparator;
public abstract class EntityOrder { public abstract class EntityOrder {
public Integer order; public Integer order;
abstract Long getSortId(); abstract Long getSortId();
abstract String getSortKey(Context context);
abstract String[] getSortTitle(Context context); abstract String[] getSortTitle(Context context);
abstract Comparator getComparator(Context context);
} }

View File

@ -75,6 +75,7 @@ import com.sun.mail.imap.protocol.IMAPProtocol;
import java.io.IOException; import java.io.IOException;
import java.net.UnknownHostException; import java.net.UnknownHostException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
@ -676,8 +677,9 @@ public class FragmentAccount extends FragmentBase {
for (EntityFolder folder : result.folders) for (EntityFolder folder : result.folders)
folder.display = folder.getDisplayName(getContext()); folder.display = folder.getDisplayName(getContext());
EntityFolder.sort(getContext(), result.folders, true);
if (result.folders.size() > 0)
Collections.sort(result.folders, result.folders.get(0).getComparator(context));
} }
return result; return result;
@ -1207,7 +1209,9 @@ public class FragmentAccount extends FragmentBase {
if (folders != null) { if (folders != null) {
for (EntityFolder folder : folders) for (EntityFolder folder : folders)
folder.display = folder.getDisplayName(getContext()); folder.display = folder.getDisplayName(getContext());
EntityFolder.sort(getContext(), folders, true);
if (folders.size() > 0)
Collections.sort(folders, folders.get(0).getComparator(context));
} }
return folders; return folders;

View File

@ -101,6 +101,7 @@ import java.util.Map;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import static android.os.Process.THREAD_PRIORITY_BACKGROUND;
import static android.text.format.DateUtils.DAY_IN_MILLIS; import static android.text.format.DateUtils.DAY_IN_MILLIS;
import static android.text.format.DateUtils.FORMAT_SHOW_DATE; import static android.text.format.DateUtils.FORMAT_SHOW_DATE;
import static android.text.format.DateUtils.FORMAT_SHOW_WEEKDAY; import static android.text.format.DateUtils.FORMAT_SHOW_WEEKDAY;
@ -1236,7 +1237,10 @@ public class FragmentMessages extends FragmentBase {
!EntityFolder.JUNK.equals(target.type) && !EntityFolder.JUNK.equals(target.type) &&
(fids.size() != 1 || !fids.contains(target.id))) (fids.size() != 1 || !fids.contains(target.id)))
targets.add(target); targets.add(target);
EntityFolder.sort(context, targets, true);
if (targets.size() > 0)
Collections.sort(targets, targets.get(0).getComparator(context));
result.targets.put(account, targets); result.targets.put(account, targets);
} }
@ -2892,7 +2896,7 @@ public class FragmentMessages extends FragmentBase {
if (snackbar.isShown()) if (snackbar.isShown())
snackbar.dismiss(); snackbar.dismiss();
new Thread(new Runnable() { Thread thread = new Thread(new Runnable() {
@Override @Override
public void run() { public void run() {
DB db = DB.getInstance(context); DB db = DB.getInstance(context);
@ -2912,7 +2916,9 @@ public class FragmentMessages extends FragmentBase {
db.endTransaction(); db.endTransaction();
} }
} }
}).start(); });
thread.setPriority(THREAD_PRIORITY_BACKGROUND);
thread.start();
} }
}, UNDO_TIMEOUT); }, UNDO_TIMEOUT);
} }

View File

@ -47,6 +47,7 @@ public class FragmentOrder extends FragmentBase {
private ContentLoadingProgressBar pbWait; private ContentLoadingProgressBar pbWait;
private Group grpReady; private Group grpReady;
private boolean dirty = false;
private AdapterOrder adapter; private AdapterOrder adapter;
@Override @Override
@ -133,45 +134,47 @@ public class FragmentOrder extends FragmentBase {
public void onPause() { public void onPause() {
super.onPause(); super.onPause();
List<EntityOrder> items = adapter.getItems(); if (dirty) {
List<EntityOrder> items = adapter.getItems();
List<Long> order = new ArrayList<>(); List<Long> order = new ArrayList<>();
for (int i = 0; i < items.size(); i++) for (int i = 0; i < items.size(); i++)
order.add(items.get(i).getSortId()); order.add(items.get(i).getSortId());
Bundle args = new Bundle(); Bundle args = new Bundle();
args.putString("class", clazz); args.putString("class", clazz);
args.putLongArray("order", Helper.toLongArray(order)); args.putLongArray("order", Helper.toLongArray(order));
new SimpleTask<Void>() { new SimpleTask<Void>() {
@Override @Override
protected Void onExecute(Context context, Bundle args) { protected Void onExecute(Context context, Bundle args) {
final String clazz = args.getString("class"); final String clazz = args.getString("class");
final long[] order = args.getLongArray("order"); final long[] order = args.getLongArray("order");
final DB db = DB.getInstance(context); final DB db = DB.getInstance(context);
db.runInTransaction(new Runnable() { db.runInTransaction(new Runnable() {
@Override @Override
public void run() { public void run() {
for (int i = 0; i < order.length; i++) for (int i = 0; i < order.length; i++)
if (EntityAccount.class.getName().equals(clazz)) if (EntityAccount.class.getName().equals(clazz))
db.account().setAccountOrder(order[i], i); db.account().setAccountOrder(order[i], i);
else if (TupleFolderSort.class.getName().equals(clazz)) else if (TupleFolderSort.class.getName().equals(clazz))
db.folder().setFolderOrder(order[i], i); db.folder().setFolderOrder(order[i], i);
else else
throw new IllegalArgumentException("Unknown class=" + clazz); throw new IllegalArgumentException("Unknown class=" + clazz);
} }
}); });
return null; return null;
} }
@Override @Override
protected void onException(Bundle args, Throwable ex) { protected void onException(Bundle args, Throwable ex) {
Helper.unexpectedError(getContext(), getViewLifecycleOwner(), ex); Helper.unexpectedError(getContext(), getViewLifecycleOwner(), ex);
} }
}.execute(getContext(), getViewLifecycleOwner(), args, "order:set"); }.execute(getContext(), getViewLifecycleOwner(), args, "order:set");
}
} }
@Override @Override
@ -212,6 +215,11 @@ public class FragmentOrder extends FragmentBase {
return null; return null;
} }
@Override
protected void onExecuted(Bundle args, Void data) {
dirty = false;
}
@Override @Override
protected void onException(Bundle args, Throwable ex) { protected void onException(Bundle args, Throwable ex) {
Helper.unexpectedError(getContext(), getViewLifecycleOwner(), ex); Helper.unexpectedError(getContext(), getViewLifecycleOwner(), ex);
@ -236,6 +244,7 @@ public class FragmentOrder extends FragmentBase {
@Override @Override
public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder source, @NonNull RecyclerView.ViewHolder target) { public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder source, @NonNull RecyclerView.ViewHolder target) {
dirty = true;
((AdapterOrder) rvOrder.getAdapter()).onMove(source.getAdapterPosition(), target.getAdapterPosition()); ((AdapterOrder) rvOrder.getAdapter()).onMove(source.getAdapterPosition(), target.getAdapterPosition());
return true; return true;
} }

View File

@ -54,6 +54,7 @@ import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.List; import java.util.List;
import static android.app.Activity.RESULT_OK; import static android.app.Activity.RESULT_OK;
@ -302,7 +303,9 @@ public class FragmentRule extends FragmentBase {
for (EntityFolder folder : data.folders) for (EntityFolder folder : data.folders)
folder.display = folder.getDisplayName(context); folder.display = folder.getDisplayName(context);
EntityFolder.sort(context, data.folders, true);
if (data.folders.size() > 0)
Collections.sort(data.folders, data.folders.get(0).getComparator(context));
data.identities = db.identity().getIdentities(aid); data.identities = db.identity().getIdentities(aid);
data.answers = db.answer().getAnswers(false); data.answers = db.answer().getAnswers(false);

View File

@ -59,6 +59,8 @@ import javax.mail.Transport;
import javax.mail.internet.InternetAddress; import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage; import javax.mail.internet.MimeMessage;
import static android.os.Process.THREAD_PRIORITY_BACKGROUND;
public class ServiceSend extends LifecycleService { public class ServiceSend extends LifecycleService {
private int lastUnsent = 0; private int lastUnsent = 0;
@ -244,6 +246,7 @@ public class ServiceSend extends LifecycleService {
} }
} }
}); });
thread.setPriority(THREAD_PRIORITY_BACKGROUND);
thread.start(); thread.start();
} }
}; };
@ -446,6 +449,7 @@ public class ServiceSend extends LifecycleService {
} }
} }
}); });
thread.setPriority(THREAD_PRIORITY_BACKGROUND);
thread.start(); thread.start();
} }
} }

View File

@ -1152,7 +1152,7 @@ public class ServiceSynchronize extends LifecycleService {
if (started) { if (started) {
EntityLog.log(ServiceSynchronize.this, "Checking account states"); EntityLog.log(ServiceSynchronize.this, "Checking account states");
new Thread(new Runnable() { Thread check = new Thread(new Runnable() {
@Override @Override
public void run() { public void run() {
try { try {
@ -1183,7 +1183,9 @@ public class ServiceSynchronize extends LifecycleService {
Log.e(ex); Log.e(ex);
} }
} }
}).start(); });
check.setPriority(THREAD_PRIORITY_BACKGROUND);
check.start();
} else } else
queue_reload(true, false, "connect " + network); queue_reload(true, false, "connect " + network);
} catch (Throwable ex) { } catch (Throwable ex) {
@ -1268,6 +1270,7 @@ public class ServiceSynchronize extends LifecycleService {
} }
} }
}); });
thread.setPriority(THREAD_PRIORITY_BACKGROUND);
thread.start(); thread.start();
} }
} }

View File

@ -19,10 +19,16 @@ package eu.faircode.email;
Copyright 2018-2019 by Marcel Bokhorst (M66B) Copyright 2018-2019 by Marcel Bokhorst (M66B)
*/ */
import android.content.Context;
import java.io.Serializable; import java.io.Serializable;
import java.text.Collator;
import java.util.Comparator;
import java.util.Locale;
import java.util.Objects; import java.util.Objects;
public class TupleFolderEx extends EntityFolder implements Serializable { public class TupleFolderEx extends EntityFolder implements Serializable {
public Integer accountOrder;
public String accountName; public String accountName;
public Integer accountColor; public Integer accountColor;
public String accountState; public String accountState;
@ -46,4 +52,40 @@ public class TupleFolderEx extends EntityFolder implements Serializable {
} else } else
return false; return false;
} }
@Override
Comparator getComparator(final Context context) {
final Collator collator = Collator.getInstance(Locale.getDefault());
collator.setStrength(Collator.SECONDARY); // Case insensitive, process accents etc
final Comparator base = super.getComparator(context);
return new Comparator() {
@Override
public int compare(Object o1, Object o2) {
TupleFolderEx f1 = (TupleFolderEx) o1;
TupleFolderEx f2 = (TupleFolderEx) o2;
// Outbox
if (f1.accountName == null && f2.accountName == null)
return 0;
else if (f1.accountName == null)
return 1;
else if (f2.accountName == null)
return -1;
int o = Integer.compare(
f1.accountOrder == null ? -1 : f1.accountOrder,
f2.accountOrder == null ? -1 : f2.accountOrder);
if (o != 0)
return o;
int a = collator.compare(f1.accountName, f2.accountName);
if (a != 0)
return a;
return base.compare(o1, o2);
}
};
}
} }

View File

@ -19,11 +19,53 @@ package eu.faircode.email;
Copyright 2018-2019 by Marcel Bokhorst (M66B) Copyright 2018-2019 by Marcel Bokhorst (M66B)
*/ */
import android.content.Context;
import java.io.Serializable; import java.io.Serializable;
import java.util.Objects; import java.text.Collator;
import java.util.Comparator;
import java.util.Locale;
public class TupleFolderNav extends EntityFolder implements Serializable { public class TupleFolderNav extends EntityFolder implements Serializable {
public Integer color; // account public Integer accountOrder;
public String accountName;
public Integer accountColor;
public int unseen; public int unseen;
public int operations; public int operations;
@Override
Comparator getComparator(final Context context) {
final Collator collator = Collator.getInstance(Locale.getDefault());
collator.setStrength(Collator.SECONDARY); // Case insensitive, process accents etc
final Comparator base = super.getComparator(context);
return new Comparator() {
@Override
public int compare(Object o1, Object o2) {
TupleFolderNav f1 = (TupleFolderNav) o1;
TupleFolderNav f2 = (TupleFolderNav) o2;
// Outbox
if (f1.accountName == null && f2.accountName == null)
return 0;
else if (f1.accountName == null)
return 1;
else if (f2.accountName == null)
return -1;
int o = Integer.compare(
f1.accountOrder == null ? -1 : f1.accountOrder,
f2.accountOrder == null ? -1 : f2.accountOrder);
if (o != 0)
return o;
int a = collator.compare(f1.accountName, f2.accountName);
if (a != 0)
return a;
return base.compare(o1, o2);
}
};
}
} }

View File

@ -21,11 +21,52 @@ package eu.faircode.email;
import android.content.Context; import android.content.Context;
import java.text.Collator;
import java.util.Comparator;
import java.util.Locale;
public class TupleFolderSort extends EntityFolder { public class TupleFolderSort extends EntityFolder {
public Integer accountOrder;
public String accountName; public String accountName;
@Override @Override
String[] getSortTitle(Context context) { String[] getSortTitle(Context context) {
return new String[]{getDisplayName(context), accountName}; return new String[]{getDisplayName(context), accountName};
} }
@Override
Comparator getComparator(final Context context) {
final Collator collator = Collator.getInstance(Locale.getDefault());
collator.setStrength(Collator.SECONDARY); // Case insensitive, process accents etc
final Comparator base = super.getComparator(context);
return new Comparator() {
@Override
public int compare(Object o1, Object o2) {
TupleFolderSort f1 = (TupleFolderSort) o1;
TupleFolderSort f2 = (TupleFolderSort) o2;
// Outbox
if (f1.accountName == null && f2.accountName == null)
return 0;
else if (f1.accountName == null)
return 1;
else if (f2.accountName == null)
return -1;
int o = Integer.compare(
f1.accountOrder == null ? -1 : f1.accountOrder,
f2.accountOrder == null ? -1 : f2.accountOrder);
if (o != 0)
return o;
int a = collator.compare(f1.accountName, f2.accountName);
if (a != 0)
return a;
return base.compare(o1, o2);
}
};
}
} }

View File

@ -27,16 +27,20 @@ import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.widget.RemoteViews; import android.widget.RemoteViews;
import static android.os.Process.THREAD_PRIORITY_BACKGROUND;
public class Widget extends AppWidgetProvider { public class Widget extends AppWidgetProvider {
@Override @Override
public void onUpdate(final Context context, final AppWidgetManager appWidgetManager, final int[] appWidgetIds) { public void onUpdate(final Context context, final AppWidgetManager appWidgetManager, final int[] appWidgetIds) {
new Thread(new Runnable() { Thread thread = new Thread(new Runnable() {
@Override @Override
public void run() { public void run() {
DB db = DB.getInstance(context); DB db = DB.getInstance(context);
update(appWidgetIds, appWidgetManager, context, db.message().getUnseenUnified()); update(appWidgetIds, appWidgetManager, context, db.message().getUnseenUnified());
} }
}).start(); });
thread.setPriority(THREAD_PRIORITY_BACKGROUND);
thread.start();
} }
static void update(Context context, int count) { static void update(Context context, int count) {