Improved folder collapsing/expanding

This commit is contained in:
M66B 2019-03-18 08:33:40 +00:00
parent afa752328c
commit 3a85a016f8
14 changed files with 1808 additions and 220 deletions

File diff suppressed because it is too large Load Diff

View File

@ -64,24 +64,25 @@ public class AdapterFolder extends RecyclerView.Adapter<AdapterFolder.ViewHolder
private LifecycleOwner owner;
private long account;
private int level;
private EntityFolder parent;
private IProperties properties;
private boolean debug;
private int dp12;
private float textSize;
private int colorUnread;
private int textColorSecondary;
private List<TupleFolderEx> all = new ArrayList<>();
private List<TupleFolderEx> filtered = new ArrayList<>();
private List<Long> collapsed = new ArrayList<>();
private List<TupleFolderEx> items = new ArrayList<>();
private static NumberFormat nf = NumberFormat.getNumberInstance();
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener {
private View view;
private View vwColor;
private ImageView ivExpander;
private View vwLevel;
private ImageView ivState;
private View vwLevel;
private ImageView ivExpander;
private ImageView ivNotify;
private TextView tvName;
private TextView tvMessages;
@ -109,9 +110,9 @@ public class AdapterFolder extends RecyclerView.Adapter<AdapterFolder.ViewHolder
view = itemView.findViewById(R.id.clItem);
vwColor = itemView.findViewById(R.id.vwColor);
ivExpander = itemView.findViewById(R.id.ivExpander);
vwLevel = itemView.findViewById(R.id.vwLevel);
ivState = itemView.findViewById(R.id.ivState);
vwLevel = itemView.findViewById(R.id.vwLevel);
ivExpander = itemView.findViewById(R.id.ivExpander);
ivNotify = itemView.findViewById(R.id.ivNotify);
tvName = itemView.findViewById(R.id.tvName);
tvMessages = itemView.findViewById(R.id.tvMessages);
@ -128,7 +129,7 @@ public class AdapterFolder extends RecyclerView.Adapter<AdapterFolder.ViewHolder
rvChilds.setLayoutManager(llm);
rvChilds.setNestedScrollingEnabled(false);
childs = new AdapterFolder(context, owner);
childs = new AdapterFolder(context, owner, properties);
rvChilds.setAdapter(childs);
}
@ -144,7 +145,7 @@ public class AdapterFolder extends RecyclerView.Adapter<AdapterFolder.ViewHolder
view.setOnLongClickListener(null);
}
private void bindTo(TupleFolderEx folder) {
private void bindTo(final TupleFolderEx folder) {
view.setActivated(folder.tbc != null || folder.tbd != null);
view.setAlpha(folder.hide ? 0.5f : 1.0f);
@ -154,16 +155,6 @@ public class AdapterFolder extends RecyclerView.Adapter<AdapterFolder.ViewHolder
vwColor.setBackgroundColor(folder.accountColor == null ? Color.TRANSPARENT : folder.accountColor);
vwColor.setVisibility(account < 0 ? View.VISIBLE : View.GONE);
ivExpander.setImageResource(collapsed.contains(folder.id)
? R.drawable.baseline_expand_more_24 : R.drawable.baseline_expand_less_24);
ivExpander.setVisibility(folder.childs > 0 ? View.VISIBLE : View.INVISIBLE);
if (account > 0) {
ViewGroup.LayoutParams lp = vwLevel.getLayoutParams();
lp.width = (EntityFolder.USER.equals(folder.type) ? folder.level : 0) * dp12;
vwLevel.setLayoutParams(lp);
}
if (folder.sync_state == null || "requested".equals(folder.sync_state)) {
if ("waiting".equals(folder.state))
ivState.setImageResource(R.drawable.baseline_hourglass_empty_24);
@ -189,14 +180,22 @@ public class AdapterFolder extends RecyclerView.Adapter<AdapterFolder.ViewHolder
folder.synchronize || folder.state != null || folder.sync_state != null
? View.VISIBLE : View.INVISIBLE);
ViewGroup.LayoutParams lp = vwLevel.getLayoutParams();
lp.width = (account < 0 ? 1 : level) * dp12;
vwLevel.setLayoutParams(lp);
ivExpander.setImageResource(folder.collapsed
? R.drawable.baseline_expand_more_24 : R.drawable.baseline_expand_less_24);
ivExpander.setVisibility(account < 0 ? View.GONE : (folder.childs > 0 ? View.VISIBLE : View.INVISIBLE));
ivNotify.setVisibility(folder.notify ? View.VISIBLE : View.GONE);
if (folder.unseen > 0)
tvName.setText(context.getString(R.string.title_name_count,
folder.getDisplayName(context),
folder.getDisplayName(context, parent),
nf.format(folder.unseen)));
else
tvName.setText(folder.getDisplayName(context));
tvName.setText(folder.getDisplayName(context, parent));
tvName.setTypeface(null, folder.unseen > 0 ? Typeface.BOLD : Typeface.NORMAL);
tvName.setTextColor(folder.unseen > 0 ? colorUnread : textColorSecondary);
@ -219,7 +218,7 @@ public class AdapterFolder extends RecyclerView.Adapter<AdapterFolder.ViewHolder
ivMessages.setImageResource(folder.download || EntityFolder.OUTBOX.equals(folder.type)
? R.drawable.baseline_mail_24 : R.drawable.baseline_mail_outline_24);
ivUnified.setVisibility(account > 0 && folder.unified ? View.VISIBLE : View.INVISIBLE);
ivUnified.setVisibility(account > 0 && folder.unified ? View.VISIBLE : View.GONE);
if (account < 0)
tvType.setText(folder.accountName);
@ -255,20 +254,30 @@ public class AdapterFolder extends RecyclerView.Adapter<AdapterFolder.ViewHolder
tvError.setText(folder.error);
tvError.setVisibility(folder.error != null ? View.VISIBLE : View.GONE);
rvChilds.setVisibility(collapsed.contains(folder.id) ? View.GONE : View.VISIBLE);
cowner.restart();
if (folder.childs > 0) {
DB db = DB.getInstance(context);
cowner.start();
db.folder().liveFolders(folder.account, folder.id).observe(cowner, new Observer<List<TupleFolderEx>>() {
@Override
public void onChanged(List<TupleFolderEx> folders) {
childs.set(account, true, folders);
}
});
} else
childs.set(account, true, new ArrayList<TupleFolderEx>());
if (account > 0 && folder.childs > 0) {
if (folder.collapsed) {
rvChilds.setVisibility(View.GONE);
childs.set(account, folder, level + 1, new ArrayList<TupleFolderEx>());
} else {
DB db = DB.getInstance(context);
cowner.start();
rvChilds.setVisibility(View.VISIBLE);
childs.set(folder.account, folder, level + 1, properties.getChilds(folder.id));
db.folder().liveFolders(folder.account, folder.id).observe(cowner, new Observer<List<TupleFolderEx>>() {
@Override
public void onChanged(List<TupleFolderEx> folders) {
if (folders == null)
folders = new ArrayList<>();
properties.setChilds(folder.id, folders);
childs.set(account, folder, level + 1, folders);
}
});
}
} else {
rvChilds.setVisibility(View.GONE);
childs.set(account, null, 0, new ArrayList<TupleFolderEx>());
}
}
@Override
@ -277,24 +286,13 @@ public class AdapterFolder extends RecyclerView.Adapter<AdapterFolder.ViewHolder
if (pos == RecyclerView.NO_POSITION)
return;
TupleFolderEx folder = filtered.get(pos);
TupleFolderEx folder = items.get(pos);
if (folder.tbd != null)
return;
if (view.getId() == R.id.ivExpander) {
if (collapsed.contains(folder.id))
collapsed.remove(folder.id);
else
collapsed.add(folder.id);
boolean expanded = !collapsed.contains(folder.id);
Log.i("Expanded=" + expanded);
ivExpander.setImageResource(collapsed.contains(folder.id)
? R.drawable.baseline_expand_more_24 : R.drawable.baseline_expand_less_24);
rvChilds.setVisibility(collapsed.contains(folder.id) ? View.GONE : View.VISIBLE);
//notifyItemChanged(pos);
} else {
if (view.getId() == R.id.ivExpander)
onCollapse(folder);
else {
LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(context);
lbm.sendBroadcast(
new Intent(ActivityView.ACTION_VIEW_MESSAGES)
@ -303,13 +301,37 @@ public class AdapterFolder extends RecyclerView.Adapter<AdapterFolder.ViewHolder
}
}
private void onCollapse(TupleFolderEx folder) {
Bundle args = new Bundle();
args.putLong("id", folder.id);
args.putBoolean("collapsed", !folder.collapsed);
new SimpleTask<Void>() {
@Override
protected Void onExecute(Context context, Bundle args) {
long id = args.getLong("id");
boolean collapsed = args.getBoolean("collapsed");
DB db = DB.getInstance(context);
db.folder().setFolderCollapsed(id, collapsed);
return null;
}
@Override
protected void onException(Bundle args, Throwable ex) {
Helper.unexpectedError(context, owner, ex);
}
}.execute(context, owner, args, "folder:collapse");
}
@Override
public boolean onLongClick(View v) {
int pos = getAdapterPosition();
if (pos == RecyclerView.NO_POSITION)
return false;
final TupleFolderEx folder = filtered.get(pos);
final TupleFolderEx folder = items.get(pos);
if (folder.tbd != null)
return false;
@ -504,10 +526,11 @@ public class AdapterFolder extends RecyclerView.Adapter<AdapterFolder.ViewHolder
}
}
AdapterFolder(Context context, LifecycleOwner owner) {
AdapterFolder(Context context, LifecycleOwner owner, IProperties properties) {
this.context = context;
this.inflater = LayoutInflater.from(context);
this.owner = owner;
this.properties = properties;
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
boolean compact = prefs.getBoolean("compact", false);
@ -525,14 +548,12 @@ public class AdapterFolder extends RecyclerView.Adapter<AdapterFolder.ViewHolder
setHasStableIds(true);
}
void showHidden(boolean show) {
set(account, show, all);
}
public void set(final long account, boolean showAll, @NonNull List<TupleFolderEx> folders) {
public void set(final long account, EntityFolder parent, int level, @NonNull List<TupleFolderEx> folders) {
Log.i("Set account=" + account + " folders=" + folders.size());
this.account = account;
this.parent = parent;
this.level = level;
final Collator collator = Collator.getInstance(Locale.getDefault());
collator.setStrength(Collator.SECONDARY); // Case insensitive, process accents etc
@ -569,18 +590,9 @@ public class AdapterFolder extends RecyclerView.Adapter<AdapterFolder.ViewHolder
}
});
all.clear();
for (EntityFolder folder : folders)
all.add((TupleFolderEx) folder);
DiffUtil.DiffResult diff = DiffUtil.calculateDiff(new DiffCallback(items, folders), false);
List<TupleFolderEx> shown = new ArrayList<>();
for (EntityFolder folder : folders)
if (!folder.hide || showAll)
shown.add((TupleFolderEx) folder);
DiffUtil.DiffResult diff = DiffUtil.calculateDiff(new DiffCallback(filtered, shown), false);
filtered = shown;
items = folders;
diff.dispatchUpdatesTo(new ListUpdateCallback() {
@Override
@ -642,12 +654,12 @@ public class AdapterFolder extends RecyclerView.Adapter<AdapterFolder.ViewHolder
@Override
public long getItemId(int position) {
return filtered.get(position).id;
return items.get(position).id;
}
@Override
public int getItemCount() {
return filtered.size();
return items.size();
}
@Override
@ -660,9 +672,15 @@ public class AdapterFolder extends RecyclerView.Adapter<AdapterFolder.ViewHolder
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
holder.unwire();
TupleFolderEx folder = filtered.get(position);
TupleFolderEx folder = items.get(position);
holder.bindTo(folder);
holder.wire();
}
interface IProperties {
void setChilds(long parent, List<TupleFolderEx> childs);
List<TupleFolderEx> getChilds(long parent);
}
}

View File

@ -755,7 +755,6 @@ class Core {
if (type != null) {
names.remove(fullName);
int level = EntityFolder.getLevel(separator, fullName);
String display = null;
if (account.prefix != null && fullName.startsWith(account.prefix + separator))
display = fullName.substring(account.prefix.length() + 1);
@ -767,7 +766,6 @@ class Core {
folder.name = fullName;
folder.display = display;
folder.type = (EntityFolder.SYSTEM.equals(type) ? type : EntityFolder.USER);
folder.level = level;
folder.synchronize = false;
folder.poll = ("imap.gmail.com".equals(account.host));
folder.sync_days = EntityFolder.DEFAULT_SYNC;
@ -791,8 +789,6 @@ class Core {
}
}
db.folder().setFolderLevel(folder.id, level);
// Compatibility
if ("Inbox_sub".equals(folder.type))
db.folder().setFolderType(folder.id, EntityFolder.USER);

View File

@ -50,7 +50,7 @@ import io.requery.android.database.sqlite.RequerySQLiteOpenHelperFactory;
// https://developer.android.com/topic/libraries/architecture/room.html
@Database(
version = 60,
version = 61,
entities = {
EntityIdentity.class,
EntityAccount.class,
@ -662,6 +662,13 @@ public abstract class DB extends RoomDatabase {
db.execSQL("ALTER TABLE `folder` ADD COLUMN `parent` INTEGER");
}
})
.addMigrations(new Migration(60, 61) {
@Override
public void migrate(SupportSQLiteDatabase db) {
Log.i("DB migration from version " + startVersion + " to " + endVersion);
db.execSQL("ALTER TABLE `folder` ADD COLUMN `collapsed` INTEGER NOT NULL DEFAULT 0");
}
})
.build();
}

View File

@ -159,12 +159,12 @@ public interface DaoFolder {
@Query("UPDATE folder SET display = :display WHERE id = :id")
int setFolderDisplay(long id, String display);
@Query("UPDATE folder SET level = :level WHERE id = :id")
int setFolderLevel(long id, int level);
@Query("UPDATE folder SET parent = :parent WHERE id = :id")
int setFolderParent(long id, Long parent);
@Query("UPDATE folder SET collapsed = :collapsed WHERE id = :id")
int setFolderCollapsed(long id, boolean collapsed);
@Query("UPDATE folder" +
" SET type = '" + EntityFolder.USER + "'" +
" WHERE account = :account" +

View File

@ -69,7 +69,7 @@ public class EntityFolder implements Serializable {
@NonNull
public String type;
@NonNull
public Integer level;
public Integer level = 0; // obsolete
@NonNull
public Boolean synchronize;
@NonNull
@ -84,6 +84,8 @@ public class EntityFolder implements Serializable {
@NonNull
public Boolean hide = false;
@NonNull
public Boolean collapsed = false;
@NonNull
public Boolean unified = false;
@NonNull
public Boolean notify = false;
@ -200,6 +202,13 @@ public class EntityFolder implements Serializable {
return (display == null ? Helper.localizeFolderName(context, name) : display);
}
String getDisplayName(Context context, EntityFolder parent) {
String n = name;
if (parent != null && name.startsWith(parent.name))
n = n.substring(parent.name.length() + 1);
return (display == null ? Helper.localizeFolderName(context, n) : display);
}
boolean isOutgoing() {
return isOutgoing(this.type);
}
@ -227,19 +236,6 @@ public class EntityFolder implements Serializable {
return USER;
}
static int getLevel(Character separator, String name) {
int level = 0;
if (separator != null) {
for (int i = 0; i < name.length(); i++)
if (name.charAt(i) == separator)
level++;
if (name.startsWith("INBOX" + separator))
level--;
}
return level;
}
String getParentName(Character separator) {
if (separator == null)
return null;
@ -250,7 +246,6 @@ public class EntityFolder implements Serializable {
else
return name.substring(0, p);
}
}
@Override
@ -261,7 +256,6 @@ public class EntityFolder implements Serializable {
Objects.equals(this.account, other.account) &&
this.name.equals(other.name) &&
this.type.equals(other.type) &&
this.level.equals(other.level) &&
this.synchronize.equals(other.synchronize) &&
this.poll.equals(other.poll) &&
this.download.equals(other.download) &&
@ -269,6 +263,7 @@ public class EntityFolder implements Serializable {
this.keep_days.equals(other.keep_days) &&
Objects.equals(this.display, other.display) &&
this.hide == other.hide &&
this.collapsed == other.collapsed &&
this.unified == other.unified &&
this.notify == other.notify &&
Objects.equals(this.total, other.total) &&
@ -292,7 +287,6 @@ public class EntityFolder implements Serializable {
json.put("id", id);
json.put("name", name);
json.put("type", type);
json.put("level", level);
json.put("synchronize", synchronize);
json.put("poll", poll);
json.put("download", download);
@ -300,6 +294,7 @@ public class EntityFolder implements Serializable {
json.put("keep_days", keep_days);
json.put("display", display);
json.put("hide", hide);
json.put("collapsed", collapsed);
json.put("unified", unified);
json.put("notify", notify);
return json;
@ -313,11 +308,6 @@ public class EntityFolder implements Serializable {
folder.name = json.getString("name");
folder.type = json.getString("type");
if (json.has("level"))
folder.level = json.getInt("level");
else
folder.level = 0;
folder.synchronize = json.getBoolean("synchronize");
if (json.has("poll"))
@ -341,6 +331,8 @@ public class EntityFolder implements Serializable {
if (json.has("hide"))
folder.hide = json.getBoolean("hide");
if (json.has("collapsed"))
folder.collapsed = json.getBoolean("collapsed");
folder.unified = json.getBoolean("unified");

View File

@ -1013,7 +1013,6 @@ public class FragmentAccount extends FragmentBase {
db.folder().setFoldersUser(account.id);
for (EntityFolder folder : folders) {
folder.level = EntityFolder.getLevel(separator, folder.name);
if (account.prefix != null && folder.name.startsWith(account.prefix + separator))
folder.display = folder.name.substring(account.prefix.length() + 1);
@ -1025,7 +1024,6 @@ public class FragmentAccount extends FragmentBase {
} else {
EntityLog.log(context, "Updated folder=" + folder.name + " type=" + folder.type);
db.folder().setFolderType(existing.id, folder.type);
db.folder().setFolderLevel(existing.id, folder.level);
}
}

View File

@ -213,7 +213,6 @@ public class FragmentFolder extends FragmentBase {
EntityFolder create = new EntityFolder();
create.account = aid;
create.name = name;
create.level = 0;
create.display = display;
create.hide = hide;
create.type = EntityFolder.USER;

View File

@ -24,6 +24,7 @@ import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Color;
import android.os.Bundle;
import android.util.LongSparseArray;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
@ -35,6 +36,7 @@ import android.widget.ImageButton;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.android.material.snackbar.Snackbar;
import java.util.ArrayList;
import java.util.List;
import androidx.annotation.NonNull;
@ -65,7 +67,7 @@ public class FragmentFolders extends FragmentBase {
private boolean searching = false;
private AdapterFolder adapter;
private Boolean show_hidden = null;
private static LongSparseArray<List<TupleFolderEx>> parentChilds = new LongSparseArray<>();
@Override
public void onCreate(Bundle savedInstanceState) {
@ -128,7 +130,18 @@ public class FragmentFolders extends FragmentBase {
LinearLayoutManager llm = new LinearLayoutManager(getContext());
rvFolder.setLayoutManager(llm);
adapter = new AdapterFolder(getContext(), getViewLifecycleOwner());
adapter = new AdapterFolder(getContext(), getViewLifecycleOwner(), new AdapterFolder.IProperties() {
@Override
public void setChilds(long parent, List<TupleFolderEx> childs) {
parentChilds.put(parent, childs);
}
@Override
public List<TupleFolderEx> getChilds(long parent) {
List<TupleFolderEx> childs = parentChilds.get(parent);
return (childs == null ? new ArrayList<TupleFolderEx>() : childs);
}
});
rvFolder.setAdapter(adapter);
fab.setOnClickListener(new View.OnClickListener() {
@ -188,22 +201,10 @@ public class FragmentFolders extends FragmentBase {
return view;
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
if (show_hidden != null)
outState.putBoolean("fair:show_hidden", show_hidden);
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
if (savedInstanceState != null) {
show_hidden = (Boolean) savedInstanceState.get("fair:show_hidden");
getActivity().invalidateOptionsMenu();
}
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getContext());
grpHintActions.setVisibility(prefs.getBoolean("folder_actions", false) ? View.GONE : View.VISIBLE);
grpHintSync.setVisibility(prefs.getBoolean("folder_sync", false) ? View.GONE : View.VISIBLE);
@ -247,26 +248,7 @@ public class FragmentFolders extends FragmentBase {
return;
}
boolean has_hidden = false;
for (TupleFolderEx folder : folders)
if (folder.hide) {
has_hidden = true;
break;
}
if (has_hidden) {
if (show_hidden == null) {
show_hidden = false;
getActivity().invalidateOptionsMenu();
}
} else {
if (show_hidden != null) {
show_hidden = null;
getActivity().invalidateOptionsMenu();
}
}
adapter.set(account, show_hidden == null || show_hidden, folders);
adapter.set(account, null, 0, folders);
pbWait.setVisibility(View.GONE);
grpReady.setVisibility(View.VISIBLE);
@ -368,38 +350,4 @@ public class FragmentFolders extends FragmentBase {
super.onCreateOptionsMenu(menu, inflater);
}
@Override
public void onPrepareOptionsMenu(Menu menu) {
menu.findItem(R.id.menu_search).setVisible(account < 0);
MenuItem item = menu.findItem(R.id.menu_show_hidden);
if (show_hidden != null) {
item.setTitle(show_hidden ? R.string.title_hide_folders : R.string.title_show_folders);
item.setIcon(show_hidden ? R.drawable.baseline_visibility_off_24 : R.drawable.baseline_visibility_24);
}
item.setVisible(show_hidden != null);
super.onPrepareOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_show_hidden:
onMenuShowHidden();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
private void onMenuShowHidden() {
if (show_hidden == null)
show_hidden = false;
else
show_hidden = !show_hidden;
getActivity().invalidateOptionsMenu();
adapter.showHidden(show_hidden);
}
}

View File

@ -286,7 +286,6 @@ public class FragmentQuickSetup extends FragmentBase {
EntityFolder folder = new EntityFolder();
folder.name = fullName;
folder.type = type;
folder.level = EntityFolder.getLevel(separator, folder.name);
folder.synchronize = (sync >= 0);
folder.download = (sync < 0 ? true : EntityFolder.SYSTEM_FOLDER_DOWNLOAD.get(sync));
folder.sync_days = EntityFolder.DEFAULT_SYNC;

View File

@ -239,7 +239,6 @@ public class FragmentSetup extends FragmentBase {
outbox = new EntityFolder();
outbox.name = "OUTBOX";
outbox.type = EntityFolder.OUTBOX;
outbox.level = 0;
outbox.synchronize = false;
outbox.sync_days = 0;
outbox.keep_days = 0;

View File

@ -20,41 +20,16 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="@+id/ivExpander"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_gravity="center_vertical|center_horizontal"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:paddingStart="6dp"
android:paddingEnd="6dp"
android:src="@drawable/baseline_expand_less_24"
android:visibility="visible"
app:layout_constraintBottom_toTopOf="@+id/vSeparator"
app:layout_constraintStart_toEndOf="@+id/vwColor"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="@+id/ivState"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_marginStart="12dp"
android:layout_marginEnd="6dp"
android:layout_marginStart="6dp"
android:src="@drawable/baseline_cloud_off_24"
app:layout_constraintBottom_toBottomOf="@+id/tvName"
app:layout_constraintStart_toEndOf="@id/ivExpander"
app:layout_constraintStart_toEndOf="@id/vwColor"
app:layout_constraintTop_toTopOf="@+id/tvName" />
<ImageView
android:id="@+id/ivUnified"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_marginStart="12dp"
android:src="@drawable/baseline_folder_special_24"
app:layout_constraintBottom_toBottomOf="@+id/tvType"
app:layout_constraintStart_toEndOf="@id/ivExpander"
app:layout_constraintTop_toTopOf="@+id/tvType" />
<View
android:id="@+id/vwLevel"
android:layout_width="0dp"
@ -64,20 +39,42 @@
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="@+id/ivNotify"
android:layout_width="24dp"
android:id="@+id/ivExpander"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_gravity="center_vertical|center_horizontal"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:paddingStart="12dp"
android:paddingEnd="12dp"
android:src="@drawable/baseline_expand_less_24"
app:layout_constraintBottom_toTopOf="@+id/vSeparator"
app:layout_constraintStart_toEndOf="@+id/vwLevel"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="@+id/ivUnified"
android:layout_width="30dp"
android:layout_height="24dp"
android:layout_marginStart="6dp"
android:paddingEnd="6dp"
android:src="@drawable/baseline_folder_special_24"
app:layout_constraintBottom_toBottomOf="@+id/tvType"
app:layout_constraintStart_toEndOf="@id/ivExpander"
app:layout_constraintTop_toTopOf="@+id/tvType" />
<ImageView
android:id="@+id/ivNotify"
android:layout_width="30dp"
android:layout_height="24dp"
android:paddingEnd="6dp"
android:src="@drawable/baseline_notifications_24"
app:layout_constraintBottom_toBottomOf="@+id/tvName"
app:layout_constraintStart_toEndOf="@id/vwLevel"
app:layout_constraintStart_toEndOf="@id/ivExpander"
app:layout_constraintTop_toTopOf="@+id/tvName" />
<TextView
android:id="@+id/tvName"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="6dp"
android:layout_marginTop="6dp"
android:layout_marginEnd="6dp"
android:ellipsize="end"
@ -116,7 +113,6 @@
android:id="@+id/tvType"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="6dp"
android:layout_marginTop="6dp"
android:layout_marginEnd="6dp"
android:gravity="center_vertical"
@ -125,7 +121,7 @@
android:textAppearance="@android:style/TextAppearance.Small"
android:textStyle="italic"
app:layout_constraintEnd_toStartOf="@+id/tvAfter"
app:layout_constraintStart_toEndOf="@id/vwLevel"
app:layout_constraintStart_toEndOf="@id/ivUnified"
app:layout_constraintTop_toBottomOf="@id/tvName" />
<TextView
@ -154,21 +150,19 @@
android:id="@+id/tvKeywords"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="6dp"
android:layout_marginTop="6dp"
android:layout_marginEnd="12dp"
android:gravity="center_vertical"
android:text="Keywords"
android:textAppearance="@android:style/TextAppearance.Small"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/vwLevel"
app:layout_constraintStart_toEndOf="@id/ivExpander"
app:layout_constraintTop_toBottomOf="@id/tvType" />
<TextView
android:id="@+id/tvError"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:layout_marginTop="6dp"
android:layout_marginEnd="12dp"
android:text="error"

View File

@ -8,10 +8,4 @@
android:title="@string/title_search"
app:actionViewClass="androidx.appcompat.widget.SearchView"
app:showAsAction="collapseActionView|always" />
<item
android:id="@+id/menu_show_hidden"
android:icon="@drawable/baseline_visibility_24"
android:title="@string/title_show_folders"
app:showAsAction="always" />
</menu>

View File

@ -289,9 +289,7 @@
<string name="title_folder_name">Folder name</string>
<string name="title_display_name">Display name</string>
<string name="title_hide_folders">Hide hidden folders</string>
<string name="title_show_folders">Show hidden folders</string>
<string name="title_hide_folder">Hide from list</string>
<string name="title_hide_folder">Hide from menus</string>
<string name="title_unified_folder">Show in unified inbox</string>
<string name="title_synchronize_folder">Synchronize (receive messages)</string>
<string name="title_poll_folder">Check periodically instead of continuous synchronize</string>