diff --git a/app/src/main/java/com/todoroo/astrid/adapter/FilterAdapter.java b/app/src/main/java/com/todoroo/astrid/adapter/FilterAdapter.java index 3bf4e44d4..b17061d36 100644 --- a/app/src/main/java/com/todoroo/astrid/adapter/FilterAdapter.java +++ b/app/src/main/java/com/todoroo/astrid/adapter/FilterAdapter.java @@ -20,47 +20,37 @@ import androidx.annotation.Nullable; import com.todoroo.astrid.api.Filter; import com.todoroo.astrid.api.FilterListItem; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; -import java.util.Map; import javax.inject.Inject; -import org.tasks.R; import org.tasks.filters.NavigationDrawerSubheader; import org.tasks.locale.Locale; import org.tasks.themes.Theme; +import org.tasks.themes.ThemeAccent; import org.tasks.themes.ThemeCache; public class FilterAdapter extends BaseAdapter { - public static final int REQUEST_SETTINGS = 10123; - public static final int REQUEST_PURCHASE = 10124; - private static final String TOKEN_FILTERS = "token_filters"; private static final String TOKEN_SELECTED = "token_selected"; private static final int VIEW_TYPE_COUNT = FilterListItem.Type.values().length; private final Activity activity; - private final Theme theme; + private final ThemeAccent accent; private final Locale locale; private final LayoutInflater inflater; private final ThemeCache themeCache; - private boolean navigationDrawer; private Filter selected = null; private List items = new ArrayList<>(); - private Map counts = new HashMap<>(); @Inject - public FilterAdapter(Activity activity, Theme theme, ThemeCache themeCache, Locale locale) { + public FilterAdapter( + Activity activity, Theme theme, ThemeCache themeCache, Locale locale) { this.activity = activity; - this.theme = theme; + this.accent = theme.getThemeAccent(); this.locale = locale; this.inflater = theme.getLayoutInflater(activity); this.themeCache = themeCache; } - public void setNavigationDrawer() { - navigationDrawer = true; - } - public void save(Bundle outState) { outState.putParcelableArrayList(TOKEN_FILTERS, getItems()); outState.putParcelable(TOKEN_SELECTED, selected); @@ -71,10 +61,6 @@ public class FilterAdapter extends BaseAdapter { selected = savedInstanceState.getParcelable(TOKEN_SELECTED); } - public void setData(List items) { - setData(items, selected); - } - public void setData(List items, @Nullable Filter selected) { setData(items, selected, -1); } @@ -86,12 +72,6 @@ public class FilterAdapter extends BaseAdapter { notifyDataSetChanged(); } - public void setCounts(Map counts) { - assertMainThread(); - this.counts = counts; - notifyDataSetChanged(); - } - @Override public int getCount() { assertMainThread(); @@ -121,11 +101,12 @@ public class FilterAdapter extends BaseAdapter { FilterViewHolder viewHolder; switch (viewType) { case ITEM: - viewHolder = new FilterViewHolder( - convertView, theme.getThemeAccent(), themeCache, navigationDrawer, locale, activity); + viewHolder = + new FilterViewHolder( + convertView, accent, themeCache, false, locale, activity, null); break; case SEPARATOR: - viewHolder = new FilterViewHolder(); + viewHolder = new FilterViewHolder(convertView); break; case SUBHEADER: viewHolder = new FilterViewHolder(convertView, activity); @@ -138,15 +119,6 @@ public class FilterAdapter extends BaseAdapter { return convertView; } - public Filter getSelected() { - return selected; - } - - public void setSelected(Filter selected) { - this.selected = selected; - notifyDataSetChanged(); - } - public ArrayList getItems() { assertMainThread(); return newArrayList(items); @@ -166,7 +138,7 @@ public class FilterAdapter extends BaseAdapter { FilterViewHolder viewHolder = (FilterViewHolder) convertView.getTag(); switch (item.getItemType()) { case ITEM: - viewHolder.bind(item, item.equals(selected), counts.get(item)); + viewHolder.bind(item, item.equals(selected), 0); break; case SUBHEADER: viewHolder.bind((NavigationDrawerSubheader) item); @@ -192,9 +164,4 @@ public class FilterAdapter extends BaseAdapter { public int getItemViewType(int position) { return getItem(position).getItemType().ordinal(); } - - @Override - public View getDropDownView(int position, View convertView, @NonNull ViewGroup parent) { - return getView(position, convertView, parent); - } } diff --git a/app/src/main/java/com/todoroo/astrid/adapter/FilterViewHolder.java b/app/src/main/java/com/todoroo/astrid/adapter/FilterViewHolder.java index abeb15f02..3963065b6 100644 --- a/app/src/main/java/com/todoroo/astrid/adapter/FilterViewHolder.java +++ b/app/src/main/java/com/todoroo/astrid/adapter/FilterViewHolder.java @@ -16,20 +16,18 @@ import androidx.annotation.Nullable; import androidx.core.content.ContextCompat; import androidx.core.content.res.ResourcesCompat; import androidx.core.graphics.drawable.DrawableCompat; +import androidx.recyclerview.widget.RecyclerView; import butterknife.BindView; import butterknife.ButterKnife; -import com.todoroo.astrid.api.Filter; import com.todoroo.astrid.api.FilterListItem; import org.tasks.R; -import org.tasks.filters.NavigationDrawerAction; import org.tasks.filters.NavigationDrawerSubheader; -import org.tasks.intents.TaskIntents; import org.tasks.locale.Locale; import org.tasks.sync.SynchronizationPreferences; import org.tasks.themes.ThemeAccent; import org.tasks.themes.ThemeCache; -public class FilterViewHolder { +public class FilterViewHolder extends RecyclerView.ViewHolder { @Nullable @BindView(R.id.row) @@ -45,6 +43,7 @@ public class FilterViewHolder { @BindView(R.id.size) TextView size; + private OnClick onClick; private ThemeCache themeCache; private boolean navigationDrawer; private Locale locale; @@ -57,7 +56,10 @@ public class FilterViewHolder { ThemeCache themeCache, boolean navigationDrawer, Locale locale, - Activity activity) { + Activity activity, + OnClick onClick) { + super(itemView); + ButterKnife.bind(this, itemView); this.itemView = itemView; @@ -65,6 +67,7 @@ public class FilterViewHolder { this.navigationDrawer = navigationDrawer; this.locale = locale; this.activity = activity; + this.onClick = onClick; if (navigationDrawer) { text.setCheckMarkDrawable(null); @@ -87,25 +90,23 @@ public class FilterViewHolder { } FilterViewHolder(@NonNull View itemView, Activity activity) { + super(itemView); + ButterKnife.bind(this, itemView); icon.setOnClickListener( v -> activity.startActivity(new Intent(activity, SynchronizationPreferences.class))); } - FilterViewHolder() { + FilterViewHolder(@NonNull View itemView) { + super(itemView); } public void bind(FilterListItem filter, boolean selected, Integer count) { - if (selected) { - if (navigationDrawer) { - itemView.setBackgroundColor(getColor(activity, R.color.drawer_color_selected)); - } else { - text.setChecked(true); - } + if (navigationDrawer) { + itemView.setSelected(selected); } else { - itemView.setBackgroundResource(0); - text.setChecked(false); + text.setChecked(selected); } icon.setImageResource(filter.icon); @@ -123,25 +124,17 @@ public class FilterViewHolder { size.setVisibility(View.VISIBLE); } - row.setOnClickListener( - v -> { - if (filter instanceof Filter) { - if (!selected) { - activity.startActivity(TaskIntents.getTaskListIntent(activity, (Filter) filter)); - } - } else if (filter instanceof NavigationDrawerAction) { - NavigationDrawerAction action = (NavigationDrawerAction) filter; - if (action.requestCode > 0) { - activity.startActivityForResult(action.intent, action.requestCode); - } else { - activity.startActivity(action.intent); - } - } - }); + if (onClick != null) { + row.setOnClickListener(v -> onClick.onClick(filter)); + } } public void bind(NavigationDrawerSubheader filter) { text.setText(filter.listingTitle); icon.setVisibility(filter.error ? View.VISIBLE : View.GONE); } + + public interface OnClick { + void onClick(FilterListItem item); + } } diff --git a/app/src/main/java/com/todoroo/astrid/adapter/NavigationDrawerAdapter.java b/app/src/main/java/com/todoroo/astrid/adapter/NavigationDrawerAdapter.java new file mode 100644 index 000000000..b2dc304fa --- /dev/null +++ b/app/src/main/java/com/todoroo/astrid/adapter/NavigationDrawerAdapter.java @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2012 Todoroo Inc + * + * See the file "LICENSE" for the full license governing this code. + */ + +package com.todoroo.astrid.adapter; + +import static com.google.common.collect.Lists.newArrayList; +import static com.todoroo.andlib.utility.AndroidUtilities.assertMainThread; +import static com.todoroo.astrid.api.FilterListItem.Type.ITEM; +import static com.todoroo.astrid.api.FilterListItem.Type.SUBHEADER; + +import android.app.Activity; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.recyclerview.widget.DiffUtil.ItemCallback; +import androidx.recyclerview.widget.ListAdapter; +import com.todoroo.astrid.adapter.FilterViewHolder.OnClick; +import com.todoroo.astrid.api.Filter; +import com.todoroo.astrid.api.FilterListItem; +import com.todoroo.astrid.api.FilterListItem.Type; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import javax.inject.Inject; +import org.tasks.filters.NavigationDrawerSubheader; +import org.tasks.locale.Locale; +import org.tasks.themes.Theme; +import org.tasks.themes.ThemeAccent; +import org.tasks.themes.ThemeCache; + +public class NavigationDrawerAdapter extends ListAdapter { + + public static final int REQUEST_SETTINGS = 10123; + public static final int REQUEST_PURCHASE = 10124; + + private static final String TOKEN_SELECTED = "token_selected"; + private final Activity activity; + private final ThemeAccent accent; + private final Locale locale; + private final LayoutInflater inflater; + private final ThemeCache themeCache; + private OnClick onClick; + private Filter selected = null; + private Map counts = new HashMap<>(); + private List items; + + @Inject + public NavigationDrawerAdapter( + Activity activity, Theme theme, ThemeCache themeCache, Locale locale) { + super(new DiffCallback()); + this.activity = activity; + this.accent = theme.getThemeAccent(); + this.locale = locale; + this.inflater = theme.getLayoutInflater(activity); + this.themeCache = themeCache; + } + + public void setOnClick(OnClick onClick) { + this.onClick = onClick; + } + + public void save(Bundle outState) { + outState.putParcelable(TOKEN_SELECTED, selected); + } + + public void restore(Bundle savedInstanceState) { + selected = savedInstanceState.getParcelable(TOKEN_SELECTED); + } + + public void setData(List items) { + setData(items, selected); + } + + public void setData(List items, @Nullable Filter selected) { + setData(items, selected, -1); + } + + public void setData(List items, @Nullable Filter selected, int defaultIndex) { + this.items = items; + submitList(items); + + if (selected != null) { + this.selected = selected; + } else if (defaultIndex >= 0) { + this.selected = getFilter(defaultIndex); + } + } + + public void setCounts(Map counts) { + assertMainThread(); + this.counts = counts; + notifyDataSetChanged(); + } + + private Filter getFilter(int position) { + FilterListItem item = getItem(position); + return item instanceof Filter ? (Filter) item : null; + } + + @Override + public long getItemId(int position) { + return position; + } + + public Filter getSelected() { + return selected; + } + + public void setSelected(Filter selected) { + this.selected = selected; + notifyDataSetChanged(); + } + + public List getItems() { + assertMainThread(); + return newArrayList(items); + } + + @NonNull + @Override + public FilterViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + Type type = Type.values()[viewType]; + View view = inflater.inflate(type.layout, parent, false); + if (type == ITEM) { + return new FilterViewHolder( + view, accent, themeCache, true, locale, activity, onClick); + } else if (type == SUBHEADER) { + return new FilterViewHolder(view, activity); + } else { + return new FilterViewHolder(view); + } + } + + @Override + public void onBindViewHolder(@NonNull FilterViewHolder holder, int position) { + FilterListItem item = getItem(position); + Type type = item.getItemType(); + if (type == ITEM) { + holder.bind(item, item.equals(selected), counts.get(item)); + } else if (type == SUBHEADER) { + holder.bind((NavigationDrawerSubheader) item); + } + } + + @Override + public int getItemViewType(int position) { + return getItem(position).getItemType().ordinal(); + } + + @Override + public FilterListItem getItem(int position) { + return super.getItem(position); + } + + private static class DiffCallback extends ItemCallback { + @Override + public boolean areItemsTheSame( + @NonNull FilterListItem oldItem, @NonNull FilterListItem newItem) { + return oldItem.areItemsTheSame(newItem); + } + + @Override + public boolean areContentsTheSame( + @NonNull FilterListItem oldItem, @NonNull FilterListItem newItem) { + return oldItem.areContentsTheSame(newItem); + } + } +} diff --git a/app/src/main/java/com/todoroo/astrid/api/CaldavFilter.java b/app/src/main/java/com/todoroo/astrid/api/CaldavFilter.java index bb2a97548..3ed368868 100644 --- a/app/src/main/java/com/todoroo/astrid/api/CaldavFilter.java +++ b/app/src/main/java/com/todoroo/astrid/api/CaldavFilter.java @@ -1,6 +1,7 @@ package com.todoroo.astrid.api; import android.os.Parcel; +import androidx.annotation.NonNull; import com.todoroo.andlib.sql.Criterion; import com.todoroo.andlib.sql.Field; import com.todoroo.andlib.sql.Join; @@ -94,4 +95,15 @@ public class CaldavFilter extends Filter { public int getMenu() { return R.menu.menu_caldav_list_fragment; } + + @Override + public boolean areItemsTheSame(@NonNull FilterListItem other) { + return other instanceof CaldavFilter + && calendar.getUuid().equals(((CaldavFilter) other).getUuid()); + } + + @Override + public boolean areContentsTheSame(@NonNull FilterListItem other) { + return calendar.equals(((CaldavFilter) other).calendar); + } } diff --git a/app/src/main/java/com/todoroo/astrid/api/CustomFilter.java b/app/src/main/java/com/todoroo/astrid/api/CustomFilter.java index 9aa528a8a..fc06348e9 100644 --- a/app/src/main/java/com/todoroo/astrid/api/CustomFilter.java +++ b/app/src/main/java/com/todoroo/astrid/api/CustomFilter.java @@ -4,7 +4,9 @@ import static com.todoroo.andlib.utility.AndroidUtilities.mapToSerializedString; import android.os.Parcel; import android.os.Parcelable; +import androidx.annotation.NonNull; import java.util.Map; +import org.tasks.Objects; import org.tasks.R; public class CustomFilter extends Filter { @@ -75,4 +77,14 @@ public class CustomFilter extends Filter { public int getMenu() { return getId() > 0 ? R.menu.menu_custom_filter : 0; } + + @Override + public boolean areItemsTheSame(@NonNull FilterListItem other) { + return other instanceof CustomFilter && id == ((CustomFilter) other).id; + } + + @Override + public boolean areContentsTheSame(@NonNull FilterListItem other) { + return super.areContentsTheSame(other) && Objects.equals(criterion, ((CustomFilter) other).criterion); + } } diff --git a/app/src/main/java/com/todoroo/astrid/api/Filter.java b/app/src/main/java/com/todoroo/astrid/api/Filter.java index 03e73e36b..16d4b0122 100644 --- a/app/src/main/java/com/todoroo/astrid/api/Filter.java +++ b/app/src/main/java/com/todoroo/astrid/api/Filter.java @@ -9,10 +9,12 @@ package com.todoroo.astrid.api; import android.os.Parcel; import android.os.Parcelable; import androidx.annotation.MenuRes; +import androidx.annotation.NonNull; import com.todoroo.andlib.sql.QueryTemplate; import java.util.Collections; import java.util.HashMap; import java.util.Map; +import org.tasks.Objects; /** * A FilterListFilter allows users to display tasks that have something in common. @@ -100,10 +102,7 @@ public class Filter extends FilterListItem { } } - /** Utility constructor */ - Filter() { - // do nothing - } + Filter() {} public String getOriginalSqlQuery() { return sqlQuery; @@ -207,4 +206,15 @@ public class Filter extends FilterListItem { + valuesForNewTasks + '}'; } + + @Override + public boolean areItemsTheSame(@NonNull FilterListItem other) { + return other instanceof Filter && Objects.equals(sqlQuery, ((Filter) other).sqlQuery); + } + + @Override + public boolean areContentsTheSame(@NonNull FilterListItem other) { + return super.areContentsTheSame(other) + && Objects.equals(sqlQuery, ((Filter) other).sqlQuery); + } } diff --git a/app/src/main/java/com/todoroo/astrid/api/FilterListItem.java b/app/src/main/java/com/todoroo/astrid/api/FilterListItem.java index 0ce7c8a5c..4bd70e075 100644 --- a/app/src/main/java/com/todoroo/astrid/api/FilterListItem.java +++ b/app/src/main/java/com/todoroo/astrid/api/FilterListItem.java @@ -10,6 +10,8 @@ import android.content.Intent; import android.os.Parcel; import android.os.Parcelable; import androidx.annotation.LayoutRes; +import androidx.annotation.NonNull; +import org.tasks.Objects; import org.tasks.R; /** @@ -53,6 +55,14 @@ public abstract class FilterListItem implements Parcelable { source.createTypedArray(Intent.CREATOR); // old context menu intents } + public abstract boolean areItemsTheSame(@NonNull FilterListItem other); + + public boolean areContentsTheSame(@NonNull FilterListItem other) { + return Objects.equals(listingTitle, other.listingTitle) + && icon == other.icon + && tint == other.tint; + } + @Override public String toString() { return "FilterListItem{" + "listingTitle='" + listingTitle + '\'' + '}'; diff --git a/app/src/main/java/com/todoroo/astrid/api/GtasksFilter.java b/app/src/main/java/com/todoroo/astrid/api/GtasksFilter.java index 3b87ce55b..404ed5807 100644 --- a/app/src/main/java/com/todoroo/astrid/api/GtasksFilter.java +++ b/app/src/main/java/com/todoroo/astrid/api/GtasksFilter.java @@ -2,6 +2,7 @@ package com.todoroo.astrid.api; import android.os.Parcel; import android.os.Parcelable; +import androidx.annotation.NonNull; import com.todoroo.andlib.sql.Criterion; import com.todoroo.andlib.sql.Field; import com.todoroo.andlib.sql.Join; @@ -109,4 +110,15 @@ public class GtasksFilter extends Filter { public int getMenu() { return R.menu.menu_gtasks_list_fragment; } + + @Override + public boolean areItemsTheSame(@NonNull FilterListItem other) { + return other instanceof GtasksFilter + && list.getRemoteId().equals(((GtasksFilter) other).list.getRemoteId()); + } + + @Override + public boolean areContentsTheSame(@NonNull FilterListItem other) { + return list.equals(((GtasksFilter) other).list); + } } diff --git a/app/src/main/java/com/todoroo/astrid/api/TagFilter.java b/app/src/main/java/com/todoroo/astrid/api/TagFilter.java index e5bc29dd1..1386a3207 100644 --- a/app/src/main/java/com/todoroo/astrid/api/TagFilter.java +++ b/app/src/main/java/com/todoroo/astrid/api/TagFilter.java @@ -2,6 +2,7 @@ package com.todoroo.astrid.api; import android.os.Parcel; import android.os.Parcelable; +import androidx.annotation.NonNull; import com.todoroo.andlib.sql.Criterion; import com.todoroo.andlib.sql.Field; import com.todoroo.andlib.sql.Join; @@ -93,4 +94,15 @@ public class TagFilter extends Filter { public int getMenu() { return R.menu.menu_tag_view_fragment; } + + @Override + public boolean areItemsTheSame(@NonNull FilterListItem other) { + return other instanceof TagFilter + && tagData.getRemoteId().equals(((TagFilter) other).getUuid()); + } + + @Override + public boolean areContentsTheSame(@NonNull FilterListItem other) { + return tagData.equals(((TagFilter) other).tagData); + } } diff --git a/app/src/main/java/org/tasks/Objects.java b/app/src/main/java/org/tasks/Objects.java new file mode 100644 index 000000000..042e6c22b --- /dev/null +++ b/app/src/main/java/org/tasks/Objects.java @@ -0,0 +1,9 @@ +package org.tasks; + +public class Objects { + private Objects() {} + + public static boolean equals(Object a, Object b) { + return (a == b) || (a != null && a.equals(b)); + } +} diff --git a/app/src/main/java/org/tasks/filters/FilterProvider.java b/app/src/main/java/org/tasks/filters/FilterProvider.java index cb06b04ab..69ca0a78c 100644 --- a/app/src/main/java/org/tasks/filters/FilterProvider.java +++ b/app/src/main/java/org/tasks/filters/FilterProvider.java @@ -4,8 +4,8 @@ import static com.google.common.base.Strings.isNullOrEmpty; import static com.google.common.collect.Iterables.concat; import static com.google.common.collect.Lists.newArrayList; import static com.todoroo.andlib.utility.AndroidUtilities.assertNotMainThread; -import static com.todoroo.astrid.adapter.FilterAdapter.REQUEST_PURCHASE; -import static com.todoroo.astrid.adapter.FilterAdapter.REQUEST_SETTINGS; +import static com.todoroo.astrid.adapter.NavigationDrawerAdapter.REQUEST_PURCHASE; +import static com.todoroo.astrid.adapter.NavigationDrawerAdapter.REQUEST_SETTINGS; import static org.tasks.caldav.CaldavCalendarSettingsActivity.EXTRA_CALDAV_ACCOUNT; import android.content.Context; diff --git a/app/src/main/java/org/tasks/filters/NavigationDrawerAction.java b/app/src/main/java/org/tasks/filters/NavigationDrawerAction.java index 4da6c233b..41a9fa621 100644 --- a/app/src/main/java/org/tasks/filters/NavigationDrawerAction.java +++ b/app/src/main/java/org/tasks/filters/NavigationDrawerAction.java @@ -3,6 +3,7 @@ package org.tasks.filters; import android.content.Intent; import android.os.Parcel; import android.os.Parcelable; +import androidx.annotation.NonNull; import com.todoroo.astrid.api.FilterListItem; public class NavigationDrawerAction extends FilterListItem { @@ -57,4 +58,10 @@ public class NavigationDrawerAction extends FilterListItem { intent = source.readParcelable(Intent.class.getClassLoader()); requestCode = source.readInt(); } + + @Override + public boolean areItemsTheSame(@NonNull FilterListItem other) { + return other instanceof NavigationDrawerAction + && requestCode == ((NavigationDrawerAction) other).requestCode; + } } diff --git a/app/src/main/java/org/tasks/filters/NavigationDrawerSeparator.java b/app/src/main/java/org/tasks/filters/NavigationDrawerSeparator.java index e736cc06b..473f305dd 100644 --- a/app/src/main/java/org/tasks/filters/NavigationDrawerSeparator.java +++ b/app/src/main/java/org/tasks/filters/NavigationDrawerSeparator.java @@ -2,6 +2,7 @@ package org.tasks.filters; import android.os.Parcel; import android.os.Parcelable; +import androidx.annotation.NonNull; import com.todoroo.astrid.api.FilterListItem; public class NavigationDrawerSeparator extends FilterListItem { @@ -28,4 +29,14 @@ public class NavigationDrawerSeparator extends FilterListItem { public Type getItemType() { return Type.SEPARATOR; } + + @Override + public boolean areItemsTheSame(@NonNull FilterListItem other) { + return other instanceof NavigationDrawerSeparator; + } + + @Override + public boolean areContentsTheSame(@NonNull FilterListItem other) { + return true; + } } diff --git a/app/src/main/java/org/tasks/filters/NavigationDrawerSubheader.java b/app/src/main/java/org/tasks/filters/NavigationDrawerSubheader.java index 5815abfca..20371ac13 100644 --- a/app/src/main/java/org/tasks/filters/NavigationDrawerSubheader.java +++ b/app/src/main/java/org/tasks/filters/NavigationDrawerSubheader.java @@ -2,6 +2,7 @@ package org.tasks.filters; import android.os.Parcel; import android.os.Parcelable; +import androidx.annotation.NonNull; import com.todoroo.astrid.api.FilterListItem; public class NavigationDrawerSubheader extends FilterListItem { @@ -39,6 +40,16 @@ public class NavigationDrawerSubheader extends FilterListItem { error = source.readInt() == 1; } + @Override + public boolean areItemsTheSame(@NonNull FilterListItem other) { + return other instanceof NavigationDrawerSubheader && listingTitle.equals(other.listingTitle); + } + + @Override + public boolean areContentsTheSame(@NonNull FilterListItem other) { + return super.areContentsTheSame(other) && error == ((NavigationDrawerSubheader) other).error; + } + @Override public void writeToParcel(Parcel dest, int flags) { super.writeToParcel(dest, flags); diff --git a/app/src/main/java/org/tasks/ui/NavigationDrawerFragment.java b/app/src/main/java/org/tasks/ui/NavigationDrawerFragment.java index cae78edc8..18737bb63 100644 --- a/app/src/main/java/org/tasks/ui/NavigationDrawerFragment.java +++ b/app/src/main/java/org/tasks/ui/NavigationDrawerFragment.java @@ -13,13 +13,14 @@ import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.ListView; import androidx.annotation.NonNull; import androidx.core.view.GravityCompat; import androidx.drawerlayout.widget.DrawerLayout; import androidx.fragment.app.FragmentActivity; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; import com.todoroo.astrid.activity.MainActivity; -import com.todoroo.astrid.adapter.FilterAdapter; +import com.todoroo.astrid.adapter.NavigationDrawerAdapter; import com.todoroo.astrid.api.Filter; import com.todoroo.astrid.api.FilterListItem; import com.todoroo.astrid.dao.TaskDao; @@ -50,13 +51,13 @@ public class NavigationDrawerFragment extends InjectingFragment { public static final int REQUEST_NEW_CALDAV_COLLECTION = 7; private final RefreshReceiver refreshReceiver = new RefreshReceiver(); @Inject LocalBroadcastManager localBroadcastManager; - @Inject FilterAdapter adapter; + @Inject NavigationDrawerAdapter adapter; @Inject FilterProvider filterProvider; @Inject TaskDao taskDao; /** A pointer to the current callbacks instance (the Activity). */ - private DrawerLayout mDrawerLayout; - private ListView mDrawerListView; + + private RecyclerView recyclerView; private View mFragmentContainerView; private CompositeDisposable disposables; @@ -80,13 +81,13 @@ public class NavigationDrawerFragment extends InjectingFragment { @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { - if (requestCode == FilterAdapter.REQUEST_SETTINGS) { + if (requestCode == NavigationDrawerAdapter.REQUEST_SETTINGS) { if (resultCode == Activity.RESULT_OK && data != null) { if (data.getBooleanExtra(AppearancePreferences.EXTRA_RESTART, false)) { ((MainActivity) getActivity()).restart(); } } - } else if (requestCode == FilterAdapter.REQUEST_PURCHASE) { + } else if (requestCode == NavigationDrawerAdapter.REQUEST_PURCHASE) { if (resultCode == Activity.RESULT_OK) { ((MainActivity) getActivity()).restart(); } @@ -114,33 +115,41 @@ public class NavigationDrawerFragment extends InjectingFragment { @Override public View onCreateView( - LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + @NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View layout = inflater.inflate(R.layout.fragment_navigation_drawer, container, false); + recyclerView = layout.findViewById(R.id.recycler_view); if (atLeastLollipop()) { ((ScrimInsetsFrameLayout) layout.findViewById(R.id.scrim_layout)) - .setOnInsetsCallback(insets -> mDrawerListView.setPadding(0, insets.top, 0, 0)); + .setOnInsetsCallback(insets -> recyclerView.setPadding(0, insets.top, 0, 0)); } - mDrawerListView = layout.findViewById(android.R.id.list); - mDrawerListView.setOnItemClickListener( - (parent, view, position, id) -> { - mDrawerLayout.addDrawerListener( - new DrawerLayout.SimpleDrawerListener() { - @Override - public void onDrawerClosed(View drawerView) { - mDrawerLayout.removeDrawerListener(this); - selectItem(position); - } - }); - close(); - }); - return layout; } private void setUpList() { - adapter.setNavigationDrawer(); - mDrawerListView.setAdapter(adapter); - registerForContextMenu(mDrawerListView); + adapter.setOnClick(this::onFilterItemSelected); + recyclerView.setLayoutManager(new LinearLayoutManager(getContext())); + recyclerView.setAdapter(adapter); + } + + private void onFilterItemSelected(FilterListItem item) { + if (item instanceof Filter) { + mDrawerLayout.addDrawerListener( + new DrawerLayout.SimpleDrawerListener() { + @Override + public void onDrawerClosed(View drawerView) { + mDrawerLayout.removeDrawerListener(this); + openFilter((Filter) item); + } + }); + close(); + } else if (item instanceof NavigationDrawerAction) { + NavigationDrawerAction action = (NavigationDrawerAction) item; + if (action.requestCode > 0) { + startActivityForResult(action.intent, action.requestCode); + } else { + startActivity(action.intent); + } + } } public boolean isDrawerOpen() { @@ -173,22 +182,6 @@ public class NavigationDrawerFragment extends InjectingFragment { disposables.dispose(); } - private void selectItem(int position) { - FilterListItem item = adapter.getItem(position); - if (item instanceof Filter) { - if (!item.equals(adapter.getSelected())) { - openFilter((Filter) item); - } - } else if (item instanceof NavigationDrawerAction) { - NavigationDrawerAction action = (NavigationDrawerAction) item; - if (action.requestCode > 0) { - startActivityForResult(action.intent, action.requestCode); - } else { - startActivity(action.intent); - } - } - } - @Override protected void inject(FragmentComponent component) { component.inject(this); diff --git a/app/src/main/res/drawable/drawer_background.xml b/app/src/main/res/drawable/drawer_background.xml new file mode 100644 index 000000000..d1469b53d --- /dev/null +++ b/app/src/main/res/drawable/drawer_background.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/drawer_background_selected.xml b/app/src/main/res/drawable/drawer_background_selected.xml new file mode 100644 index 000000000..414cb613d --- /dev/null +++ b/app/src/main/res/drawable/drawer_background_selected.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/drawer_background_selector.xml b/app/src/main/res/drawable/drawer_background_selector.xml new file mode 100644 index 000000000..a39e83834 --- /dev/null +++ b/app/src/main/res/drawable/drawer_background_selector.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/filter_adapter_row.xml b/app/src/main/res/layout/filter_adapter_row.xml index c78008e01..a0fa0d00c 100644 --- a/app/src/main/res/layout/filter_adapter_row.xml +++ b/app/src/main/res/layout/filter_adapter_row.xml @@ -2,6 +2,7 @@ diff --git a/app/src/main/res/layout/filter_adapter_subheader.xml b/app/src/main/res/layout/filter_adapter_subheader.xml index e305d7696..5057483f3 100644 --- a/app/src/main/res/layout/filter_adapter_subheader.xml +++ b/app/src/main/res/layout/filter_adapter_subheader.xml @@ -4,6 +4,7 @@ android:layout_width="match_parent" android:layout_height="48dp" android:paddingTop="8dp" + android:background="@drawable/drawer_background_selector" android:orientation="vertical"> -