From 0bd53fb52844b57a1037741000129cc59e4f12b0 Mon Sep 17 00:00:00 2001 From: Robert Lin Date: Wed, 6 Sep 2017 07:33:40 -0700 Subject: [PATCH] Fixes #126: Option to Save Selected Tag Filters (#147) * New option in Settings to toggle filter saving * Some English strings updated * Improved code legibility in a few places --- .../screens/list/AppListContract.java | 6 ++ .../screens/list/AppListFragment.java | 16 ++-- .../appstore/screens/list/AppListModule.java | 9 ++- .../screens/list/AppListPresenter.java | 45 +++++++++++- .../screens/list/FilterListAdapter.java | 73 ++++++++++++------- .../screens/settings/SettingsActivity.java | 28 ++++++- app/src/main/res/values/strings.xml | 8 +- app/src/main/res/xml/preferences.xml | 14 +++- 8 files changed, 158 insertions(+), 41 deletions(-) diff --git a/app/src/main/java/subreddit/android/appstore/screens/list/AppListContract.java b/app/src/main/java/subreddit/android/appstore/screens/list/AppListContract.java index 5aaf633..a348abf 100644 --- a/app/src/main/java/subreddit/android/appstore/screens/list/AppListContract.java +++ b/app/src/main/java/subreddit/android/appstore/screens/list/AppListContract.java @@ -1,8 +1,10 @@ package subreddit.android.appstore.screens.list; +import java.util.Collection; import java.util.List; import subreddit.android.appstore.backend.data.AppInfo; +import subreddit.android.appstore.backend.data.AppTags; import subreddit.android.appstore.util.mvp.BasePresenter; import subreddit.android.appstore.util.mvp.BaseView; @@ -17,6 +19,10 @@ interface View extends BaseView { void updateTagCount(TagMap tagMap); void showError(); + + void restoreSelectedTags(Collection appTags); + + Collection getSelectedTags(); } interface Presenter extends BasePresenter { diff --git a/app/src/main/java/subreddit/android/appstore/screens/list/AppListFragment.java b/app/src/main/java/subreddit/android/appstore/screens/list/AppListFragment.java index 118da7d..1413a4e 100644 --- a/app/src/main/java/subreddit/android/appstore/screens/list/AppListFragment.java +++ b/app/src/main/java/subreddit/android/appstore/screens/list/AppListFragment.java @@ -27,6 +27,7 @@ import com.google.gson.Gson; import com.google.gson.GsonBuilder; +import java.util.ArrayList; import java.util.Collection; import java.util.List; @@ -64,7 +65,7 @@ public class AppListFragment extends BasePresenterFragment appTags; + Collection appTags = new ArrayList<>(); private BaseActivity.OnBackKeyPressedListener closeDrawerOnBackKeyListener; @@ -229,10 +230,6 @@ public boolean onItemClick(View view, int position, long itemId) { return true; } - private boolean isTagFilterDrawerOpen() { - return drawerLayout.isDrawerOpen(GravityCompat.END); - } - private void toggleTagFilterDrawer() { if (drawerLayout.isDrawerOpen(GravityCompat.END)) { drawerLayout.closeDrawer(GravityCompat.END); @@ -247,4 +244,13 @@ public void onNewFilterTags(Collection appTagses) { appListAdapter.getFilter().setFilterAppTagses(appTagses); appListAdapter.getFilter().filter(appListAdapter.getFilter().getFilterString()); } + + @Override + public void restoreSelectedTags(Collection appTags) { + filterListAdapter.setSelectedItems(appTags); + } + + public Collection getSelectedTags() { + return appTags; + } } diff --git a/app/src/main/java/subreddit/android/appstore/screens/list/AppListModule.java b/app/src/main/java/subreddit/android/appstore/screens/list/AppListModule.java index 4a156b4..53b22dd 100644 --- a/app/src/main/java/subreddit/android/appstore/screens/list/AppListModule.java +++ b/app/src/main/java/subreddit/android/appstore/screens/list/AppListModule.java @@ -1,5 +1,6 @@ package subreddit.android.appstore.screens.list; +import android.content.SharedPreferences; import android.os.Bundle; import dagger.Module; @@ -26,11 +27,15 @@ public CategoryFilter provideCategories() { @Provides @FragmentScope - public PresenterFactory providePresenterFactory(final WikiRepository wikiRepository, final CategoryFilter categoryFilter) { + public PresenterFactory providePresenterFactory( + final WikiRepository wikiRepository, + final CategoryFilter categoryFilter, + SharedPreferences preferences + ) { return new PresenterFactory() { @Override public AppListContract.Presenter create() { - return new AppListPresenter(wikiRepository, categoryFilter); + return new AppListPresenter(wikiRepository, categoryFilter, preferences); } @Override diff --git a/app/src/main/java/subreddit/android/appstore/screens/list/AppListPresenter.java b/app/src/main/java/subreddit/android/appstore/screens/list/AppListPresenter.java index d458062..fd3dd07 100644 --- a/app/src/main/java/subreddit/android/appstore/screens/list/AppListPresenter.java +++ b/app/src/main/java/subreddit/android/appstore/screens/list/AppListPresenter.java @@ -1,8 +1,10 @@ package subreddit.android.appstore.screens.list; +import android.content.SharedPreferences; import android.os.Bundle; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.List; @@ -16,19 +18,22 @@ import subreddit.android.appstore.backend.data.AppTags; import subreddit.android.appstore.backend.reddit.wiki.WikiRepository; import subreddit.android.appstore.screens.navigation.CategoryFilter; +import subreddit.android.appstore.screens.settings.SettingsActivity; import timber.log.Timber; public class AppListPresenter implements AppListContract.Presenter { final WikiRepository repository; final CategoryFilter categoryFilter; + private SharedPreferences sharedPreferences; private Disposable listUpdater; private Disposable tagUpdater; AppListContract.View view; - public AppListPresenter(WikiRepository repository, CategoryFilter categoryFilter) { + public AppListPresenter(WikiRepository repository, CategoryFilter categoryFilter, SharedPreferences preferences) { this.repository = repository; this.categoryFilter = categoryFilter; + this.sharedPreferences = preferences; } @Override @@ -66,6 +71,11 @@ public void onAttachView(final AppListContract.View view) { .subscribe(appInfos -> { Timber.d("showAppList(%s items)", appInfos.size()); AppListPresenter.this.view.showAppList(appInfos); + + if (saveTagFiltersSelected()) { + AppListPresenter.this.view.restoreSelectedTags(getSavedTagFilters()); + } + }); tagUpdater = filteredData @@ -93,6 +103,9 @@ public TagMap apply(Collection appInfos) throws Exception { @Override public void onDetachView() { + if (saveTagFiltersSelected()) { + saveSelectedTags(AppListPresenter.this.view.getSelectedTags()); + } listUpdater.dispose(); tagUpdater.dispose(); view = null; @@ -114,4 +127,34 @@ public void refreshData() { view.showLoadingScreen(); repository.refresh(); } + + private boolean saveTagFiltersSelected() { + return sharedPreferences.getBoolean(SettingsActivity.PREF_KEY_SAVE_TAG_FILTERS, false); + } + + private Collection getSavedTagFilters() { + List data = Arrays.asList(AppTags.values()); + Collection appTags = new ArrayList<>(); + + for (int i = 0; i < data.size(); i++) { + if (sharedPreferences.getBoolean("savedTags_" + i, false)) { + appTags.add(data.get(i)); + } + } + + return appTags; + } + + public void saveSelectedTags(Collection appTags) { + List data = Arrays.asList(AppTags.values()); + SharedPreferences.Editor editor = sharedPreferences.edit(); + + for (int i = 0; i < data.size(); i++) { + if (appTags.contains(data.get(i))) { + editor.putBoolean("savedTags_" + i, true); + } + } + + editor.commit(); + } } diff --git a/app/src/main/java/subreddit/android/appstore/screens/list/FilterListAdapter.java b/app/src/main/java/subreddit/android/appstore/screens/list/FilterListAdapter.java index f81fd27..398f569 100644 --- a/app/src/main/java/subreddit/android/appstore/screens/list/FilterListAdapter.java +++ b/app/src/main/java/subreddit/android/appstore/screens/list/FilterListAdapter.java @@ -22,43 +22,29 @@ public class FilterListAdapter extends BaseAdapter { final List data = Arrays.asList(AppTags.values()); - final SparseBooleanArray selectedItems = new SparseBooleanArray(AppTags.values().length); + final FilterListener filterListener; + private SparseBooleanArray selectedItems = new SparseBooleanArray(AppTags.values().length);; TagMap tagMap = new TagMap(); interface FilterListener { void onNewFilterTags(Collection appTagses); } - public FilterListAdapter(final FilterListener filterListener) { + public FilterListAdapter(FilterListener filterListener) { + this.filterListener = filterListener; + setItemClickListener((view, position, itemId) -> { - //If selected tag is FREE, make sure paid is removed from selectedItems before it is added + if (data.get(position) == AppTags.FREE) { - //Find 'PAID' in selectedItems and remove it - for (int i = 0; i < selectedItems.size(); i++) { - int key = selectedItems.keyAt(i); - if (data.get(key) == AppTags.PAID) { - selectedItems.delete(key); - notifyDataSetChanged(); - } - } + deselectTag(AppTags.PAID); } else if (data.get(position) == AppTags.PAID) { - //Find 'FREE' in selectedItems and remove it - for (int i = 0; i < selectedItems.size(); i++) { - int key = selectedItems.keyAt(i); - if (data.get(key) == AppTags.FREE) { - selectedItems.delete(key); - notifyDataSetChanged(); - } - } + deselectTag(AppTags.FREE); } + selectedItems.put(position, !selectedItems.get(position)); notifyItemChanged(position); - Collection activeAppTagses = new ArrayList<>(); - for (int i = 0; i < selectedItems.size(); i++) { - int key = selectedItems.keyAt(i); - if (selectedItems.get(key)) activeAppTagses.add(data.get(key)); - } - filterListener.onNewFilterTags(activeAppTagses); + + filterListener.onNewFilterTags(getActiveAppTags()); return false; }); } @@ -88,6 +74,21 @@ public int getItemCount() { return data.size(); } + public void setSelectedItems(Collection appTags) { + boolean changed = false; + for (int i = 0; i < AppTags.values().length; i++) { + if (appTags.contains(data.get(i))) { + selectedItems.put(i, true); + changed = true; + } + } + + if (changed) { + notifyDataSetChanged(); + filterListener.onNewFilterTags(getActiveAppTags()); + } + } + static class ViewHolder extends BaseViewHolder { @BindView(R.id.tagname) TextView tagName; @BindView(R.id.tagcount) TextView tagCount; @@ -104,4 +105,26 @@ public void bind(AppTags item, boolean checked, int tagNumber) { checkBox.setChecked(checked); } } + + private void deselectTag(AppTags tag) { + for (int i = 0; i < selectedItems.size(); i++) { + int key = selectedItems.keyAt(i); + if (data.get(key) == tag) { + selectedItems.delete(key); + notifyDataSetChanged(); + } + } + } + + private Collection getActiveAppTags() { + Collection activeAppTagses = new ArrayList<>(); + + for (int i = 0; i < selectedItems.size(); i++) { + int key = selectedItems.keyAt(i); + if (selectedItems.get(key)) activeAppTagses.add(data.get(key)); + } + + return activeAppTagses; + } + } diff --git a/app/src/main/java/subreddit/android/appstore/screens/settings/SettingsActivity.java b/app/src/main/java/subreddit/android/appstore/screens/settings/SettingsActivity.java index f46ed6c..7acdb7e 100644 --- a/app/src/main/java/subreddit/android/appstore/screens/settings/SettingsActivity.java +++ b/app/src/main/java/subreddit/android/appstore/screens/settings/SettingsActivity.java @@ -1,8 +1,10 @@ package subreddit.android.appstore.screens.settings; import android.content.Intent; +import android.content.SharedPreferences; import android.net.Uri; import android.os.Bundle; +import android.preference.PreferenceManager; import android.support.customtabs.CustomTabsIntent; import android.support.v4.content.ContextCompat; import android.support.v7.app.AlertDialog; @@ -15,10 +17,13 @@ import butterknife.ButterKnife; import subreddit.android.appstore.AppStoreApp; import subreddit.android.appstore.R; +import subreddit.android.appstore.backend.data.AppTags; import subreddit.android.appstore.util.ui.BaseActivity; +import timber.log.Timber; public class SettingsActivity extends BaseActivity implements View.OnClickListener { - public static final String PREF_KEY_LOAD_MEDIA = "core.data.loadmedia"; + public static final String PREF_KEY_LOAD_MEDIA = "core.options.loadmedia"; + public static final String PREF_KEY_SAVE_TAG_FILTERS = "core.options.savetagfilters"; protected static final String SUBMIT_APP_URL = "https://androidflair.github.io/wikiapps/"; @BindView(R.id.settings_toolbar) Toolbar mToolbar; @@ -50,6 +55,7 @@ public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { findPreference("about").setOnPreferenceClickListener(this); findPreference("submitapp").setOnPreferenceClickListener(this); findPreference("theme").setOnPreferenceChangeListener(this); + findPreference("core.options.savetagfilters").setOnPreferenceChangeListener(this); } @Override @@ -59,6 +65,14 @@ public void onViewCreated(View view, Bundle savedInstanceState) { @Override public boolean onPreferenceChange(Preference preference, Object o) { + if (preference.getKey().equals("core.options.savetagfilters")) { + if (!((Boolean) o)) { + deleteSavedTagFilters(); + Timber.d("Save selected tags is now " + o); + } + return true; + } + new AlertDialog.Builder(getActivity()) .setMessage(R.string.restart) .setNegativeButton(R.string.later, null) @@ -84,6 +98,18 @@ else if (preference.getKey().equals("submitapp")) { return true; } + private void deleteSavedTagFilters() { + SharedPreferences prefs = + PreferenceManager.getDefaultSharedPreferences(getContext()); + SharedPreferences.Editor editor = prefs.edit(); + + editor.remove("savedTags_size"); + for(int i = 0; i < AppTags.values().length; i++) { + editor.remove("savedTags_" + i); + } + + editor.commit(); + } } } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 485ee39..8cce21c 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -30,10 +30,12 @@ New View Error fetching repository - Data options + Options Screenshots - - Load app icons and screenshots + + Load app icons and screenshots + Save selected Tag filters + Filter by the same selected Tags every time Update available Error checking for updates Update diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml index 9d3da58..25facf8 100644 --- a/app/src/main/res/xml/preferences.xml +++ b/app/src/main/res/xml/preferences.xml @@ -11,13 +11,19 @@ android:key="theme"/> + android:title="@string/options"> + android:summary="@string/options_loadmedia_summary"/> +