From e32a8ca486d1bad9d35ad8eeb092bd34a0bf812f Mon Sep 17 00:00:00 2001 From: ByteHamster Date: Sun, 1 Sep 2019 16:09:48 +0200 Subject: [PATCH 1/9] Added icons to ChooseFolder --- .../com/fsck/k9/activity/ChooseFolder.java | 225 ++++++++++++++---- .../res/layout/choose_folder_list_item.xml | 32 +++ 2 files changed, 214 insertions(+), 43 deletions(-) create mode 100644 app/ui/src/main/res/layout/choose_folder_list_item.xml diff --git a/app/ui/src/main/java/com/fsck/k9/activity/ChooseFolder.java b/app/ui/src/main/java/com/fsck/k9/activity/ChooseFolder.java index 2baf85439..35847dcfe 100644 --- a/app/ui/src/main/java/com/fsck/k9/activity/ChooseFolder.java +++ b/app/ui/src/main/java/com/fsck/k9/activity/ChooseFolder.java @@ -5,22 +5,30 @@ import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; +import java.util.Locale; import android.content.Intent; import android.os.Bundle; import android.os.Handler; +import android.text.TextUtils; import android.view.Menu; import android.view.MenuItem; import android.view.View; +import android.view.ViewGroup; import android.view.Window; import android.widget.AdapterView; -import android.widget.ArrayAdapter; +import android.widget.BaseAdapter; import android.widget.Filter; +import android.widget.Filterable; +import android.widget.ImageView; +import android.widget.LinearLayout; import android.widget.ListView; import android.widget.SearchView; +import android.widget.TextView; import com.fsck.k9.Account; import com.fsck.k9.Account.FolderMode; +import com.fsck.k9.K9; import com.fsck.k9.Preferences; import com.fsck.k9.controller.MessageReference; import com.fsck.k9.ui.R; @@ -29,6 +37,8 @@ import com.fsck.k9.controller.MessagingListener; import com.fsck.k9.controller.SimpleMessagingListener; import com.fsck.k9.mail.Folder; import com.fsck.k9.mailstore.LocalFolder; +import com.fsck.k9.ui.folders.FolderIconProvider; +import timber.log.Timber; public class ChooseFolder extends K9ListActivity { @@ -46,7 +56,7 @@ public class ChooseFolder extends K9ListActivity { String mSelectFolder; Account mAccount; MessageReference mMessageReference; - ArrayAdapter mAdapter; + FolderListAdapter mAdapter; private ChooseFolderHandler mHandler = new ChooseFolderHandler(); boolean mHideCurrentFolder = true; boolean mShowDisplayableOnly = false; @@ -95,18 +105,7 @@ public class ChooseFolder extends K9ListActivity { if (currentFolder == null) currentFolder = ""; - mAdapter = new ArrayAdapter(this, android.R.layout.simple_list_item_1) { - private Filter myFilter = null; - - @Override - public Filter getFilter() { - if (myFilter == null) { - myFilter = new FolderListFilter<>(this); - } - return myFilter; - } - }; - + mAdapter = new FolderListAdapter(); setListAdapter(mAdapter); mMode = mAccount.getFolderTargetMode(); @@ -115,7 +114,7 @@ public class ChooseFolder extends K9ListActivity { this.getListView().setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView parent, View view, int position, long id) { - FolderDisplayData folder = mAdapter.getItem(position); + FolderInfoHolder folder = mAdapter.getItem(position); if (folder == null) { throw new AssertionError("Couldn't get item at adapter position " + position); } @@ -264,8 +263,8 @@ public class ChooseFolder extends K9ListActivity { } Account.FolderMode aMode = mMode; - List newFolders = new ArrayList<>(); - List topFolders = new ArrayList<>(); + List newFolders = new ArrayList<>(); + List topFolders = new ArrayList<>(); for (LocalFolder folder : folders) { String serverId = folder.getServerId(); @@ -289,10 +288,7 @@ public class ChooseFolder extends K9ListActivity { continue; } - long id = folder.getDatabaseId(); - String name = folder.getName(); - String displayName = buildDisplayName(account, serverId, name); - FolderDisplayData folderDisplayData = new FolderDisplayData(id, serverId, displayName); + FolderInfoHolder folderDisplayData = new FolderInfoHolder(folder, account); if (folder.isInTopGroup()) { topFolders.add(folderDisplayData); @@ -301,9 +297,9 @@ public class ChooseFolder extends K9ListActivity { } } - final Comparator comparator = new Comparator() { + final Comparator comparator = new Comparator() { @Override - public int compare(FolderDisplayData lhs, FolderDisplayData rhs) { + public int compare(FolderInfoHolder lhs, FolderInfoHolder rhs) { int result = lhs.displayName.compareToIgnoreCase(rhs.displayName); return (result != 0) ? result : lhs.displayName.compareTo(rhs.displayName); } @@ -312,7 +308,7 @@ public class ChooseFolder extends K9ListActivity { Collections.sort(topFolders, comparator); Collections.sort(newFolders, comparator); - final List folderList = new ArrayList<>(newFolders.size() + topFolders.size()); + final List folderList = new ArrayList<>(newFolders.size() + topFolders.size()); folderList.addAll(topFolders); folderList.addAll(newFolders); @@ -325,7 +321,7 @@ public class ChooseFolder extends K9ListActivity { */ try { int position = 0; - for (FolderDisplayData folder : folderList) { + for (FolderInfoHolder folder : folderList) { if (mSelectFolder != null) { /* * Never select EXTRA_CUR_FOLDER (mFolder) if EXTRA_SEL_FOLDER @@ -347,8 +343,9 @@ public class ChooseFolder extends K9ListActivity { @Override public void run() { // Now we're in the UI-thread, we can safely change the contents of the adapter. - mAdapter.clear(); - mAdapter.addAll(folderList); + mAdapter.mFolders.clear(); + mAdapter.mFolders.addAll(folderList); + mAdapter.mFilteredFolders = mAdapter.mFolders; mAdapter.notifyDataSetChanged(); /* @@ -367,29 +364,171 @@ public class ChooseFolder extends K9ListActivity { } }; - private String buildDisplayName(Account account, String serverId, String name) { - if (account.getInboxFolder().equals(serverId)) { - return getString(R.string.special_mailbox_name_inbox); - } else { - return name; + class FolderListAdapter extends BaseAdapter implements Filterable { + private List mFolders = new ArrayList<>(); + private List mFilteredFolders = Collections.unmodifiableList(mFolders); + private Filter mFilter = new FolderListAdapter.FolderListFilter(); + private FolderIconProvider folderIconProvider = new FolderIconProvider(getTheme()); + + public FolderInfoHolder getItem(long position) { + return getItem((int)position); + } + + public FolderInfoHolder getItem(int position) { + return mFilteredFolders.get(position); } - } - static class FolderDisplayData { - final long id; - final String serverId; - final String displayName; + public long getItemId(int position) { + return mFilteredFolders.get(position).folder.getServerId().hashCode() ; + } - FolderDisplayData(long id, String serverId, String displayName) { - this.id = id; - this.serverId = serverId; - this.displayName = displayName; + public int getCount() { + return mFilteredFolders.size(); } @Override - public String toString() { - return displayName; + public boolean isEnabled(int item) { + return true; + } + + @Override + public boolean areAllItemsEnabled() { + return true; + } + + public View getView(int position, View convertView, ViewGroup parent) { + if (position <= getCount()) { + return getItemView(position, convertView, parent); + } else { + Timber.e("getView with illegal position=%d called! count is only %d", position, getCount()); + return null; + } + } + + public View getItemView(int itemPosition, View convertView, ViewGroup parent) { + FolderInfoHolder folder = getItem(itemPosition); + View view; + if (convertView != null) { + view = convertView; + } else { + view = View.inflate(ChooseFolder.this, R.layout.choose_folder_list_item, null); + } + + FolderViewHolder holder = (FolderViewHolder) view.getTag(); + + if (holder == null) { + holder = new FolderViewHolder(); + holder.folderName = view.findViewById(R.id.folder_name); + holder.folderIcon = view.findViewById(R.id.folder_icon); + holder.folderListItemLayout = view.findViewById(R.id.folder_list_item_layout); + + view.setTag(holder); + } + + if (folder == null) { + return view; + } + + holder.folderName.setText(folder.displayName); + holder.folderIcon.setImageResource(folderIconProvider.getFolderIcon(folder.folder.getType())); + + if (K9.isWrapFolderNames()) { + holder.folderName.setEllipsize(null); + holder.folderName.setSingleLine(false); + } + else { + holder.folderName.setEllipsize(TextUtils.TruncateAt.START); + holder.folderName.setSingleLine(true); + } + + return view; + } + + @Override + public boolean hasStableIds() { + return true; + } + + public Filter getFilter() { + return mFilter; + } + + /** + * Filter to search for occurrences of the search-expression in any place of the + * folder-name instead of doing just a prefix-search. + * + * @author Marcus@Wolschon.biz + */ + public class FolderListFilter extends Filter { + private CharSequence mSearchTerm; + + public CharSequence getSearchTerm() { + return mSearchTerm; + } + + /** + * Do the actual search. + * {@inheritDoc} + * + * @see #publishResults(CharSequence, FilterResults) + */ + @Override + protected FilterResults performFiltering(CharSequence searchTerm) { + mSearchTerm = searchTerm; + FilterResults results = new FilterResults(); + + Locale locale = Locale.getDefault(); + if ((searchTerm == null) || (searchTerm.length() == 0)) { + List list = new ArrayList<>(mFolders); + results.values = list; + results.count = list.size(); + } else { + final String searchTermString = searchTerm.toString().toLowerCase(locale); + final String[] words = searchTermString.split(" "); + final int wordCount = words.length; + + final List newValues = new ArrayList<>(); + + for (final FolderInfoHolder value : mFolders) { + if (value.displayName == null) { + continue; + } + final String valueText = value.displayName.toLowerCase(locale); + + for (int k = 0; k < wordCount; k++) { + if (valueText.contains(words[k])) { + newValues.add(value); + break; + } + } + } + + results.values = newValues; + results.count = newValues.size(); + } + + return results; + } + + /** + * Publish the results to the user-interface. + * {@inheritDoc} + */ + @SuppressWarnings("unchecked") + @Override + protected void publishResults(CharSequence constraint, FilterResults results) { + //noinspection unchecked + mFilteredFolders = Collections.unmodifiableList((ArrayList) results.values); + // Send notification that the data set changed now + notifyDataSetChanged(); + } } } + + static class FolderViewHolder { + TextView folderName; + ImageView folderIcon; + LinearLayout folderListItemLayout; + } } diff --git a/app/ui/src/main/res/layout/choose_folder_list_item.xml b/app/ui/src/main/res/layout/choose_folder_list_item.xml new file mode 100644 index 000000000..fe6fe00e9 --- /dev/null +++ b/app/ui/src/main/res/layout/choose_folder_list_item.xml @@ -0,0 +1,32 @@ + + + + + + + + From 6550a5662f8fb68840683bb1785d2a1c1007a887 Mon Sep 17 00:00:00 2001 From: ByteHamster Date: Sun, 1 Sep 2019 19:05:29 +0200 Subject: [PATCH 2/9] Using interface in FolderListFilter --- .../fsck/k9/activity/FolderListFilter.java | 45 +++++++++---------- 1 file changed, 22 insertions(+), 23 deletions(-) diff --git a/app/ui/src/main/java/com/fsck/k9/activity/FolderListFilter.java b/app/ui/src/main/java/com/fsck/k9/activity/FolderListFilter.java index 871985967..554070740 100644 --- a/app/ui/src/main/java/com/fsck/k9/activity/FolderListFilter.java +++ b/app/ui/src/main/java/com/fsck/k9/activity/FolderListFilter.java @@ -5,7 +5,6 @@ import java.util.List; import java.util.Locale; import timber.log.Timber; -import android.widget.ArrayAdapter; import android.widget.Filter; /** @@ -22,7 +21,7 @@ public class FolderListFilter extends Filter { * changes due to the filtering performed by {@link #performFiltering}. * This in turn will change the folders displayed in the ListView. */ - private ArrayAdapter mFolders; + private FilterableAdapter mFolders; /** * All folders. @@ -34,7 +33,7 @@ public class FolderListFilter extends Filter { * * @param folders */ - public FolderListFilter(final ArrayAdapter folders) { + public FolderListFilter(final FilterableAdapter folders) { this.mFolders = folders; } @@ -97,32 +96,32 @@ public class FolderListFilter extends Filter { @SuppressWarnings("unchecked") @Override protected void publishResults(CharSequence constraint, FilterResults results) { - // Don't notify for every change - mFolders.setNotifyOnChange(false); - try { - - //noinspection unchecked - final List folders = (List) results.values; - mFolders.clear(); - if (folders != null) { - for (T folder : folders) { - if (folder != null) { - mFolders.add(folder); - } + //noinspection unchecked + final List folders = (List) results.values; + mFolders.clear(); + if (folders != null) { + for (T folder : folders) { + if (folder != null) { + mFolders.add(folder); } - } else { - Timber.w("FolderListFilter.publishResults - null search-result "); } - - // Send notification that the data set changed now - mFolders.notifyDataSetChanged(); - } finally { - // restore notification status - mFolders.setNotifyOnChange(true); + } else { + Timber.w("FolderListFilter.publishResults - null search-result "); } + + // Send notification that the data set changed now + mFolders.notifyDataSetChanged(); } public void invalidate() { mOriginalValues = null; } + + public interface FilterableAdapter { + void notifyDataSetChanged(); + void clear(); + void add(T object); + int getCount(); + T getItem(int i); + } } From 88edc080b5adb4e0b997c8462791dcc1c74ce33f Mon Sep 17 00:00:00 2001 From: ByteHamster Date: Sun, 1 Sep 2019 19:09:19 +0200 Subject: [PATCH 3/9] Make ChooseFolder use new FolderListFilter --- .../com/fsck/k9/activity/ChooseFolder.java | 117 ++++-------------- 1 file changed, 24 insertions(+), 93 deletions(-) diff --git a/app/ui/src/main/java/com/fsck/k9/activity/ChooseFolder.java b/app/ui/src/main/java/com/fsck/k9/activity/ChooseFolder.java index 35847dcfe..99db93f5c 100644 --- a/app/ui/src/main/java/com/fsck/k9/activity/ChooseFolder.java +++ b/app/ui/src/main/java/com/fsck/k9/activity/ChooseFolder.java @@ -5,7 +5,6 @@ import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; -import java.util.Locale; import android.content.Intent; import android.os.Bundle; @@ -52,14 +51,14 @@ public class ChooseFolder extends K9ListActivity { public static final String RESULT_FOLDER_DISPLAY_NAME = "folderDisplayName"; - String currentFolder; - String mSelectFolder; - Account mAccount; - MessageReference mMessageReference; - FolderListAdapter mAdapter; + private String currentFolder; + private String mSelectFolder; + private Account mAccount; + private MessageReference mMessageReference; + private FolderListAdapter mAdapter; private ChooseFolderHandler mHandler = new ChooseFolderHandler(); - boolean mHideCurrentFolder = true; - boolean mShowDisplayableOnly = false; + private boolean mHideCurrentFolder = true; + private boolean mShowDisplayableOnly = false; /** * What folders to display.
@@ -69,13 +68,6 @@ public class ChooseFolder extends K9ListActivity { */ private Account.FolderMode mMode; - /** - * Current filter used by our ArrayAdapter.
- * Created on the fly and invalidated if a new - * set of folders is chosen via {@link #onOptionsItemSelected(MenuItem)} - */ - private FolderListFilter mMyFilter = null; - @Override public void onCreate(Bundle savedInstanceState) { @@ -224,10 +216,6 @@ public class ChooseFolder extends K9ListActivity { private void setDisplayMode(FolderMode aMode) { mMode = aMode; - // invalidate the current filter as it is working on an inval - if (mMyFilter != null) { - mMyFilter.invalidate(); - } //re-populate the list MessagingController.getInstance(getApplication()).listFolders(mAccount, false, mListener); } @@ -364,25 +352,38 @@ public class ChooseFolder extends K9ListActivity { } }; - class FolderListAdapter extends BaseAdapter implements Filterable { + class FolderListAdapter extends BaseAdapter implements Filterable, + FolderListFilter.FilterableAdapter { private List mFolders = new ArrayList<>(); private List mFilteredFolders = Collections.unmodifiableList(mFolders); - private Filter mFilter = new FolderListAdapter.FolderListFilter(); + private Filter mFilter = new FolderListFilter<>(this); private FolderIconProvider folderIconProvider = new FolderIconProvider(getTheme()); public FolderInfoHolder getItem(long position) { return getItem((int)position); } + @Override public FolderInfoHolder getItem(int position) { return mFilteredFolders.get(position); } - + @Override public long getItemId(int position) { return mFilteredFolders.get(position).folder.getServerId().hashCode() ; } + @Override + public void clear() { + mFolders.clear(); + } + + @Override + public void add(FolderInfoHolder object) { + mFolders.add(object); + } + + @Override public int getCount() { return mFilteredFolders.size(); } @@ -397,6 +398,7 @@ public class ChooseFolder extends K9ListActivity { return true; } + @Override public View getView(int position, View convertView, ViewGroup parent) { if (position <= getCount()) { return getItemView(position, convertView, parent); @@ -453,77 +455,6 @@ public class ChooseFolder extends K9ListActivity { public Filter getFilter() { return mFilter; } - - /** - * Filter to search for occurrences of the search-expression in any place of the - * folder-name instead of doing just a prefix-search. - * - * @author Marcus@Wolschon.biz - */ - public class FolderListFilter extends Filter { - private CharSequence mSearchTerm; - - public CharSequence getSearchTerm() { - return mSearchTerm; - } - - /** - * Do the actual search. - * {@inheritDoc} - * - * @see #publishResults(CharSequence, FilterResults) - */ - @Override - protected FilterResults performFiltering(CharSequence searchTerm) { - mSearchTerm = searchTerm; - FilterResults results = new FilterResults(); - - Locale locale = Locale.getDefault(); - if ((searchTerm == null) || (searchTerm.length() == 0)) { - List list = new ArrayList<>(mFolders); - results.values = list; - results.count = list.size(); - } else { - final String searchTermString = searchTerm.toString().toLowerCase(locale); - final String[] words = searchTermString.split(" "); - final int wordCount = words.length; - - final List newValues = new ArrayList<>(); - - for (final FolderInfoHolder value : mFolders) { - if (value.displayName == null) { - continue; - } - final String valueText = value.displayName.toLowerCase(locale); - - for (int k = 0; k < wordCount; k++) { - if (valueText.contains(words[k])) { - newValues.add(value); - break; - } - } - } - - results.values = newValues; - results.count = newValues.size(); - } - - return results; - } - - /** - * Publish the results to the user-interface. - * {@inheritDoc} - */ - @SuppressWarnings("unchecked") - @Override - protected void publishResults(CharSequence constraint, FilterResults results) { - //noinspection unchecked - mFilteredFolders = Collections.unmodifiableList((ArrayList) results.values); - // Send notification that the data set changed now - notifyDataSetChanged(); - } - } } static class FolderViewHolder { From f2bf8a9fdaf9860d7ac8e4778c770016344ab38d Mon Sep 17 00:00:00 2001 From: cketti Date: Thu, 3 Oct 2019 22:50:42 +0200 Subject: [PATCH 4/9] Port item ID fix from PR #4180 --- app/ui/src/main/java/com/fsck/k9/activity/ChooseFolder.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/ui/src/main/java/com/fsck/k9/activity/ChooseFolder.java b/app/ui/src/main/java/com/fsck/k9/activity/ChooseFolder.java index 99db93f5c..030b4315a 100644 --- a/app/ui/src/main/java/com/fsck/k9/activity/ChooseFolder.java +++ b/app/ui/src/main/java/com/fsck/k9/activity/ChooseFolder.java @@ -370,7 +370,7 @@ public class ChooseFolder extends K9ListActivity { @Override public long getItemId(int position) { - return mFilteredFolders.get(position).folder.getServerId().hashCode() ; + return mFilteredFolders.get(position).folder.getDatabaseId(); } @Override From 80c2d20c9bdf22318284d15eee216e662e6c7548 Mon Sep 17 00:00:00 2001 From: cketti Date: Thu, 3 Oct 2019 22:57:28 +0200 Subject: [PATCH 5/9] Clean up comments in FolderListFilter --- .../fsck/k9/activity/FolderListFilter.java | 39 +------------------ 1 file changed, 1 insertion(+), 38 deletions(-) diff --git a/app/ui/src/main/java/com/fsck/k9/activity/FolderListFilter.java b/app/ui/src/main/java/com/fsck/k9/activity/FolderListFilter.java index 554070740..ca8c139aa 100644 --- a/app/ui/src/main/java/com/fsck/k9/activity/FolderListFilter.java +++ b/app/ui/src/main/java/com/fsck/k9/activity/FolderListFilter.java @@ -8,47 +8,20 @@ import timber.log.Timber; import android.widget.Filter; /** - * Filter to search for occurrences of the search-expression in any place of the - * folder-name instead of doing just a prefix-search. - * - * @author Marcus@Wolschon.biz + * Filter to search for occurrences of the search-expression in any place of the folder name. */ public class FolderListFilter extends Filter { - /** - * ArrayAdapter that contains the list of folders displayed in the - * ListView. - * This object is modified by {@link #publishResults} to reflect the - * changes due to the filtering performed by {@link #performFiltering}. - * This in turn will change the folders displayed in the ListView. - */ private FilterableAdapter mFolders; - - /** - * All folders. - */ private List mOriginalValues = null; - /** - * Create a filter for a list of folders. - * - * @param folders - */ public FolderListFilter(final FilterableAdapter folders) { this.mFolders = folders; } - /** - * Do the actual search. - * {@inheritDoc} - * - * @see #publishResults(CharSequence, FilterResults) - */ @Override protected FilterResults performFiltering(CharSequence searchTerm) { FilterResults results = new FilterResults(); - // Copy the values from mFolders to mOriginalValues if this is the - // first time this method is called. if (mOriginalValues == null) { int count = mFolders.getCount(); mOriginalValues = new ArrayList<>(count); @@ -89,14 +62,9 @@ public class FolderListFilter extends Filter { return results; } - /** - * Publish the results to the user-interface. - * {@inheritDoc} - */ @SuppressWarnings("unchecked") @Override protected void publishResults(CharSequence constraint, FilterResults results) { - //noinspection unchecked final List folders = (List) results.values; mFolders.clear(); if (folders != null) { @@ -109,14 +77,9 @@ public class FolderListFilter extends Filter { Timber.w("FolderListFilter.publishResults - null search-result "); } - // Send notification that the data set changed now mFolders.notifyDataSetChanged(); } - public void invalidate() { - mOriginalValues = null; - } - public interface FilterableAdapter { void notifyDataSetChanged(); void clear(); From 9df97445c2cf492d3a013303a3e56441292410bd Mon Sep 17 00:00:00 2001 From: cketti Date: Thu, 3 Oct 2019 23:01:07 +0200 Subject: [PATCH 6/9] Rename fields in FolderListFilter --- .../fsck/k9/activity/FolderListFilter.java | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/app/ui/src/main/java/com/fsck/k9/activity/FolderListFilter.java b/app/ui/src/main/java/com/fsck/k9/activity/FolderListFilter.java index ca8c139aa..51d88a7c7 100644 --- a/app/ui/src/main/java/com/fsck/k9/activity/FolderListFilter.java +++ b/app/ui/src/main/java/com/fsck/k9/activity/FolderListFilter.java @@ -11,28 +11,28 @@ import android.widget.Filter; * Filter to search for occurrences of the search-expression in any place of the folder name. */ public class FolderListFilter extends Filter { - private FilterableAdapter mFolders; - private List mOriginalValues = null; + private FilterableAdapter adapter; + private List unfilteredFolderList = null; public FolderListFilter(final FilterableAdapter folders) { - this.mFolders = folders; + this.adapter = folders; } @Override protected FilterResults performFiltering(CharSequence searchTerm) { FilterResults results = new FilterResults(); - if (mOriginalValues == null) { - int count = mFolders.getCount(); - mOriginalValues = new ArrayList<>(count); + if (unfilteredFolderList == null) { + int count = adapter.getCount(); + unfilteredFolderList = new ArrayList<>(count); for (int i = 0; i < count; i++) { - mOriginalValues.add(mFolders.getItem(i)); + unfilteredFolderList.add(adapter.getItem(i)); } } Locale locale = Locale.getDefault(); if ((searchTerm == null) || (searchTerm.length() == 0)) { - List list = new ArrayList<>(mOriginalValues); + List list = new ArrayList<>(unfilteredFolderList); results.values = list; results.count = list.size(); } else { @@ -40,7 +40,7 @@ public class FolderListFilter extends Filter { final String[] words = searchTermString.split(" "); final int wordCount = words.length; - final List values = mOriginalValues; + final List values = unfilteredFolderList; final List newValues = new ArrayList<>(); @@ -66,18 +66,18 @@ public class FolderListFilter extends Filter { @Override protected void publishResults(CharSequence constraint, FilterResults results) { final List folders = (List) results.values; - mFolders.clear(); + adapter.clear(); if (folders != null) { for (T folder : folders) { if (folder != null) { - mFolders.add(folder); + adapter.add(folder); } } } else { Timber.w("FolderListFilter.publishResults - null search-result "); } - mFolders.notifyDataSetChanged(); + adapter.notifyDataSetChanged(); } public interface FilterableAdapter { From b7f4ab9a70f1accd74cf9a8342022abb74b93295 Mon Sep 17 00:00:00 2001 From: cketti Date: Thu, 3 Oct 2019 23:11:40 +0200 Subject: [PATCH 7/9] Simplify FolderListFilter --- .../com/fsck/k9/activity/ChooseFolder.java | 27 ++++---- .../fsck/k9/activity/FolderListFilter.java | 66 ++++++------------- 2 files changed, 34 insertions(+), 59 deletions(-) diff --git a/app/ui/src/main/java/com/fsck/k9/activity/ChooseFolder.java b/app/ui/src/main/java/com/fsck/k9/activity/ChooseFolder.java index 030b4315a..081957b3e 100644 --- a/app/ui/src/main/java/com/fsck/k9/activity/ChooseFolder.java +++ b/app/ui/src/main/java/com/fsck/k9/activity/ChooseFolder.java @@ -29,6 +29,7 @@ import com.fsck.k9.Account; import com.fsck.k9.Account.FolderMode; import com.fsck.k9.K9; import com.fsck.k9.Preferences; +import com.fsck.k9.activity.FolderListFilter.FolderAdapter; import com.fsck.k9.controller.MessageReference; import com.fsck.k9.ui.R; import com.fsck.k9.controller.MessagingController; @@ -352,11 +353,10 @@ public class ChooseFolder extends K9ListActivity { } }; - class FolderListAdapter extends BaseAdapter implements Filterable, - FolderListFilter.FilterableAdapter { + class FolderListAdapter extends BaseAdapter implements Filterable, FolderAdapter { private List mFolders = new ArrayList<>(); private List mFilteredFolders = Collections.unmodifiableList(mFolders); - private Filter mFilter = new FolderListFilter<>(this); + private Filter mFilter = new FolderListFilter(this); private FolderIconProvider folderIconProvider = new FolderIconProvider(getTheme()); public FolderInfoHolder getItem(long position) { @@ -373,16 +373,6 @@ public class ChooseFolder extends K9ListActivity { return mFilteredFolders.get(position).folder.getDatabaseId(); } - @Override - public void clear() { - mFolders.clear(); - } - - @Override - public void add(FolderInfoHolder object) { - mFolders.add(object); - } - @Override public int getCount() { return mFilteredFolders.size(); @@ -455,6 +445,17 @@ public class ChooseFolder extends K9ListActivity { public Filter getFilter() { return mFilter; } + + @Override + public List getFolders() { + return mFolders; + } + + @Override + public void setFilteredFolders(List folders) { + mFilteredFolders = new ArrayList<>(folders); + notifyDataSetChanged(); + } } static class FolderViewHolder { diff --git a/app/ui/src/main/java/com/fsck/k9/activity/FolderListFilter.java b/app/ui/src/main/java/com/fsck/k9/activity/FolderListFilter.java index 51d88a7c7..f30612f54 100644 --- a/app/ui/src/main/java/com/fsck/k9/activity/FolderListFilter.java +++ b/app/ui/src/main/java/com/fsck/k9/activity/FolderListFilter.java @@ -4,17 +4,16 @@ import java.util.ArrayList; import java.util.List; import java.util.Locale; -import timber.log.Timber; import android.widget.Filter; /** * Filter to search for occurrences of the search-expression in any place of the folder name. */ -public class FolderListFilter extends Filter { - private FilterableAdapter adapter; - private List unfilteredFolderList = null; +public class FolderListFilter extends Filter { + private final FolderAdapter adapter; - public FolderListFilter(final FilterableAdapter folders) { + + public FolderListFilter(FolderAdapter folders) { this.adapter = folders; } @@ -22,34 +21,22 @@ public class FolderListFilter extends Filter { protected FilterResults performFiltering(CharSequence searchTerm) { FilterResults results = new FilterResults(); - if (unfilteredFolderList == null) { - int count = adapter.getCount(); - unfilteredFolderList = new ArrayList<>(count); - for (int i = 0; i < count; i++) { - unfilteredFolderList.add(adapter.getItem(i)); - } - } - Locale locale = Locale.getDefault(); - if ((searchTerm == null) || (searchTerm.length() == 0)) { - List list = new ArrayList<>(unfilteredFolderList); + if (searchTerm == null || searchTerm.length() == 0) { + List list = new ArrayList<>(adapter.getFolders()); results.values = list; results.count = list.size(); } else { - final String searchTermString = searchTerm.toString().toLowerCase(locale); - final String[] words = searchTermString.split(" "); - final int wordCount = words.length; + String searchTermString = searchTerm.toString().toLowerCase(locale); + String[] words = searchTermString.split(" "); - final List values = unfilteredFolderList; + List newValues = new ArrayList<>(); + for (FolderInfoHolder folderInfoHolder : adapter.getFolders()) { + String valueText = folderInfoHolder.displayName.toLowerCase(locale); - final List newValues = new ArrayList<>(); - - for (final T value : values) { - final String valueText = value.toString().toLowerCase(locale); - - for (int k = 0; k < wordCount; k++) { - if (valueText.contains(words[k])) { - newValues.add(value); + for (String word : words) { + if (valueText.contains(word)) { + newValues.add(folderInfoHolder); break; } } @@ -65,26 +52,13 @@ public class FolderListFilter extends Filter { @SuppressWarnings("unchecked") @Override protected void publishResults(CharSequence constraint, FilterResults results) { - final List folders = (List) results.values; - adapter.clear(); - if (folders != null) { - for (T folder : folders) { - if (folder != null) { - adapter.add(folder); - } - } - } else { - Timber.w("FolderListFilter.publishResults - null search-result "); - } - - adapter.notifyDataSetChanged(); + List folders = (List) results.values; + adapter.setFilteredFolders(folders); } - public interface FilterableAdapter { - void notifyDataSetChanged(); - void clear(); - void add(T object); - int getCount(); - T getItem(int i); + + public interface FolderAdapter { + List getFolders(); + void setFilteredFolders(List folders); } } From 1005f5e300f10c425242c5395dc4d37ab2b2fea0 Mon Sep 17 00:00:00 2001 From: cketti Date: Thu, 3 Oct 2019 23:53:41 +0200 Subject: [PATCH 8/9] Retain filter when updating the folder list --- .../com/fsck/k9/activity/ChooseFolder.java | 23 ++++++++----------- .../fsck/k9/activity/FolderListFilter.java | 4 ++-- 2 files changed, 12 insertions(+), 15 deletions(-) diff --git a/app/ui/src/main/java/com/fsck/k9/activity/ChooseFolder.java b/app/ui/src/main/java/com/fsck/k9/activity/ChooseFolder.java index 081957b3e..c1836d701 100644 --- a/app/ui/src/main/java/com/fsck/k9/activity/ChooseFolder.java +++ b/app/ui/src/main/java/com/fsck/k9/activity/ChooseFolder.java @@ -332,17 +332,7 @@ public class ChooseFolder extends K9ListActivity { @Override public void run() { // Now we're in the UI-thread, we can safely change the contents of the adapter. - mAdapter.mFolders.clear(); - mAdapter.mFolders.addAll(folderList); - mAdapter.mFilteredFolders = mAdapter.mFolders; - mAdapter.notifyDataSetChanged(); - - /* - * Only enable the text filter after the list has been - * populated to avoid possible race conditions because our - * FolderListFilter isn't really thread-safe. - */ - getListView().setTextFilterEnabled(true); + mAdapter.setFolders(folderList); } }); } @@ -358,6 +348,7 @@ public class ChooseFolder extends K9ListActivity { private List mFilteredFolders = Collections.unmodifiableList(mFolders); private Filter mFilter = new FolderListFilter(this); private FolderIconProvider folderIconProvider = new FolderIconProvider(getTheme()); + private CharSequence filterText; public FolderInfoHolder getItem(long position) { return getItem((int)position); @@ -452,10 +443,16 @@ public class ChooseFolder extends K9ListActivity { } @Override - public void setFilteredFolders(List folders) { - mFilteredFolders = new ArrayList<>(folders); + public void setFilteredFolders(CharSequence filterText, List folders) { + this.filterText = filterText; + mFilteredFolders = folders; notifyDataSetChanged(); } + + void setFolders(List folders) { + mFolders = folders; + getFilter().filter(filterText); + } } static class FolderViewHolder { diff --git a/app/ui/src/main/java/com/fsck/k9/activity/FolderListFilter.java b/app/ui/src/main/java/com/fsck/k9/activity/FolderListFilter.java index f30612f54..31ef6907e 100644 --- a/app/ui/src/main/java/com/fsck/k9/activity/FolderListFilter.java +++ b/app/ui/src/main/java/com/fsck/k9/activity/FolderListFilter.java @@ -53,12 +53,12 @@ public class FolderListFilter extends Filter { @Override protected void publishResults(CharSequence constraint, FilterResults results) { List folders = (List) results.values; - adapter.setFilteredFolders(folders); + adapter.setFilteredFolders(constraint, folders); } public interface FolderAdapter { List getFolders(); - void setFilteredFolders(List folders); + void setFilteredFolders(CharSequence filterText, List folders); } } From bc713807cd234763c72842045623cfffdb8d2cc9 Mon Sep 17 00:00:00 2001 From: cketti Date: Fri, 4 Oct 2019 00:10:34 +0200 Subject: [PATCH 9/9] Don't fetch list of folders from adapter in worker thread --- .../java/com/fsck/k9/activity/ChooseFolder.java | 16 +++++++--------- .../com/fsck/k9/activity/FolderListFilter.java | 11 ++++++----- 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/app/ui/src/main/java/com/fsck/k9/activity/ChooseFolder.java b/app/ui/src/main/java/com/fsck/k9/activity/ChooseFolder.java index c1836d701..213989c78 100644 --- a/app/ui/src/main/java/com/fsck/k9/activity/ChooseFolder.java +++ b/app/ui/src/main/java/com/fsck/k9/activity/ChooseFolder.java @@ -40,6 +40,8 @@ import com.fsck.k9.mailstore.LocalFolder; import com.fsck.k9.ui.folders.FolderIconProvider; import timber.log.Timber; +import static java.util.Collections.emptyList; + public class ChooseFolder extends K9ListActivity { public static final String EXTRA_ACCOUNT = "com.fsck.k9.ChooseFolder_account"; @@ -344,9 +346,9 @@ public class ChooseFolder extends K9ListActivity { }; class FolderListAdapter extends BaseAdapter implements Filterable, FolderAdapter { - private List mFolders = new ArrayList<>(); - private List mFilteredFolders = Collections.unmodifiableList(mFolders); - private Filter mFilter = new FolderListFilter(this); + private List mFolders = emptyList(); + private List mFilteredFolders = emptyList(); + private Filter mFilter = new FolderListFilter(this, mFolders); private FolderIconProvider folderIconProvider = new FolderIconProvider(getTheme()); private CharSequence filterText; @@ -437,11 +439,6 @@ public class ChooseFolder extends K9ListActivity { return mFilter; } - @Override - public List getFolders() { - return mFolders; - } - @Override public void setFilteredFolders(CharSequence filterText, List folders) { this.filterText = filterText; @@ -451,7 +448,8 @@ public class ChooseFolder extends K9ListActivity { void setFolders(List folders) { mFolders = folders; - getFilter().filter(filterText); + mFilter = new FolderListFilter(this, folders); + mFilter.filter(filterText); } } diff --git a/app/ui/src/main/java/com/fsck/k9/activity/FolderListFilter.java b/app/ui/src/main/java/com/fsck/k9/activity/FolderListFilter.java index 31ef6907e..e2df35e9c 100644 --- a/app/ui/src/main/java/com/fsck/k9/activity/FolderListFilter.java +++ b/app/ui/src/main/java/com/fsck/k9/activity/FolderListFilter.java @@ -11,10 +11,12 @@ import android.widget.Filter; */ public class FolderListFilter extends Filter { private final FolderAdapter adapter; + private final List folders; - public FolderListFilter(FolderAdapter folders) { - this.adapter = folders; + public FolderListFilter(FolderAdapter adapter, List folders) { + this.adapter = adapter; + this.folders = folders; } @Override @@ -23,7 +25,7 @@ public class FolderListFilter extends Filter { Locale locale = Locale.getDefault(); if (searchTerm == null || searchTerm.length() == 0) { - List list = new ArrayList<>(adapter.getFolders()); + List list = new ArrayList<>(folders); results.values = list; results.count = list.size(); } else { @@ -31,7 +33,7 @@ public class FolderListFilter extends Filter { String[] words = searchTermString.split(" "); List newValues = new ArrayList<>(); - for (FolderInfoHolder folderInfoHolder : adapter.getFolders()) { + for (FolderInfoHolder folderInfoHolder : folders) { String valueText = folderInfoHolder.displayName.toLowerCase(locale); for (String word : words) { @@ -58,7 +60,6 @@ public class FolderListFilter extends Filter { public interface FolderAdapter { - List getFolders(); void setFilteredFolders(CharSequence filterText, List folders); } }