Category as view

pull/215/head
M66B 3 months ago
parent 88275d18f4
commit 792e020d0a

@ -2504,6 +2504,7 @@ public class ActivityView extends ActivityBilling implements FragmentManager.OnB
Bundle args = new Bundle();
args.putString("type", intent.getStringExtra("type"));
args.putString("category", intent.getStringExtra("category"));
args.putLong("account", intent.getLongExtra("account", -1));
args.putLong("folder", intent.getLongExtra("folder", -1));

@ -38,12 +38,14 @@ import androidx.recyclerview.widget.DiffUtil;
import androidx.recyclerview.widget.ListUpdateCallback;
import androidx.recyclerview.widget.RecyclerView;
import java.text.Collator;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
@ -52,6 +54,8 @@ public class AdapterNavUnified extends RecyclerView.Adapter<AdapterNavUnified.Vi
private LifecycleOwner owner;
private LayoutInflater inflater;
private int dp6;
private int dp12;
private boolean nav_count;
private boolean nav_count_pinned;
private boolean nav_unseen_drafts;
@ -96,6 +100,9 @@ public class AdapterNavUnified extends RecyclerView.Adapter<AdapterNavUnified.Vi
}
private void bindTo(TupleFolderUnified folder) {
int start = (folder.category == null ? 0 : (expanded ? dp12 : dp6));
view.setPaddingRelative(start, 0, 0, 0);
if (folder.type == null)
ivItem.setImageResource(R.drawable.twotone_all_inbox_24);
else if (EntityFolder.INBOX.equals(folder.type))
@ -127,9 +134,10 @@ public class AdapterNavUnified extends RecyclerView.Adapter<AdapterNavUnified.Vi
tvCount.setText(Helper.formatNumber(count, 99, NF));
tvCount.setVisibility(count == 0 || expanded || !nav_count_pinned ? View.GONE : View.VISIBLE);
String name = (folder.type == null
? context.getString(R.string.title_folder_unified)
: EntityFolder.localizeType(context, folder.type));
String name = (folder.category != null ? folder.category :
(folder.type == null
? context.getString(R.string.title_folder_unified)
: EntityFolder.localizeType(context, folder.type)));
int unexposed = (show_unexposed ? folder.unexposed : 0);
if (count > 0 || unexposed > 0) {
@ -169,15 +177,16 @@ public class AdapterNavUnified extends RecyclerView.Adapter<AdapterNavUnified.Vi
LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(context);
if (EntityFolder.OUTBOX.equals(folder.type))
lbm.sendBroadcast(new Intent(ActivityView.ACTION_VIEW_OUTBOX));
else if ("inbox".equals(startup) && EntityFolder.INBOX.equals(folder.type))
else if ("inbox".equals(startup) && EntityFolder.INBOX.equals(folder.type) && folder.category == null)
lbm.sendBroadcast(
new Intent(ActivityView.ACTION_VIEW_MESSAGES)
.putExtra("type", (String) null)
.putExtra("unified", true));
else if (folder.folders > 1 || folder.type == null)
else if (folder.folders > 1 || folder.type == null || folder.category != null)
lbm.sendBroadcast(
new Intent(ActivityView.ACTION_VIEW_MESSAGES)
.putExtra("type", folder.type)
.putExtra("category", folder.category)
.putExtra("unified", folder.type == null));
else {
Bundle args = new Bundle();
@ -224,6 +233,9 @@ public class AdapterNavUnified extends RecyclerView.Adapter<AdapterNavUnified.Vi
this.owner = owner;
this.inflater = LayoutInflater.from(context);
this.dp6 = Helper.dp2pixels(context, 6);
this.dp12 = Helper.dp2pixels(context, 12);
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
this.nav_count = prefs.getBoolean("nav_count", false);
this.nav_count_pinned = prefs.getBoolean("nav_count_pinned", false);
@ -242,42 +254,52 @@ public class AdapterNavUnified extends RecyclerView.Adapter<AdapterNavUnified.Vi
Map<String, TupleFolderUnified> map = new HashMap<>();
TupleFolderUnified unified = new TupleFolderUnified();
for (TupleFolderUnified type : new ArrayList<>(folders)) {
TupleFolderUnified f = map.get(type.type);
if (!EntityFolder.SYSTEM.equals(type.type) &&
!EntityFolder.USER.equals(type.type))
if (f == null)
map.put(type.type, type);
else {
f.folders += type.folders;
f.messages += type.messages;
f.unseen += type.unseen;
f.unexposed += type.unexposed;
if (Objects.equals(f.color, type.color) ||
(f.color == null && f.folders == type.folders)) {
f.color = type.color;
f.colorCount += type.colorCount;
if (!EntityFolder.INBOX.equals(type.type))
type.category = null;
for (int i = 0; i < 1 + (type.category == null ? 0 : 1); i++) {
if (i > 0) {
type = new TupleFolderUnified(type);
type.category = null;
}
String key = (type.category + "/" + type.type);
TupleFolderUnified f = map.get(key);
if (!EntityFolder.SYSTEM.equals(type.type) &&
!EntityFolder.USER.equals(type.type))
if (f == null)
map.put(key, type);
else {
f.folders += type.folders;
f.messages += type.messages;
f.unseen += type.unseen;
f.unexposed += type.unexposed;
if (Objects.equals(f.color, type.color) ||
(f.color == null && f.folders == type.folders)) {
f.color = type.color;
f.colorCount += type.colorCount;
} else
f.colorCount++;
}
if (type.unified && i == 0) {
unified.folders += type.folders;
unified.messages += type.messages;
unified.unseen += type.unseen;
unified.unexposed = type.unexposed;
if (Objects.equals(unified.color, type.color) ||
(unified.color == null && unified.folders == type.folders)) {
unified.color = type.color;
unified.colorCount += type.colorCount;
} else
f.colorCount++;
unified.colorCount++;
}
if (type.unified) {
unified.folders += type.folders;
unified.messages += type.messages;
unified.unseen += type.unseen;
unified.unexposed = type.unexposed;
if (Objects.equals(unified.color, type.color) ||
(unified.color == null && unified.folders == type.folders)) {
unified.color = type.color;
unified.colorCount += type.colorCount;
} else
unified.colorCount++;
if ((EntityFolder.INBOX.equals(type.type) && !type.unified) ||
(!EntityFolder.INBOX.equals(type.type) && type.unified))
show = true;
}
if ((EntityFolder.INBOX.equals(type.type) && !type.unified) ||
(!EntityFolder.INBOX.equals(type.type) && type.unified))
show = true;
}
TupleFolderUnified inbox = map.get(EntityFolder.INBOX);
@ -290,12 +312,21 @@ public class AdapterNavUnified extends RecyclerView.Adapter<AdapterNavUnified.Vi
if (unified.folders > 0 && show)
types.add(unified);
final Collator collator = Collator.getInstance(Locale.getDefault());
collator.setStrength(Collator.SECONDARY); // Case insensitive, process accents etc
Collections.sort(types, new Comparator<TupleFolderUnified>() {
@Override
public int compare(TupleFolderUnified f1, TupleFolderUnified f2) {
int i1 = EntityFolder.FOLDER_SORT_ORDER.indexOf(f1.type);
int i2 = EntityFolder.FOLDER_SORT_ORDER.indexOf(f2.type);
return Integer.compare(i1, i2);
int f = Integer.compare(i1, i2);
if (f == 0)
return collator.compare(
f1.category == null ? "" : f1.category,
f2.category == null ? "" : f2.category);
else
return f;
}
});

@ -120,13 +120,14 @@ public interface DaoFolder {
" LEFT JOIN operation ON operation.folder = folder.id" +
" WHERE account.`synchronize`" +
" AND ((:type IS NULL AND folder.unified) OR folder.type = :type)" +
" AND (:category IS NULL OR account.category = :category)" +
" GROUP BY folder.id";
@Query(queryUnified)
LiveData<List<TupleFolderEx>> liveUnified(String type);
LiveData<List<TupleFolderEx>> liveUnified(String type, String category);
@Query(queryUnified)
List<TupleFolderEx> getUnified(String type);
List<TupleFolderEx> getUnified(String type, String category);
@Query("SELECT folder.account, folder.id AS folder, unified, sync_state" +
" FROM folder" +
@ -190,7 +191,7 @@ public interface DaoFolder {
" ORDER BY name COLLATE NOCASE")
List<EntityFolder> getChildFolders(long parent);
@Query("SELECT folder.type, folder.unified" +
@Query("SELECT folder.type, account.category, folder.unified" +
", COUNT(DISTINCT folder.id) AS folders" +
", COUNT(message.id) AS messages" +
", SUM(CASE WHEN NOT message.ui_seen THEN 1 ELSE 0 END) AS unseen" +
@ -204,7 +205,7 @@ public interface DaoFolder {
" AND ((folder.type <> '" + EntityFolder.SYSTEM + "'" +
" AND folder.type <> '" + EntityFolder.USER + "')" +
" OR folder.unified)" +
" GROUP BY folder.type, folder.unified")
" GROUP BY folder.type, account.category, folder.unified")
LiveData<List<TupleFolderUnified>> liveUnified();
@Query("SELECT * FROM folder" +

@ -79,6 +79,7 @@ public interface DaoMessage {
" LEFT JOIN identity_view AS identity ON identity.id = message.identity" +
" JOIN folder_view AS folder ON folder.id = message.folder" +
" WHERE account.`synchronize`" +
" AND (:category IS NULL OR account.category = :category)" +
" AND (:threading OR (:type IS NULL AND (folder.unified OR :found)) OR (:type IS NOT NULL AND folder.type = :type))" +
" AND (NOT message.ui_hide OR :debug)" +
" AND (NOT :found OR message.ui_found = :found)" +
@ -114,7 +115,7 @@ public interface DaoMessage {
" END" +
", CASE WHEN :ascending THEN message.received ELSE -message.received END")
DataSource.Factory<Integer, TupleMessageEx> pagedUnified(
String type,
String type, String category,
boolean threading, boolean group_category,
String sort1, String sort2, boolean ascending,
boolean filter_seen, boolean filter_unflagged, boolean filter_unknown, boolean filter_snoozed, boolean filter_deleted, String filter_language,
@ -1113,6 +1114,7 @@ public interface DaoMessage {
" LEFT JOIN identity_view AS identity ON identity.id = message.identity" +
" JOIN folder_view AS folder ON folder.id = message.folder" +
" WHERE account.`synchronize`" +
" AND (:category IS NULL OR account.category = :category)" +
" AND (:threading OR (:type IS NULL AND (folder.unified OR :found)) OR (:type IS NOT NULL AND folder.type = :type))" +
" AND (NOT message.ui_hide OR :debug)" +
" AND (NOT :found OR message.ui_found = :found)" +
@ -1148,7 +1150,7 @@ public interface DaoMessage {
" END" +
", CASE WHEN :ascending THEN message.received ELSE -message.received END")
DataSource.Factory<Integer, TupleMessageEx> pagedUnifiedLegacy(
String type,
String type, String category,
boolean threading, boolean group_category,
String sort1, String sort2, boolean ascending,
boolean filter_seen, boolean filter_unflagged, boolean filter_unknown, boolean filter_snoozed, boolean filter_deleted, String filter_language,

@ -80,7 +80,7 @@ public class FragmentDialogSelectUnifiedFolder extends FragmentDialogBase {
@Override
protected List<TupleFolderEx> onExecute(Context context, Bundle args) {
DB db = DB.getInstance(context);
return db.folder().getUnified(null);
return db.folder().getUnified(null, null);
}
@Override

@ -319,6 +319,7 @@ public class FragmentMessages extends FragmentBase
private ObjectAnimator animator;
private String type;
private String category;
private long account;
private long folder;
private boolean server;
@ -339,7 +340,7 @@ public class FragmentMessages extends FragmentBase
private boolean cards;
private boolean dividers;
private boolean category;
private boolean group_category;
private boolean date;
private boolean date_week;
private boolean date_fixed;
@ -464,6 +465,7 @@ public class FragmentMessages extends FragmentBase
// Get arguments
Bundle args = getArguments();
type = args.getString("type");
category = args.getString("category");
account = args.getLong("account", -1);
folder = args.getLong("folder", -1);
server = args.getBoolean("server", false);
@ -494,7 +496,7 @@ public class FragmentMessages extends FragmentBase
cards = prefs.getBoolean("cards", true);
dividers = prefs.getBoolean("dividers", true);
category = prefs.getBoolean("group_category", false);
group_category = (category == null && prefs.getBoolean("group_category", false));
date = prefs.getBoolean("date", true);
date_week = prefs.getBoolean("date_week", false);
date_fixed = (!date && prefs.getBoolean("date_fixed", false));
@ -1020,7 +1022,7 @@ public class FragmentMessages extends FragmentBase
if (message == null)
return null;
boolean ch = (category &&
boolean ch = (group_category &&
viewType == AdapterMessage.ViewType.UNIFIED &&
(pos == 0
? message.accountCategory != null
@ -5392,7 +5394,7 @@ public class FragmentMessages extends FragmentBase
// Folder
switch (viewType) {
case UNIFIED:
db.folder().liveUnified(type).observe(getViewLifecycleOwner(), new Observer<List<TupleFolderEx>>() {
db.folder().liveUnified(type, category).observe(getViewLifecycleOwner(), new Observer<List<TupleFolderEx>>() {
@Override
public void onChanged(List<TupleFolderEx> folders) {
updateState(folders);
@ -7045,7 +7047,7 @@ public class FragmentMessages extends FragmentBase
if (name == null)
name = getString(R.string.title_folder_unified);
} else
name = "»" + EntityFolder.localizeType(context, type);
name = "»" + EntityFolder.localizeType(context, type) + (category == null ? "" : "/" + category);
else {
name = (folders.size() > 0 ? folders.get(0).getDisplayName(context) : "");
if (folders.size() == 1) {
@ -7291,7 +7293,7 @@ public class FragmentMessages extends FragmentBase
ViewModelMessages.Model vmodel = model.getModel(
getContext(), getViewLifecycleOwner(),
viewType, type, account, folder, thread, id, threading, filter_archive, criteria, server);
viewType, type, category, account, folder, thread, id, threading, filter_archive, criteria, server);
initialized = false;
loading = false;

@ -23,6 +23,7 @@ import java.util.Objects;
public class TupleFolderUnified {
public String type;
public String category;
public boolean unified;
public int folders;
public int messages;
@ -32,11 +33,28 @@ public class TupleFolderUnified {
public Integer color;
public int colorCount;
TupleFolderUnified() {
}
TupleFolderUnified(TupleFolderUnified other) {
this.type = other.type;
this.category = other.category;
this.unified = other.unified;
this.folders = other.folders;
this.messages = other.messages;
this.unseen = other.unseen;
this.unexposed = other.unexposed;
this.sync_state = other.sync_state;
this.color = other.color;
this.colorCount = other.colorCount;
}
@Override
public boolean equals(Object obj) {
if (obj instanceof TupleFolderUnified) {
TupleFolderUnified other = (TupleFolderUnified) obj;
return (Objects.equals(this.type, other.type) &&
Objects.equals(this.category, other.category) &&
this.unified == other.unified &&
this.folders == other.folders &&
this.messages == other.messages &&

@ -82,7 +82,7 @@ public class ViewModelMessages extends ViewModel {
Model getModel(
final Context context, final LifecycleOwner owner,
final AdapterMessage.ViewType viewType,
String type, long account, long folder,
String type, String category, long account, long folder,
String thread, long id,
boolean threading,
boolean filter_archive,
@ -93,7 +93,7 @@ public class ViewModelMessages extends ViewModel {
boolean cache_lists = prefs.getBoolean("cache_lists", true);
Args args = new Args(context,
viewType, type, account, folder,
viewType, type, category, account, folder,
thread, id, threading,
filter_archive, criteria, server);
Log.i("Get model=" + viewType + " " + args);
@ -128,6 +128,7 @@ public class ViewModelMessages extends ViewModel {
if (legacy)
pager = db.message().pagedUnifiedLegacy(
args.type,
args.category,
args.threading,
args.group_category,
args.sort1, args.sort2, args.ascending,
@ -142,6 +143,7 @@ public class ViewModelMessages extends ViewModel {
else
pager = db.message().pagedUnified(
args.type,
args.category,
args.threading,
args.group_category,
args.sort1, args.sort2, args.ascending,
@ -214,7 +216,7 @@ public class ViewModelMessages extends ViewModel {
if (args.folder < 0) {
if (legacy)
pager = db.message().pagedUnifiedLegacy(
null,
null, null,
args.threading, false,
criteria == null || criteria.touched == null ? "time" : "touched", "", false,
false, false, false, false, false,
@ -223,7 +225,7 @@ public class ViewModelMessages extends ViewModel {
args.debug);
else
pager = db.message().pagedUnified(
null,
null, null,
args.threading, false,
criteria == null || criteria.touched == null ? "time" : "touched", "", false,
false, false, false, false, false,
@ -562,6 +564,7 @@ public class ViewModelMessages extends ViewModel {
private class Args {
private long account;
private String type;
private String category;
private long folder;
private String thread;
private long id;
@ -584,12 +587,13 @@ public class ViewModelMessages extends ViewModel {
Args(Context context,
AdapterMessage.ViewType viewType,
String type, long account, long folder,
String type, String category, long account, long folder,
String thread, long id, boolean threading,
boolean filter_archive,
BoundaryCallbackMessages.SearchCriteria criteria, boolean server) {
this.type = type;
this.category = category;
this.account = account;
this.folder = folder;
this.thread = thread;
@ -626,6 +630,7 @@ public class ViewModelMessages extends ViewModel {
if (obj instanceof Args) {
Args other = (Args) obj;
return (Objects.equals(this.type, other.type) &&
Objects.equals(this.category, other.category) &&
this.account == other.account &&
this.folder == other.folder &&
Objects.equals(this.thread, other.thread) &&
@ -653,7 +658,7 @@ public class ViewModelMessages extends ViewModel {
@NonNull
@Override
public String toString() {
return "folder=" + type + ":" + account + ":" + folder +
return "folder=" + type + "/" + category + ":" + account + ":" + folder +
" thread=" + thread + ":" + id +
" criteria=" + criteria + ":" + server + "" +
" threading=" + threading +

Loading…
Cancel
Save