Collapsible folder selector

pull/156/head
M66B 6 years ago
parent 9dd73d9d46
commit dca3447446

@ -69,6 +69,7 @@ public class AdapterFolder extends RecyclerView.Adapter<AdapterFolder.ViewHolder
private boolean show_hidden; private boolean show_hidden;
private long account; private long account;
private IFolderSelectedListener listener;
private boolean subscriptions; private boolean subscriptions;
private boolean debug; private boolean debug;
@ -141,7 +142,7 @@ public class AdapterFolder extends RecyclerView.Adapter<AdapterFolder.ViewHolder
private void bindTo(final TupleFolderEx folder) { private void bindTo(final TupleFolderEx folder) {
boolean hidden = (folder.hide && !show_hidden); boolean hidden = (folder.hide && !show_hidden);
int level = 1; int level = 0;
TupleFolderEx parent = folder.parent_ref; TupleFolderEx parent = folder.parent_ref;
while (parent != null) { while (parent != null) {
level++; level++;
@ -150,6 +151,20 @@ public class AdapterFolder extends RecyclerView.Adapter<AdapterFolder.ViewHolder
parent = parent.parent_ref; parent = parent.parent_ref;
} }
boolean root_childs_visible = false;
if (folder.parent_ref != null &&
folder.parent_ref.parent_ref == null &&
folder.parent_ref.child_refs != null) {
for (TupleFolderEx root : folder.parent_ref.child_refs)
if ((!root.hide || show_hidden) && root.child_refs != null)
for (TupleFolderEx child : root.child_refs)
if (!child.hide || show_hidden) {
root_childs_visible = true;
break;
}
} else
root_childs_visible = true;
boolean childs_visible = false; boolean childs_visible = false;
if (folder.child_refs != null) if (folder.child_refs != null)
for (TupleFolderEx child : folder.child_refs) for (TupleFolderEx child : folder.child_refs)
@ -165,49 +180,53 @@ public class AdapterFolder extends RecyclerView.Adapter<AdapterFolder.ViewHolder
if (textSize != 0) if (textSize != 0)
tvName.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize); tvName.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize);
vwColor.setBackgroundColor(folder.accountColor == null ? Color.TRANSPARENT : folder.accountColor); if (listener == null) {
vwColor.setVisibility(account < 0 ? View.VISIBLE : View.GONE); vwColor.setBackgroundColor(folder.accountColor == null ? Color.TRANSPARENT : folder.accountColor);
vwColor.setVisibility(account < 0 ? View.VISIBLE : View.GONE);
if (folder.sync_state == null || "requested".equals(folder.sync_state)) {
if (folder.executing > 0) if (folder.sync_state == null || "requested".equals(folder.sync_state)) {
ivState.setImageResource(R.drawable.baseline_dns_24); if (folder.executing > 0)
else if ("waiting".equals(folder.state)) ivState.setImageResource(R.drawable.baseline_dns_24);
ivState.setImageResource(R.drawable.baseline_hourglass_empty_24); else if ("waiting".equals(folder.state))
else if ("connected".equals(folder.state)) ivState.setImageResource(R.drawable.baseline_hourglass_empty_24);
ivState.setImageResource(R.drawable.baseline_cloud_24); else if ("connected".equals(folder.state))
else if ("connecting".equals(folder.state)) ivState.setImageResource(R.drawable.baseline_cloud_24);
ivState.setImageResource(R.drawable.baseline_cloud_queue_24); else if ("connecting".equals(folder.state))
else if ("closing".equals(folder.state)) ivState.setImageResource(R.drawable.baseline_cloud_queue_24);
ivState.setImageResource(R.drawable.baseline_close_24); else if ("closing".equals(folder.state))
else if (folder.state == null) ivState.setImageResource(R.drawable.baseline_close_24);
ivState.setImageResource(R.drawable.baseline_cloud_off_24); else if (folder.state == null)
else ivState.setImageResource(R.drawable.baseline_cloud_off_24);
ivState.setImageResource(R.drawable.baseline_warning_24); else
} else { ivState.setImageResource(R.drawable.baseline_warning_24);
if ("syncing".equals(folder.sync_state)) } else {
ivState.setImageResource(R.drawable.baseline_compare_arrows_24); if ("syncing".equals(folder.sync_state))
else if ("downloading".equals(folder.sync_state)) ivState.setImageResource(R.drawable.baseline_compare_arrows_24);
ivState.setImageResource(R.drawable.baseline_cloud_download_24); else if ("downloading".equals(folder.sync_state))
else ivState.setImageResource(R.drawable.baseline_cloud_download_24);
ivState.setImageResource(R.drawable.baseline_warning_24); else
} ivState.setImageResource(R.drawable.baseline_warning_24);
ivState.setVisibility( }
folder.synchronize || folder.state != null || folder.sync_state != null ivState.setVisibility(
? View.VISIBLE : View.INVISIBLE); folder.synchronize || folder.state != null || folder.sync_state != null
? View.VISIBLE : View.INVISIBLE);
ivReadOnly.setVisibility(folder.read_only ? View.VISIBLE : View.GONE); ivReadOnly.setVisibility(folder.read_only ? View.VISIBLE : View.GONE);
}
ViewGroup.LayoutParams lp = vwLevel.getLayoutParams(); ViewGroup.LayoutParams lp = vwLevel.getLayoutParams();
lp.width = (account < 0 ? 1 : level) * dp12; lp.width = (account < 0 ? 1 : level) * dp12;
vwLevel.setLayoutParams(lp); vwLevel.setLayoutParams(lp);
ivExpander.setImageLevel(folder.collapsed ? 1 /* more */ : 0 /* less */); ivExpander.setImageLevel(folder.collapsed ? 1 /* more */ : 0 /* less */);
ivExpander.setVisibility(account < 0 ivExpander.setVisibility(account < 0 || !root_childs_visible
? View.GONE ? View.GONE
: childs_visible ? View.VISIBLE : View.INVISIBLE); : childs_visible ? View.VISIBLE : View.INVISIBLE);
ivNotify.setVisibility(folder.notify ? View.VISIBLE : View.GONE); if (listener == null) {
ivSubscribed.setVisibility(subscriptions && folder.subscribed != null && folder.subscribed ? View.VISIBLE : View.GONE); ivNotify.setVisibility(folder.notify ? View.VISIBLE : View.GONE);
ivSubscribed.setVisibility(subscriptions && folder.subscribed != null && folder.subscribed ? View.VISIBLE : View.GONE);
}
if (folder.unseen > 0) if (folder.unseen > 0)
tvName.setText(context.getString(R.string.title_name_count, tvName.setText(context.getString(R.string.title_name_count,
@ -219,60 +238,65 @@ public class AdapterFolder extends RecyclerView.Adapter<AdapterFolder.ViewHolder
tvName.setTypeface(null, folder.unseen > 0 ? Typeface.BOLD : Typeface.NORMAL); tvName.setTypeface(null, folder.unseen > 0 ? Typeface.BOLD : Typeface.NORMAL);
tvName.setTextColor(folder.unseen > 0 ? colorUnread : textColorSecondary); tvName.setTextColor(folder.unseen > 0 ? colorUnread : textColorSecondary);
StringBuilder sb = new StringBuilder(); if (listener == null) {
if (folder.account == null) StringBuilder sb = new StringBuilder();
sb.append(nf.format(folder.messages)); if (folder.account == null)
else { sb.append(nf.format(folder.messages));
sb.append(nf.format(folder.content)); else {
sb.append('/'); sb.append(nf.format(folder.content));
sb.append(nf.format(folder.messages)); sb.append('/');
sb.append('/'); sb.append(nf.format(folder.messages));
if (folder.total == null) sb.append('/');
sb.append('?'); if (folder.total == null)
else sb.append('?');
sb.append(nf.format(folder.total)); else
} sb.append(nf.format(folder.total));
tvMessages.setText(sb.toString()); }
tvMessages.setText(sb.toString());
ivMessages.setImageResource(folder.download || EntityFolder.OUTBOX.equals(folder.type) ivMessages.setImageResource(folder.download || EntityFolder.OUTBOX.equals(folder.type)
? R.drawable.baseline_mail_24 : R.drawable.baseline_mail_outline_24); ? R.drawable.baseline_mail_24 : R.drawable.baseline_mail_outline_24);
}
ivType.setImageResource(EntityFolder.getIcon(folder.type)); ivType.setImageResource(EntityFolder.getIcon(folder.type));
ivUnified.setVisibility(account > 0 && folder.unified ? View.VISIBLE : View.GONE);
if (account < 0) if (listener == null) {
tvType.setText(folder.accountName); ivUnified.setVisibility(account > 0 && folder.unified ? View.VISIBLE : View.GONE);
else {
int resid = context.getResources().getIdentifier( if (account < 0)
"title_folder_" + folder.type.toLowerCase(), tvType.setText(folder.accountName);
"string", else {
context.getPackageName()); int resid = context.getResources().getIdentifier(
tvType.setText(resid > 0 ? context.getString(resid) : folder.type); "title_folder_" + folder.type.toLowerCase(),
} "string",
context.getPackageName());
tvType.setText(resid > 0 ? context.getString(resid) : folder.type);
}
if (folder.account == null) { if (folder.account == null) {
tvAfter.setText(null); tvAfter.setText(null);
ivSync.setImageResource(R.drawable.baseline_sync_24); ivSync.setImageResource(R.drawable.baseline_sync_24);
} else { } else {
StringBuilder a = new StringBuilder(); StringBuilder a = new StringBuilder();
a.append(nf.format(folder.sync_days)); a.append(nf.format(folder.sync_days));
a.append('/'); a.append('/');
if (folder.keep_days == Integer.MAX_VALUE) if (folder.keep_days == Integer.MAX_VALUE)
a.append('∞'); a.append('∞');
else else
a.append(nf.format(folder.keep_days)); a.append(nf.format(folder.keep_days));
tvAfter.setText(a.toString()); tvAfter.setText(a.toString());
ivSync.setImageResource(folder.synchronize ? R.drawable.baseline_sync_24 : R.drawable.baseline_sync_disabled_24); ivSync.setImageResource(folder.synchronize ? R.drawable.baseline_sync_24 : R.drawable.baseline_sync_disabled_24);
} }
ivSync.setImageTintList(ColorStateList.valueOf( ivSync.setImageTintList(ColorStateList.valueOf(
folder.synchronize && folder.initialize && !EntityFolder.OUTBOX.equals(folder.type) folder.synchronize && folder.initialize && !EntityFolder.OUTBOX.equals(folder.type)
? colorUnread : textColorSecondary)); ? colorUnread : textColorSecondary));
tvKeywords.setText(TextUtils.join(" ", folder.keywords)); tvKeywords.setText(TextUtils.join(" ", folder.keywords));
tvKeywords.setVisibility(debug && folder.keywords.length > 0 ? View.VISIBLE : View.GONE); tvKeywords.setVisibility(debug && folder.keywords.length > 0 ? View.VISIBLE : View.GONE);
tvError.setText(folder.error); tvError.setText(folder.error);
tvError.setVisibility(folder.error != null ? View.VISIBLE : View.GONE); tvError.setVisibility(folder.error != null ? View.VISIBLE : View.GONE);
}
} }
@Override @Override
@ -288,15 +312,24 @@ public class AdapterFolder extends RecyclerView.Adapter<AdapterFolder.ViewHolder
if (view.getId() == R.id.ivExpander) if (view.getId() == R.id.ivExpander)
onCollapse(folder); onCollapse(folder);
else { else {
LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(context); if (listener == null) {
lbm.sendBroadcast( LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(context);
new Intent(ActivityView.ACTION_VIEW_MESSAGES) lbm.sendBroadcast(
.putExtra("account", folder.account) new Intent(ActivityView.ACTION_VIEW_MESSAGES)
.putExtra("folder", folder.id)); .putExtra("account", folder.account)
.putExtra("folder", folder.id));
} else
listener.onFolderSelected(folder);
} }
} }
private void onCollapse(TupleFolderEx folder) { private void onCollapse(TupleFolderEx folder) {
if (listener != null) {
folder.collapsed = !folder.collapsed;
notifyDataSetChanged();
return;
}
Bundle args = new Bundle(); Bundle args = new Bundle();
args.putLong("id", folder.id); args.putLong("id", folder.id);
args.putBoolean("collapsed", !folder.collapsed); args.putBoolean("collapsed", !folder.collapsed);
@ -648,12 +681,13 @@ public class AdapterFolder extends RecyclerView.Adapter<AdapterFolder.ViewHolder
} }
} }
AdapterFolder(Context context, LifecycleOwner owner, long account, boolean show_hidden) { AdapterFolder(Context context, LifecycleOwner owner, long account, boolean show_hidden, IFolderSelectedListener listener) {
this.context = context; this.context = context;
this.inflater = LayoutInflater.from(context); this.inflater = LayoutInflater.from(context);
this.owner = owner; this.owner = owner;
this.account = account; this.account = account;
this.show_hidden = show_hidden; this.show_hidden = show_hidden;
this.listener = listener;
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
boolean compact = prefs.getBoolean("compact", false); boolean compact = prefs.getBoolean("compact", false);
@ -696,11 +730,18 @@ public class AdapterFolder extends RecyclerView.Adapter<AdapterFolder.ViewHolder
} }
} }
TupleFolderEx root = new TupleFolderEx();
root.child_refs = parents;
for (TupleFolderEx parent : parents)
parent.parent_ref = root;
for (long pid : parentChilds.keySet()) { for (long pid : parentChilds.keySet()) {
TupleFolderEx parent = idFolder.get(pid); TupleFolderEx parent = idFolder.get(pid);
parent.child_refs = parentChilds.get(pid); if (parent != null) {
for (TupleFolderEx child : parent.child_refs) parent.child_refs = parentChilds.get(pid);
child.parent_ref = parent; for (TupleFolderEx child : parent.child_refs)
child.parent_ref = parent;
}
} }
List<TupleFolderEx> hierarchical = getHierchical(parents); List<TupleFolderEx> hierarchical = getHierchical(parents);
@ -783,7 +824,9 @@ public class AdapterFolder extends RecyclerView.Adapter<AdapterFolder.ViewHolder
TupleFolderEx f1 = prev.get(oldItemPosition); TupleFolderEx f1 = prev.get(oldItemPosition);
TupleFolderEx f2 = next.get(newItemPosition); TupleFolderEx f2 = next.get(newItemPosition);
boolean e = f1.equals(f2); boolean e = f1.equals(f2);
if (!e || f1.parent_ref == null || f2.parent_ref == null) if (!e ||
f1.parent_ref == null || f1.parent_ref.id == null ||
f2.parent_ref == null || f2.parent_ref.id == null)
return e; return e;
return f1.parent_ref.equals(f2.parent_ref); return f1.parent_ref.equals(f2.parent_ref);
} }
@ -802,7 +845,9 @@ public class AdapterFolder extends RecyclerView.Adapter<AdapterFolder.ViewHolder
@Override @Override
@NonNull @NonNull
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
return new ViewHolder(inflater.inflate(R.layout.item_folder, parent, false)); return new ViewHolder(inflater.inflate(
listener == null ? R.layout.item_folder : R.layout.item_folder_select,
parent, false));
} }
@Override @Override
@ -819,4 +864,8 @@ public class AdapterFolder extends RecyclerView.Adapter<AdapterFolder.ViewHolder
holder.wire(); holder.wire();
} }
interface IFolderSelectedListener {
void onFolderSelected(TupleFolderEx folder);
}
} }

@ -1,184 +0,0 @@
package eu.faircode.email;
/*
This file is part of FairEmail.
FairEmail is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
FairEmail is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with FairEmail. If not, see <http://www.gnu.org/licenses/>.
Copyright 2018-2019 by Marcel Bokhorst (M66B)
*/
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.lifecycle.LifecycleOwner;
import androidx.recyclerview.widget.DiffUtil;
import androidx.recyclerview.widget.ListUpdateCallback;
import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;
import java.util.List;
public class AdapterFolderSelect extends RecyclerView.Adapter<AdapterFolderSelect.ViewHolder> {
private Context context;
private LifecycleOwner owner;
private IFolderSelectedListener listener;
private LayoutInflater inflater;
private List<EntityFolder> items = new ArrayList<>();
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
private View view;
private ImageView ivType;
private TextView tvName;
ViewHolder(View itemView) {
super(itemView);
view = itemView.findViewById(R.id.clItem);
ivType = itemView.findViewById(R.id.ivType);
tvName = itemView.findViewById(R.id.tvName);
}
private void wire() {
view.setOnClickListener(this);
}
private void unwire() {
view.setOnClickListener(null);
}
private void bindTo(EntityFolder folder) {
ivType.setImageResource(EntityFolder.getIcon(folder.type));
tvName.setText(folder.getDisplayName(context));
}
@Override
public void onClick(View v) {
int pos = getAdapterPosition();
if (pos == RecyclerView.NO_POSITION)
return;
EntityFolder folder = items.get(pos);
if (folder != null)
listener.onFolderSelected(folder);
}
}
AdapterFolderSelect(Context context, LifecycleOwner owner, IFolderSelectedListener listener) {
this.context = context;
this.owner = owner;
this.listener = listener;
this.inflater = LayoutInflater.from(context);
setHasStableIds(true);
}
public void set(@NonNull List<EntityFolder> folders) {
Log.i("Set folders=" + folders.size());
DiffUtil.DiffResult diff = DiffUtil.calculateDiff(new DiffCallback(items, folders), false);
items = folders;
diff.dispatchUpdatesTo(new ListUpdateCallback() {
@Override
public void onInserted(int position, int count) {
Log.i("Inserted @" + position + " #" + count);
}
@Override
public void onRemoved(int position, int count) {
Log.i("Removed @" + position + " #" + count);
}
@Override
public void onMoved(int fromPosition, int toPosition) {
Log.i("Moved " + fromPosition + ">" + toPosition);
}
@Override
public void onChanged(int position, int count, Object payload) {
Log.i("Changed @" + position + " #" + count);
}
});
diff.dispatchUpdatesTo(this);
}
private class DiffCallback extends DiffUtil.Callback {
private List<EntityFolder> prev = new ArrayList<>();
private List<EntityFolder> next = new ArrayList<>();
DiffCallback(List<EntityFolder> prev, List<EntityFolder> next) {
this.prev.addAll(prev);
this.next.addAll(next);
}
@Override
public int getOldListSize() {
return prev.size();
}
@Override
public int getNewListSize() {
return next.size();
}
@Override
public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) {
EntityFolder m1 = prev.get(oldItemPosition);
EntityFolder m2 = next.get(newItemPosition);
return m1.id.equals(m2.id);
}
@Override
public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) {
EntityFolder m1 = prev.get(oldItemPosition);
EntityFolder m2 = next.get(newItemPosition);
return m1.id.equals(m2.id);
}
}
@Override
public long getItemId(int position) {
return items.get(position).id;
}
@Override
public int getItemCount() {
return items.size();
}
@Override
@NonNull
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
return new ViewHolder(inflater.inflate(R.layout.item_folder_select, parent, false));
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
holder.unwire();
EntityFolder folder = items.get(position);
holder.bindTo(folder);
holder.wire();
}
interface IFolderSelectedListener {
void onFolderSelected(EntityFolder folder);
}
}

@ -3063,49 +3063,50 @@ public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHold
LinearLayoutManager llm = new LinearLayoutManager(context); LinearLayoutManager llm = new LinearLayoutManager(context);
rvFolder.setLayoutManager(llm); rvFolder.setLayoutManager(llm);
final AdapterFolderSelect adapter = new AdapterFolderSelect(context, owner, new AdapterFolderSelect.IFolderSelectedListener() { final AdapterFolder adapter = new AdapterFolder(context, owner, data.message.account, false,
@Override new AdapterFolder.IFolderSelectedListener() {
public void onFolderSelected(EntityFolder folder) { @Override
dialog.dismiss(); public void onFolderSelected(TupleFolderEx folder) {
dialog.dismiss();
if (copy) { if (copy) {
Bundle args = new Bundle(); Bundle args = new Bundle();
args.putLong("id", data.message.id); args.putLong("id", data.message.id);
args.putLong("target", folder.id); args.putLong("target", folder.id);
new SimpleTask<Void>() { new SimpleTask<Void>() {
@Override @Override
protected Void onExecute(Context context, Bundle args) { protected Void onExecute(Context context, Bundle args) {
long id = args.getLong("id"); long id = args.getLong("id");
long target = args.getLong("target"); long target = args.getLong("target");
DB db = DB.getInstance(context); DB db = DB.getInstance(context);
try { try {
db.beginTransaction(); db.beginTransaction();
EntityMessage message = db.message().getMessage(id); EntityMessage message = db.message().getMessage(id);
if (message == null) if (message == null)
return null; return null;
EntityOperation.queue(context, message, EntityOperation.COPY, target); EntityOperation.queue(context, message, EntityOperation.COPY, target);
db.setTransactionSuccessful(); db.setTransactionSuccessful();
} finally { } finally {
db.endTransaction(); db.endTransaction();
} }
return null; return null;
} }
@Override @Override
protected void onException(Bundle args, Throwable ex) { protected void onException(Bundle args, Throwable ex) {
Helper.unexpectedError(context, owner, ex); Helper.unexpectedError(context, owner, ex);
} }
}.execute(context, owner, args, "message:copy"); }.execute(context, owner, args, "message:copy");
} else } else
properties.move(data.message.id, folder.name, false); properties.move(data.message.id, folder.name, false);
} }
}); });
rvFolder.setAdapter(adapter); rvFolder.setAdapter(adapter);
@ -3117,14 +3118,14 @@ public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHold
args.putLong("id", data.message.id); args.putLong("id", data.message.id);
args.putBoolean("copy", copy); args.putBoolean("copy", copy);
new SimpleTask<List<EntityFolder>>() { new SimpleTask<List<TupleFolderEx>>() {
@Override @Override
protected List<EntityFolder> onExecute(Context context, Bundle args) { protected List<TupleFolderEx> onExecute(Context context, Bundle args) {
long id = args.getLong("id"); long id = args.getLong("id");
boolean copy = args.getBoolean("copy"); boolean copy = args.getBoolean("copy");
EntityMessage message; EntityMessage message;
List<EntityFolder> folders; List<TupleFolderEx> folders;
DB db = DB.getInstance(context); DB db = DB.getInstance(context);
try { try {
@ -3134,7 +3135,7 @@ public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHold
if (message == null) if (message == null)
return null; return null;
folders = db.folder().getFolders(message.account); folders = db.folder().getFoldersEx(message.account);
db.setTransactionSuccessful(); db.setTransactionSuccessful();
} finally { } finally {
@ -3144,24 +3145,20 @@ public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHold
if (folders == null) if (folders == null)
return null; return null;
List<EntityFolder> targets = new ArrayList<>(); List<TupleFolderEx> targets = new ArrayList<>();
for (EntityFolder folder : folders) for (TupleFolderEx folder : folders)
if (!folder.hide && if (!folder.id.equals(message.folder) &&
!folder.id.equals(message.folder) &&
(copy || (copy ||
(!EntityFolder.ARCHIVE.equals(folder.type) && (!EntityFolder.ARCHIVE.equals(folder.type) &&
!EntityFolder.TRASH.equals(folder.type) && !EntityFolder.TRASH.equals(folder.type) &&
!EntityFolder.JUNK.equals(folder.type)))) !EntityFolder.JUNK.equals(folder.type))))
targets.add(folder); targets.add(folder);
if (targets.size() > 0)
Collections.sort(targets, targets.get(0).getComparator(context));
return targets; return targets;
} }
@Override @Override
protected void onExecuted(final Bundle args, List<EntityFolder> folders) { protected void onExecuted(final Bundle args, List<TupleFolderEx> folders) {
if (folders == null) if (folders == null)
folders = new ArrayList<>(); folders = new ArrayList<>();

@ -31,6 +31,19 @@ public interface DaoFolder {
@Query("SELECT * FROM folder WHERE account = :account") @Query("SELECT * FROM folder WHERE account = :account")
List<EntityFolder> getFolders(long account); List<EntityFolder> getFolders(long account);
@Query("SELECT folder.*" +
", account.`order` AS accountOrder, account.name AS accountName, account.color AS accountColor, account.state AS accountState" +
", COUNT(message.id) AS messages" +
", 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" +
", (SELECT COUNT(operation.id) FROM operation WHERE operation.folder = folder.id AND operation.state = 'executing') AS executing" +
" FROM folder" +
" LEFT JOIN account ON account.id = folder.account" +
" LEFT JOIN message ON message.folder = folder.id AND NOT message.ui_hide" +
" WHERE folder.account = :account AND account.synchronize" +
" GROUP BY folder.id")
List<TupleFolderEx> getFoldersEx(long account);
@Query("SELECT folder.* FROM folder" + @Query("SELECT folder.* FROM folder" +
" JOIN account ON account.id = folder.account" + " JOIN account ON account.id = folder.account" +
" WHERE account.synchronize" + " WHERE account.synchronize" +

@ -144,7 +144,7 @@ public class FragmentFolders extends FragmentBase {
itemDecorator.setDrawable(getContext().getDrawable(R.drawable.divider)); itemDecorator.setDrawable(getContext().getDrawable(R.drawable.divider));
rvFolder.addItemDecoration(itemDecorator); rvFolder.addItemDecoration(itemDecorator);
adapter = new AdapterFolder(getContext(), getViewLifecycleOwner(), account, show_hidden); adapter = new AdapterFolder(getContext(), getViewLifecycleOwner(), account, show_hidden, null);
rvFolder.setAdapter(adapter); rvFolder.setAdapter(adapter);
fab.setOnClickListener(new View.OnClickListener() { fab.setOnClickListener(new View.OnClickListener() {

@ -1389,19 +1389,15 @@ public class FragmentMessages extends FragmentBase {
result.accounts = db.account().getSynchronizingAccounts(); result.accounts = db.account().getSynchronizingAccounts();
for (EntityAccount account : result.accounts) { for (EntityAccount account : result.accounts) {
List<EntityFolder> targets = new ArrayList<>(); List<TupleFolderEx> targets = new ArrayList<>();
List<EntityFolder> folders = db.folder().getFolders(account.id); List<TupleFolderEx> folders = db.folder().getFoldersEx(account.id);
for (EntityFolder target : folders) for (TupleFolderEx target : folders)
if (!target.hide && if ((fids.size() != 1 || !fids.contains(target.id)) &&
!EntityFolder.ARCHIVE.equals(target.type) && !EntityFolder.ARCHIVE.equals(target.type) &&
!EntityFolder.TRASH.equals(target.type) && !EntityFolder.TRASH.equals(target.type) &&
!EntityFolder.JUNK.equals(target.type) && !EntityFolder.JUNK.equals(target.type))
(fids.size() != 1 || !fids.contains(target.id)))
targets.add(target); targets.add(target);
if (targets.size() > 0)
Collections.sort(targets, targets.get(0).getComparator(context));
result.targets.put(account.id, targets); result.targets.put(account.id, targets);
} }
@ -1482,7 +1478,7 @@ public class FragmentMessages extends FragmentBase {
return true; return true;
case R.string.title_move_to_account: case R.string.title_move_to_account:
long account = target.getIntent().getLongExtra("account", -1); long account = target.getIntent().getLongExtra("account", -1);
onActionMoveSelectionAccount(result.targets.get(account)); onActionMoveSelectionAccount(account, result.targets.get(account));
return true; return true;
default: default:
return false; return false;
@ -1833,7 +1829,7 @@ public class FragmentMessages extends FragmentBase {
}.execute(FragmentMessages.this, args, "messages:move"); }.execute(FragmentMessages.this, args, "messages:move");
} }
private void onActionMoveSelectionAccount(List<EntityFolder> folders) { private void onActionMoveSelectionAccount(long account, List<TupleFolderEx> folders) {
final View dview = LayoutInflater.from(getContext()).inflate(R.layout.dialog_folder_select, null); final View dview = LayoutInflater.from(getContext()).inflate(R.layout.dialog_folder_select, null);
final RecyclerView rvFolder = dview.findViewById(R.id.rvFolder); final RecyclerView rvFolder = dview.findViewById(R.id.rvFolder);
final ContentLoadingProgressBar pbWait = dview.findViewById(R.id.pbWait); final ContentLoadingProgressBar pbWait = dview.findViewById(R.id.pbWait);
@ -1847,10 +1843,10 @@ public class FragmentMessages extends FragmentBase {
LinearLayoutManager llm = new LinearLayoutManager(getContext()); LinearLayoutManager llm = new LinearLayoutManager(getContext());
rvFolder.setLayoutManager(llm); rvFolder.setLayoutManager(llm);
final AdapterFolderSelect adapter = new AdapterFolderSelect(getContext(), getViewLifecycleOwner(), final AdapterFolder adapter = new AdapterFolder(getContext(), getViewLifecycleOwner(), account, false,
new AdapterFolderSelect.IFolderSelectedListener() { new AdapterFolder.IFolderSelectedListener() {
@Override @Override
public void onFolderSelected(EntityFolder folder) { public void onFolderSelected(TupleFolderEx folder) {
dialog.dismiss(); dialog.dismiss();
onActionMoveSelection(folder.id); onActionMoveSelection(folder.id);
} }
@ -3308,7 +3304,7 @@ public class FragmentMessages extends FragmentBase {
Boolean isJunk; Boolean isJunk;
Boolean isDrafts; Boolean isDrafts;
List<EntityAccount> accounts; List<EntityAccount> accounts;
Map<Long, List<EntityFolder>> targets = new HashMap<>(); Map<Long, List<TupleFolderEx>> targets = new HashMap<>();
} }
private static class MessageTarget implements Parcelable { private static class MessageTarget implements Parcelable {

@ -11,6 +11,26 @@
android:background="?attr/activatableItemBackground" android:background="?attr/activatableItemBackground"
android:padding="6dp"> android:padding="6dp">
<View
android:id="@+id/vwLevel"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="@+id/ivExpander"
android:layout_width="36dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical|center_horizontal"
android:contentDescription="@string/title_legend_expander"
android:padding="6dp"
android:src="@drawable/expander"
app:layout_constraintBottom_toBottomOf="@+id/tvName"
app:layout_constraintStart_toEndOf="@+id/vwLevel"
app:layout_constraintTop_toTopOf="@+id/tvName" />
<ImageView <ImageView
android:id="@+id/ivType" android:id="@+id/ivType"
android:layout_width="24dp" android:layout_width="24dp"
@ -18,7 +38,7 @@
android:contentDescription="@string/title_legend_folder_tye" android:contentDescription="@string/title_legend_folder_tye"
android:src="@drawable/baseline_inbox_24" android:src="@drawable/baseline_inbox_24"
app:layout_constraintBottom_toBottomOf="@+id/tvName" app:layout_constraintBottom_toBottomOf="@+id/tvName"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toEndOf="@+id/ivExpander"
app:layout_constraintTop_toTopOf="@+id/tvName" /> app:layout_constraintTop_toTopOf="@+id/tvName" />
<TextView <TextView

Loading…
Cancel
Save