From b1be1dffb6c8fb4db7849bdb757c2c8dd4d9ee1e Mon Sep 17 00:00:00 2001 From: Peter Serwylo Date: Wed, 25 Nov 2015 22:54:01 +1100 Subject: [PATCH 01/11] Initial move of search logic to FDroid activity from SearchActivity --- F-Droid/AndroidManifest.xml | 29 ++++------- F-Droid/src/org/fdroid/fdroid/FDroid.java | 31 +++++++++-- .../org/fdroid/fdroid/compat/TabManager.java | 4 ++ .../org/fdroid/fdroid/data/AppProvider.java | 52 +++++++++++++++---- .../views/AppListFragmentPagerAdapter.java | 33 ++++++++++-- .../views/fragments/AppListFragment.java | 15 +++++- .../fragments/AvailableAppsFragment.java | 4 ++ .../fragments/CanUpdateAppsFragment.java | 4 ++ .../fragments/InstalledAppsFragment.java | 4 ++ 9 files changed, 138 insertions(+), 38 deletions(-) diff --git a/F-Droid/AndroidManifest.xml b/F-Droid/AndroidManifest.xml index 6deda93e0..0f1036114 100644 --- a/F-Droid/AndroidManifest.xml +++ b/F-Droid/AndroidManifest.xml @@ -100,7 +100,7 @@ + android:value=".FDroid" /> + + + + + + @@ -388,25 +396,6 @@ - - - - - - - - - diff --git a/F-Droid/src/org/fdroid/fdroid/FDroid.java b/F-Droid/src/org/fdroid/fdroid/FDroid.java index d5eda5c4b..b5750a1e6 100644 --- a/F-Droid/src/org/fdroid/fdroid/FDroid.java +++ b/F-Droid/src/org/fdroid/fdroid/FDroid.java @@ -29,10 +29,13 @@ import android.content.res.Configuration; import android.database.ContentObserver; import android.net.Uri; import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.v4.content.LocalBroadcastManager; import android.support.v4.view.MenuItemCompat; import android.support.v4.view.ViewPager; -import android.support.v7.app.ActionBarActivity; import android.support.v7.app.AlertDialog; +import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.SearchView; import android.text.TextUtils; import android.view.LayoutInflater; @@ -48,9 +51,10 @@ import org.fdroid.fdroid.data.NewRepoConfig; import org.fdroid.fdroid.privileged.install.InstallExtensionDialogActivity; import org.fdroid.fdroid.views.AppListFragmentPagerAdapter; import org.fdroid.fdroid.views.ManageReposActivity; +import org.fdroid.fdroid.views.fragments.AppListFragment; import org.fdroid.fdroid.views.swap.SwapWorkflowActivity; -public class FDroid extends ActionBarActivity { +public class FDroid extends AppCompatActivity implements SearchView.OnQueryTextListener { private static final String TAG = "FDroid"; @@ -66,8 +70,11 @@ public class FDroid extends ActionBarActivity { private ViewPager viewPager; + @Nullable private TabManager tabManager; + private AppListFragmentPagerAdapter adapter; + @Override protected void onCreate(Bundle savedInstanceState) { @@ -248,6 +255,7 @@ public class FDroid extends ActionBarActivity { searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName())); // LayoutParams.MATCH_PARENT does not work, use a big value instead searchView.setMaxWidth(1000000); + searchView.setOnQueryTextListener(this); return super.onCreateOptionsMenu(menu); } @@ -335,8 +343,8 @@ public class FDroid extends ActionBarActivity { private void createViews() { viewPager = (ViewPager) findViewById(R.id.main_pager); - AppListFragmentPagerAdapter viewPagerAdapter = new AppListFragmentPagerAdapter(this); - viewPager.setAdapter(viewPagerAdapter); + this.adapter = new AppListFragmentPagerAdapter(this); + viewPager.setAdapter(this.adapter); viewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() { @Override public void onPageSelected(int position) { @@ -345,6 +353,7 @@ public class FDroid extends ActionBarActivity { }); } + @NonNull private TabManager getTabManager() { if (tabManager == null) { tabManager = new TabManager(this, viewPager); @@ -363,6 +372,20 @@ public class FDroid extends ActionBarActivity { nMgr.cancel(id); } + @Override + public boolean onQueryTextSubmit(String query) { + return false; + } + + private static final String SEARCH_CHANGED = "fdroid.SearchChanged"; + private static final String SEARCH_QUERY = "fdroid.SearchQuery"; + + @Override + public boolean onQueryTextChange(String newText) { + this.adapter.updateSearchQuery(newText, getTabManager().getSelectedIndex()); + return true; + } + private class AppObserver extends ContentObserver { AppObserver() { diff --git a/F-Droid/src/org/fdroid/fdroid/compat/TabManager.java b/F-Droid/src/org/fdroid/fdroid/compat/TabManager.java index 524f1a2ad..17a65f4d4 100644 --- a/F-Droid/src/org/fdroid/fdroid/compat/TabManager.java +++ b/F-Droid/src/org/fdroid/fdroid/compat/TabManager.java @@ -35,6 +35,10 @@ public class TabManager { this.pager = pager; } + public int getSelectedIndex() { + return actionBar != null ? actionBar.getSelectedNavigationIndex() : -1; + } + protected CharSequence getLabel(int index) { return pager.getAdapter().getPageTitle(index); } diff --git a/F-Droid/src/org/fdroid/fdroid/data/AppProvider.java b/F-Droid/src/org/fdroid/fdroid/data/AppProvider.java index 79019be56..cc265132b 100644 --- a/F-Droid/src/org/fdroid/fdroid/data/AppProvider.java +++ b/F-Droid/src/org/fdroid/fdroid/data/AppProvider.java @@ -425,6 +425,8 @@ public class AppProvider extends FDroidProvider { private static final String PATH_INSTALLED = "installed"; private static final String PATH_CAN_UPDATE = "canUpdate"; private static final String PATH_SEARCH = "search"; + private static final String PATH_SEARCH_INSTALLED = "seasrchInstalled"; + private static final String PATH_SEARCH_CAN_UPDATE = "searchCanUpdate"; private static final String PATH_SEARCH_REPO = "searchRepo"; private static final String PATH_NO_APKS = "noApks"; private static final String PATH_APPS = "apps"; @@ -435,18 +437,20 @@ public class AppProvider extends FDroidProvider { private static final String PATH_CALC_APP_DETAILS_FROM_INDEX = "calcDetailsFromIndex"; private static final String PATH_REPO = "repo"; - private static final int CAN_UPDATE = CODE_SINGLE + 1; - private static final int INSTALLED = CAN_UPDATE + 1; - private static final int SEARCH = INSTALLED + 1; - private static final int NO_APKS = SEARCH + 1; - private static final int APPS = NO_APKS + 1; + private static final int CAN_UPDATE = CODE_SINGLE + 1; + private static final int INSTALLED = CAN_UPDATE + 1; + private static final int SEARCH = INSTALLED + 1; + private static final int NO_APKS = SEARCH + 1; + private static final int APPS = NO_APKS + 1; private static final int RECENTLY_UPDATED = APPS + 1; - private static final int NEWLY_ADDED = RECENTLY_UPDATED + 1; - private static final int CATEGORY = NEWLY_ADDED + 1; - private static final int IGNORED = CATEGORY + 1; + private static final int NEWLY_ADDED = RECENTLY_UPDATED + 1; + private static final int CATEGORY = NEWLY_ADDED + 1; + private static final int IGNORED = CATEGORY + 1; private static final int CALC_APP_DETAILS_FROM_INDEX = IGNORED + 1; - private static final int REPO = CALC_APP_DETAILS_FROM_INDEX + 1; - private static final int SEARCH_REPO = REPO + 1; + private static final int REPO = CALC_APP_DETAILS_FROM_INDEX + 1; + private static final int SEARCH_REPO = REPO + 1; + private static final int SEARCH_INSTALLED = SEARCH_REPO + 1; + private static final int SEARCH_CAN_UPDATE = SEARCH_INSTALLED + 1; static { matcher.addURI(getAuthority(), null, CODE_LIST); @@ -456,6 +460,8 @@ public class AppProvider extends FDroidProvider { matcher.addURI(getAuthority(), PATH_NEWLY_ADDED, NEWLY_ADDED); matcher.addURI(getAuthority(), PATH_CATEGORY + "/*", CATEGORY); matcher.addURI(getAuthority(), PATH_SEARCH + "/*", SEARCH); + matcher.addURI(getAuthority(), PATH_SEARCH_INSTALLED + "/*", SEARCH_INSTALLED); + matcher.addURI(getAuthority(), PATH_SEARCH_CAN_UPDATE + "/*", SEARCH_CAN_UPDATE); matcher.addURI(getAuthority(), PATH_SEARCH_REPO + "/*/*", SEARCH_REPO); matcher.addURI(getAuthority(), PATH_REPO + "/#", REPO); matcher.addURI(getAuthority(), PATH_CAN_UPDATE, CAN_UPDATE); @@ -540,6 +546,22 @@ public class AppProvider extends FDroidProvider { .build(); } + public static Uri getSearchInstalledUri(String query) { + return getContentUri() + .buildUpon() + .appendPath(PATH_SEARCH_INSTALLED) + .appendPath(query) + .build(); + } + + public static Uri getSearchCanUpdateUri(String query) { + return getContentUri() + .buildUpon() + .appendPath(PATH_SEARCH_CAN_UPDATE) + .appendPath(query) + .build(); + } + public static Uri getSearchUri(Repo repo, String query) { return getContentUri().buildUpon() .appendPath(PATH_SEARCH_REPO) @@ -735,6 +757,16 @@ public class AppProvider extends FDroidProvider { includeSwap = false; break; + case SEARCH_INSTALLED: + selection = querySearch(uri.getLastPathSegment()).add(queryInstalled()); + includeSwap = false; + break; + + case SEARCH_CAN_UPDATE: + selection = querySearch(uri.getLastPathSegment()).add(queryCanUpdate()); + includeSwap = false; + break; + case SEARCH_REPO: selection = selection.add(querySearch(uri.getPathSegments().get(2))); selection = selection.add(queryRepo(Long.parseLong(uri.getPathSegments().get(1)))); diff --git a/F-Droid/src/org/fdroid/fdroid/views/AppListFragmentPagerAdapter.java b/F-Droid/src/org/fdroid/fdroid/views/AppListFragmentPagerAdapter.java index 43ac7b81f..f0c48be64 100644 --- a/F-Droid/src/org/fdroid/fdroid/views/AppListFragmentPagerAdapter.java +++ b/F-Droid/src/org/fdroid/fdroid/views/AppListFragmentPagerAdapter.java @@ -1,5 +1,7 @@ package org.fdroid.fdroid.views; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentPagerAdapter; @@ -7,6 +9,7 @@ import org.fdroid.fdroid.FDroid; import org.fdroid.fdroid.R; import org.fdroid.fdroid.compat.TabManager; import org.fdroid.fdroid.data.AppProvider; +import org.fdroid.fdroid.views.fragments.AppListFragment; import org.fdroid.fdroid.views.fragments.AvailableAppsFragment; import org.fdroid.fdroid.views.fragments.CanUpdateAppsFragment; import org.fdroid.fdroid.views.fragments.InstalledAppsFragment; @@ -17,11 +20,28 @@ import org.fdroid.fdroid.views.fragments.InstalledAppsFragment; */ public class AppListFragmentPagerAdapter extends FragmentPagerAdapter { + @NonNull private final FDroid parent; + @NonNull + private final AppListFragment availableFragment; + + @NonNull + private final AppListFragment installedFragment; + + @NonNull + private final AppListFragment canUpdateFragment; + + @Nullable + private String searchQuery; + public AppListFragmentPagerAdapter(FDroid parent) { super(parent.getSupportFragmentManager()); this.parent = parent; + + availableFragment = new AvailableAppsFragment(); + installedFragment = new InstalledAppsFragment(); + canUpdateFragment = new CanUpdateAppsFragment(); } private String getInstalledTabTitle() { @@ -34,15 +54,22 @@ public class AppListFragmentPagerAdapter extends FragmentPagerAdapter { return parent.getString(R.string.tab_updates_count, updateCount); } + public void updateSearchQuery(@Nullable String query, int tabIndex) { + searchQuery = query; + availableFragment.updateSearchQuery(query); + installedFragment.updateSearchQuery(query); + canUpdateFragment.updateSearchQuery(query); + } + @Override public Fragment getItem(int i) { switch (i) { case TabManager.INDEX_AVAILABLE: - return new AvailableAppsFragment(); + return availableFragment; case TabManager.INDEX_INSTALLED: - return new InstalledAppsFragment(); + return installedFragment; default: - return new CanUpdateAppsFragment(); + return canUpdateFragment; } } diff --git a/F-Droid/src/org/fdroid/fdroid/views/fragments/AppListFragment.java b/F-Droid/src/org/fdroid/fdroid/views/fragments/AppListFragment.java index 401c14120..985e4e5e9 100644 --- a/F-Droid/src/org/fdroid/fdroid/views/fragments/AppListFragment.java +++ b/F-Droid/src/org/fdroid/fdroid/views/fragments/AppListFragment.java @@ -6,10 +6,12 @@ import android.content.SharedPreferences; import android.database.Cursor; import android.net.Uri; import android.os.Bundle; +import android.support.annotation.Nullable; import android.support.v4.app.ListFragment; import android.support.v4.app.LoaderManager; import android.support.v4.content.CursorLoader; import android.support.v4.content.Loader; +import android.text.TextUtils; import android.view.View; import android.widget.AdapterView; @@ -52,12 +54,17 @@ public abstract class AppListFragment extends ListFragment implements protected AppListAdapter appAdapter; + @Nullable + private String searchQuery; + protected abstract AppListAdapter getAppListAdapter(); protected abstract String getFromTitle(); protected abstract Uri getDataUri(); + protected abstract Uri getDataUri(String query); + @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); @@ -144,9 +151,15 @@ public abstract class AppListFragment extends ListFragment implements @Override public Loader onCreateLoader(int id, Bundle args) { - Uri uri = getDataUri(); + Uri uri = TextUtils.isEmpty(searchQuery) ? getDataUri() : getDataUri(searchQuery); return new CursorLoader( getActivity(), uri, APP_PROJECTION, null, null, APP_SORT); } + public void updateSearchQuery(@Nullable String query) { + this.searchQuery = query; + if (isAdded()) { + getLoaderManager().restartLoader(0, null, this); + } + } } diff --git a/F-Droid/src/org/fdroid/fdroid/views/fragments/AvailableAppsFragment.java b/F-Droid/src/org/fdroid/fdroid/views/fragments/AvailableAppsFragment.java index ffb14c4e2..9805f7973 100644 --- a/F-Droid/src/org/fdroid/fdroid/views/fragments/AvailableAppsFragment.java +++ b/F-Droid/src/org/fdroid/fdroid/views/fragments/AvailableAppsFragment.java @@ -164,6 +164,10 @@ public class AvailableAppsFragment extends AppListFragment implements return AppProvider.getCategoryUri(currentCategory); } + protected Uri getDataUri(String query) { + return AppProvider.getSearchUri(query); + } + private void setCurrentCategory(String category) { currentCategory = category; Utils.debugLog(TAG, "Category '" + currentCategory + "' selected."); diff --git a/F-Droid/src/org/fdroid/fdroid/views/fragments/CanUpdateAppsFragment.java b/F-Droid/src/org/fdroid/fdroid/views/fragments/CanUpdateAppsFragment.java index e767077b9..8b5954609 100644 --- a/F-Droid/src/org/fdroid/fdroid/views/fragments/CanUpdateAppsFragment.java +++ b/F-Droid/src/org/fdroid/fdroid/views/fragments/CanUpdateAppsFragment.java @@ -28,6 +28,10 @@ public class CanUpdateAppsFragment extends AppListFragment { return AppProvider.getCanUpdateUri(); } + protected Uri getDataUri(String query) { + return AppProvider.getSearchCanUpdateUri(query); + } + @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return inflater.inflate(R.layout.can_update_app_list, container, false); diff --git a/F-Droid/src/org/fdroid/fdroid/views/fragments/InstalledAppsFragment.java b/F-Droid/src/org/fdroid/fdroid/views/fragments/InstalledAppsFragment.java index d5078b80f..7f7a77c01 100644 --- a/F-Droid/src/org/fdroid/fdroid/views/fragments/InstalledAppsFragment.java +++ b/F-Droid/src/org/fdroid/fdroid/views/fragments/InstalledAppsFragment.java @@ -28,6 +28,10 @@ public class InstalledAppsFragment extends AppListFragment { return AppProvider.getInstalledUri(); } + protected Uri getDataUri(String query) { + return AppProvider.getSearchInstalledUri(query); + } + @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return inflater.inflate(R.layout.installed_app_list, container, false); From bfb90ef655be927f03468105b6fa4cd8774b37c0 Mon Sep 17 00:00:00 2001 From: Peter Serwylo Date: Sat, 28 Nov 2015 12:26:38 +1100 Subject: [PATCH 02/11] Correctly search currently selected category in main app list. --- .../org/fdroid/fdroid/data/AppProvider.java | 60 +++++++++++++++++-- .../fragments/AvailableAppsFragment.java | 8 ++- 2 files changed, 62 insertions(+), 6 deletions(-) diff --git a/F-Droid/src/org/fdroid/fdroid/data/AppProvider.java b/F-Droid/src/org/fdroid/fdroid/data/AppProvider.java index cc265132b..fd98601e6 100644 --- a/F-Droid/src/org/fdroid/fdroid/data/AppProvider.java +++ b/F-Droid/src/org/fdroid/fdroid/data/AppProvider.java @@ -425,14 +425,17 @@ public class AppProvider extends FDroidProvider { private static final String PATH_INSTALLED = "installed"; private static final String PATH_CAN_UPDATE = "canUpdate"; private static final String PATH_SEARCH = "search"; - private static final String PATH_SEARCH_INSTALLED = "seasrchInstalled"; + private static final String PATH_SEARCH_INSTALLED = "searchInstalled"; private static final String PATH_SEARCH_CAN_UPDATE = "searchCanUpdate"; private static final String PATH_SEARCH_REPO = "searchRepo"; private static final String PATH_NO_APKS = "noApks"; private static final String PATH_APPS = "apps"; private static final String PATH_RECENTLY_UPDATED = "recentlyUpdated"; + private static final String PATH_SEARCH_RECENTLY_UPDATED = "searchRecentlyUpdated"; private static final String PATH_NEWLY_ADDED = "newlyAdded"; + private static final String PATH_SEARCH_NEWLY_ADDED = "searchNewlyAdded"; private static final String PATH_CATEGORY = "category"; + private static final String PATH_SEARCH_CATEGORY = "searchCategory"; private static final String PATH_IGNORED = "ignored"; private static final String PATH_CALC_APP_DETAILS_FROM_INDEX = "calcDetailsFromIndex"; private static final String PATH_REPO = "repo"; @@ -451,6 +454,9 @@ public class AppProvider extends FDroidProvider { private static final int SEARCH_REPO = REPO + 1; private static final int SEARCH_INSTALLED = SEARCH_REPO + 1; private static final int SEARCH_CAN_UPDATE = SEARCH_INSTALLED + 1; + private static final int SEARCH_CATEGORY = SEARCH_CAN_UPDATE + 1; + private static final int SEARCH_NEWLY_ADDED = SEARCH_CATEGORY + 1; + private static final int SEARCH_RECENTLY_UPDATED = SEARCH_NEWLY_ADDED + 1; static { matcher.addURI(getAuthority(), null, CODE_LIST); @@ -460,6 +466,9 @@ public class AppProvider extends FDroidProvider { matcher.addURI(getAuthority(), PATH_NEWLY_ADDED, NEWLY_ADDED); matcher.addURI(getAuthority(), PATH_CATEGORY + "/*", CATEGORY); matcher.addURI(getAuthority(), PATH_SEARCH + "/*", SEARCH); + matcher.addURI(getAuthority(), PATH_SEARCH_NEWLY_ADDED + "/*", SEARCH_NEWLY_ADDED); + matcher.addURI(getAuthority(), PATH_SEARCH_RECENTLY_UPDATED + "/*", SEARCH_RECENTLY_UPDATED); + matcher.addURI(getAuthority(), PATH_SEARCH_CATEGORY + "/*/*", SEARCH_CATEGORY); matcher.addURI(getAuthority(), PATH_SEARCH_INSTALLED + "/*", SEARCH_INSTALLED); matcher.addURI(getAuthority(), PATH_SEARCH_CAN_UPDATE + "/*", SEARCH_CAN_UPDATE); matcher.addURI(getAuthority(), PATH_SEARCH_REPO + "/*/*", SEARCH_REPO); @@ -479,10 +488,24 @@ public class AppProvider extends FDroidProvider { return Uri.withAppendedPath(getContentUri(), PATH_RECENTLY_UPDATED); } + public static Uri getSearchRecentlyUpdatedUri(String query) { + return getContentUri().buildUpon() + .appendPath(PATH_SEARCH_RECENTLY_UPDATED) + .appendEncodedPath(query) + .build(); + } + public static Uri getNewlyAddedUri() { return Uri.withAppendedPath(getContentUri(), PATH_NEWLY_ADDED); } + public static Uri getSearchNewlyAddedUri(String query) { + return getContentUri().buildUpon() + .appendPath(PATH_SEARCH_NEWLY_ADDED) + .appendEncodedPath(query) + .build(); + } + public static Uri getIgnoredUri() { return Uri.withAppendedPath(getContentUri(), PATH_IGNORED); } @@ -498,6 +521,14 @@ public class AppProvider extends FDroidProvider { .build(); } + public static Uri getSearchCategoryUri(String category, String query) { + return getContentUri().buildUpon() + .appendPath(PATH_SEARCH_CATEGORY) + .appendEncodedPath(category) + .appendEncodedPath(query) + .build(); + } + public static Uri getNoApksUri() { return Uri.withAppendedPath(getContentUri(), PATH_NO_APKS); } @@ -542,7 +573,7 @@ public class AppProvider extends FDroidProvider { public static Uri getSearchUri(String query) { return getContentUri().buildUpon() .appendPath(PATH_SEARCH) - .appendPath(query) + .appendEncodedPath(query) .build(); } @@ -550,7 +581,7 @@ public class AppProvider extends FDroidProvider { return getContentUri() .buildUpon() .appendPath(PATH_SEARCH_INSTALLED) - .appendPath(query) + .appendEncodedPath(query) .build(); } @@ -558,7 +589,7 @@ public class AppProvider extends FDroidProvider { return getContentUri() .buildUpon() .appendPath(PATH_SEARCH_CAN_UPDATE) - .appendPath(query) + .appendEncodedPath(query) .build(); } @@ -566,7 +597,7 @@ public class AppProvider extends FDroidProvider { return getContentUri().buildUpon() .appendPath(PATH_SEARCH_REPO) .appendPath(repo.id + "") - .appendPath(query) + .appendEncodedPath(query) .build(); } @@ -789,18 +820,37 @@ public class AppProvider extends FDroidProvider { includeSwap = false; break; + case SEARCH_CATEGORY: + String query = uri.getPathSegments().get(2); + String category = uri.getPathSegments().get(1); + selection = selection.add(queryCategory(category)).add(querySearch(query)); + includeSwap = false; + break; + case RECENTLY_UPDATED: sortOrder = getTableName() + ".lastUpdated DESC"; selection = selection.add(queryRecentlyUpdated()); includeSwap = false; break; + case SEARCH_RECENTLY_UPDATED: + sortOrder = " fdroid_app.lastUpdated DESC"; + selection = selection.add(queryRecentlyUpdated()).add(querySearch(uri.getLastPathSegment())); + includeSwap = false; + break; + case NEWLY_ADDED: sortOrder = getTableName() + ".added DESC"; selection = selection.add(queryNewlyAdded()); includeSwap = false; break; + case SEARCH_NEWLY_ADDED: + sortOrder = " fdroid_app.added DESC"; + selection = selection.add(queryNewlyAdded()).add(querySearch(uri.getLastPathSegment())); + includeSwap = false; + break; + default: Log.e(TAG, "Invalid URI for app content provider: " + uri); throw new UnsupportedOperationException("Invalid URI for app content provider: " + uri); diff --git a/F-Droid/src/org/fdroid/fdroid/views/fragments/AvailableAppsFragment.java b/F-Droid/src/org/fdroid/fdroid/views/fragments/AvailableAppsFragment.java index 9805f7973..554fd6009 100644 --- a/F-Droid/src/org/fdroid/fdroid/views/fragments/AvailableAppsFragment.java +++ b/F-Droid/src/org/fdroid/fdroid/views/fragments/AvailableAppsFragment.java @@ -165,7 +165,13 @@ public class AvailableAppsFragment extends AppListFragment implements } protected Uri getDataUri(String query) { - return AppProvider.getSearchUri(query); + if (currentCategory == null || currentCategory.equals(AppProvider.Helper.getCategoryAll(getActivity()))) + return AppProvider.getSearchUri(query); + if (currentCategory.equals(AppProvider.Helper.getCategoryRecentlyUpdated(getActivity()))) + return AppProvider.getSearchRecentlyUpdatedUri(query); + if (currentCategory.equals(AppProvider.Helper.getCategoryWhatsNew(getActivity()))) + return AppProvider.getSearchNewlyAddedUri(query); + return AppProvider.getSearchCategoryUri(currentCategory, query); } private void setCurrentCategory(String category) { From 7b5160df4760b2bb64c148ce1765041243adb770 Mon Sep 17 00:00:00 2001 From: Peter Serwylo Date: Tue, 8 Dec 2015 00:09:08 +1100 Subject: [PATCH 03/11] Make the SearchView get shown when SearchDialog is submitted. --- F-Droid/src/org/fdroid/fdroid/FDroid.java | 76 +++++++++++++------ .../org/fdroid/fdroid/compat/UriCompat.java | 25 ++++++ F-Droid/tools/test-search-intents.sh | 42 ++++++++++ 3 files changed, 120 insertions(+), 23 deletions(-) create mode 100644 F-Droid/src/org/fdroid/fdroid/compat/UriCompat.java create mode 100755 F-Droid/tools/test-search-intents.sh diff --git a/F-Droid/src/org/fdroid/fdroid/FDroid.java b/F-Droid/src/org/fdroid/fdroid/FDroid.java index b5750a1e6..9f77c976e 100644 --- a/F-Droid/src/org/fdroid/fdroid/FDroid.java +++ b/F-Droid/src/org/fdroid/fdroid/FDroid.java @@ -31,7 +31,6 @@ import android.net.Uri; import android.os.Bundle; import android.support.annotation.NonNull; import android.support.annotation.Nullable; -import android.support.v4.content.LocalBroadcastManager; import android.support.v4.view.MenuItemCompat; import android.support.v4.view.ViewPager; import android.support.v7.app.AlertDialog; @@ -45,7 +44,9 @@ import android.view.View; import android.widget.TextView; import android.widget.Toast; +import org.fdroid.fdroid.compat.Compatibility; import org.fdroid.fdroid.compat.TabManager; +import org.fdroid.fdroid.compat.UriCompat; import org.fdroid.fdroid.data.AppProvider; import org.fdroid.fdroid.data.NewRepoConfig; import org.fdroid.fdroid.privileged.install.InstallExtensionDialogActivity; @@ -75,6 +76,9 @@ public class FDroid extends AppCompatActivity implements SearchView.OnQueryTextL private AppListFragmentPagerAdapter adapter; + @Nullable + private MenuItem searchMenuItem; + @Override protected void onCreate(Bundle savedInstanceState) { @@ -92,8 +96,9 @@ public class FDroid extends AppCompatActivity implements SearchView.OnQueryTextL Intent intent = getIntent(); - // If the intent can be handled via AppDetails or SearchResults, it - // will call finish() and the rest of the code won't execute + // If the intent can be handled via AppDetails it will call finish() + // and the rest of the code won't execute. If it looks like a search term, + // this will prompt the SearchView to update itself. handleIntent(intent); if (intent.hasExtra(EXTRA_TAB_UPDATE)) { @@ -116,6 +121,17 @@ public class FDroid extends AppCompatActivity implements SearchView.OnQueryTextL // } } + private void performSearch(String query) { + if (searchMenuItem == null) { + Log.e(TAG, "Tried to search, but search view has not yet been created."); + return; + } + + SearchView searchView = (SearchView) MenuItemCompat.getActionView(searchMenuItem); + MenuItemCompat.expandActionView(searchMenuItem); + searchView.setQuery(query, true); + } + @Override protected void onResume() { super.onResume(); @@ -124,11 +140,24 @@ public class FDroid extends AppCompatActivity implements SearchView.OnQueryTextL checkForAddRepoIntent(); } + @Override + protected void onNewIntent(Intent intent) { + super.onNewIntent(intent); + handleIntent(intent); + } + private void handleIntent(Intent intent) { final Uri data = intent.getData(); if (data == null) { return; } + + if (Intent.ACTION_SEARCH.equals(intent.getAction())) { + String query = intent.getStringExtra(SearchManager.QUERY); + performSearch(query); + return; + } + final String scheme = data.getScheme(); final String path = data.getPath(); String appId = null; @@ -140,11 +169,14 @@ public class FDroid extends AppCompatActivity implements SearchView.OnQueryTextL } switch (host) { case "f-droid.org": - // http://f-droid.org/app/app.id if (path.startsWith("/repository/browse")) { + // http://f-droid.org/repository/browse?fdfilter=search+query + query = UriCompat.getQueryParameter(data, "fdfilter"); + // http://f-droid.org/repository/browse?fdid=app.id - appId = data.getQueryParameter("fdid"); + appId = UriCompat.getQueryParameter(data, "fdid"); } else if (path.startsWith("/app")) { + // http://f-droid.org/app/app.id appId = data.getLastPathSegment(); if ("app".equals(appId)) { appId = null; @@ -153,28 +185,28 @@ public class FDroid extends AppCompatActivity implements SearchView.OnQueryTextL break; case "details": // market://details?id=app.id - appId = data.getQueryParameter("id"); + appId = UriCompat.getQueryParameter(data, "id"); break; case "search": // market://search?q=query - query = data.getQueryParameter("q"); + query = UriCompat.getQueryParameter(data, "q"); break; case "play.google.com": if (path.startsWith("/store/apps/details")) { // http://play.google.com/store/apps/details?id=app.id - appId = data.getQueryParameter("id"); + appId = UriCompat.getQueryParameter(data, "id"); } else if (path.startsWith("/store/search")) { // http://play.google.com/store/search?q=foo - query = data.getQueryParameter("q"); + query = UriCompat.getQueryParameter(data, "q"); } break; case "apps": case "amazon.com": case "www.amazon.com": // amzn://apps/android?p=app.id - // http://amazon.com/gp/mas/dl/android?p=app.id - appId = data.getQueryParameter("p"); - query = data.getQueryParameter("s"); + // http://amazon.com/gp/mas/dl/android?s=app.id + appId = UriCompat.getQueryParameter(data, "p"); + query = UriCompat.getQueryParameter(data, "s"); break; } } else if ("fdroid.app".equals(scheme)) { @@ -182,7 +214,7 @@ public class FDroid extends AppCompatActivity implements SearchView.OnQueryTextL appId = data.getSchemeSpecificPart(); } else if ("fdroid.search".equals(scheme)) { // fdroid.search:query - query = data.getSchemeSpecificPart(); + query = UriCompat.replacePlusWithSpace(data.getSchemeSpecificPart()); } if (!TextUtils.isEmpty(query)) { @@ -202,10 +234,9 @@ public class FDroid extends AppCompatActivity implements SearchView.OnQueryTextL call.putExtra(AppDetails.EXTRA_APPID, appId); } else if (!TextUtils.isEmpty(query)) { Utils.debugLog(TAG, "FDroid launched via search link for '" + query + "'"); - call = new Intent(this, SearchResults.class); - call.setAction(Intent.ACTION_SEARCH); - call.putExtra(SearchManager.QUERY, query); + performSearch(query); } + if (call != null) { startActivity(call); finish(); @@ -250,8 +281,8 @@ public class FDroid extends AppCompatActivity implements SearchView.OnQueryTextL } SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE); - MenuItem searchItem = menu.findItem(R.id.action_search); - SearchView searchView = (SearchView) MenuItemCompat.getActionView(searchItem); + searchMenuItem = menu.findItem(R.id.action_search); + SearchView searchView = (SearchView) MenuItemCompat.getActionView(searchMenuItem); searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName())); // LayoutParams.MATCH_PARENT does not work, use a big value instead searchView.setMaxWidth(1000000); @@ -374,15 +405,14 @@ public class FDroid extends AppCompatActivity implements SearchView.OnQueryTextL @Override public boolean onQueryTextSubmit(String query) { - return false; + // Do nothing, because we respond to the query being changed as it is updated + // via onQueryTextChange(...) + return true; } - private static final String SEARCH_CHANGED = "fdroid.SearchChanged"; - private static final String SEARCH_QUERY = "fdroid.SearchQuery"; - @Override public boolean onQueryTextChange(String newText) { - this.adapter.updateSearchQuery(newText, getTabManager().getSelectedIndex()); + adapter.updateSearchQuery(newText, getTabManager().getSelectedIndex()); return true; } diff --git a/F-Droid/src/org/fdroid/fdroid/compat/UriCompat.java b/F-Droid/src/org/fdroid/fdroid/compat/UriCompat.java new file mode 100644 index 000000000..c703b1efd --- /dev/null +++ b/F-Droid/src/org/fdroid/fdroid/compat/UriCompat.java @@ -0,0 +1,25 @@ +package org.fdroid.fdroid.compat; + +import android.net.Uri; +import android.os.Build; + +public class UriCompat { + + /** + * Uri#getQueryParameter(String) has the following warning: + * + * > Prior to Ice Cream Sandwich, this decoded the '+' character as '+' rather than ' '. + */ + public static String getQueryParameter(Uri uri, String key) { + String value = uri.getQueryParameter(key); + if (value != null && Build.VERSION.SDK_INT < Build.VERSION_CODES.ICE_CREAM_SANDWICH) { + value = replacePlusWithSpace(value); + } + return value; + } + + public static String replacePlusWithSpace(String input) { + return input.replaceAll("\\+", " "); + } + +} diff --git a/F-Droid/tools/test-search-intents.sh b/F-Droid/tools/test-search-intents.sh new file mode 100755 index 000000000..c93f77c7a --- /dev/null +++ b/F-Droid/tools/test-search-intents.sh @@ -0,0 +1,42 @@ +#!/bin/sh + +function view { + DESCRIPTION=$1 + DATA=$2 + wait "$DESCRIPTION" + CMD="adb shell am start -a android.intent.action.VIEW -d $DATA" + $CMD + echo "" + sleep 1 +} + +function wait { + DESCRIPTION=$1 + echo "$DESCRIPTION [Y/n]" + + read -n 1 RESULT + + # Lower case the result. + RESULT=`echo "$RESULT" | tr '[:upper:]' '[:lower:]'` + + echo "" + + if [ "$RESULT" != 'y' ]; then + exit; + fi +} + +APP_TO_SHOW=org.fdroid.fdroid +SEARCH_QUERY=book+reader + +view "Search for '$SEARCH_QUERY' (fdroid web)" http://f-droid.org/repository/browse?fdfilter=$SEARCH_QUERY +view "Search for '$SEARCH_QUERY' (market)" market://search?q=$SEARCH_QUERY +view "Search for '$SEARCH_QUERY' (play)" http://play.google.com/store/search?q=$SEARCH_QUERY +view "Search for '$SEARCH_QUERY' (amazon)" http://amazon.com/gp/mas/dl/android?s=$SEARCH_QUERY +view "Search for '$SEARCH_QUERY' (fdroid)" fdroid.search:$SEARCH_QUERY +view "View '$APP_TO_SHOW' (fdroid web fdid)" http://f-droid.org/repository/browse?fdid=$APP_TO_SHOW +view "View '$APP_TO_SHOW' (fdroid web /app/ path)" http://f-droid.org/app/$APP_TO_SHOW +view "View '$APP_TO_SHOW' (market)" market://details?id=$APP_TO_SHOW +view "View '$APP_TO_SHOW' (play)" http://play.google.com/store/apps/details?id=$APP_TO_SHOW +view "View '$APP_TO_SHOW' (amazon)" amzn://apps/android?p=$APP_TO_SHOW +view "View '$APP_TO_SHOW' (fdroid)" fdroid.app:$APP_TO_SHOW From 829e8f10581dd361c818fd00e82c2b0e23b6064c Mon Sep 17 00:00:00 2001 From: Peter Serwylo Date: Tue, 8 Dec 2015 00:20:20 +1100 Subject: [PATCH 04/11] Queue pending search until the SearchView is inflated. --- F-Droid/src/org/fdroid/fdroid/FDroid.java | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/F-Droid/src/org/fdroid/fdroid/FDroid.java b/F-Droid/src/org/fdroid/fdroid/FDroid.java index 9f77c976e..0013cd264 100644 --- a/F-Droid/src/org/fdroid/fdroid/FDroid.java +++ b/F-Droid/src/org/fdroid/fdroid/FDroid.java @@ -79,6 +79,9 @@ public class FDroid extends AppCompatActivity implements SearchView.OnQueryTextL @Nullable private MenuItem searchMenuItem; + @Nullable + private String pendingSearchQuery; + @Override protected void onCreate(Bundle savedInstanceState) { @@ -123,7 +126,8 @@ public class FDroid extends AppCompatActivity implements SearchView.OnQueryTextL private void performSearch(String query) { if (searchMenuItem == null) { - Log.e(TAG, "Tried to search, but search view has not yet been created."); + // Store this for later when we do actually have a search menu ready to use. + pendingSearchQuery = query; return; } @@ -288,6 +292,11 @@ public class FDroid extends AppCompatActivity implements SearchView.OnQueryTextL searchView.setMaxWidth(1000000); searchView.setOnQueryTextListener(this); + if (pendingSearchQuery != null) { + performSearch(pendingSearchQuery); + pendingSearchQuery = null; + } + return super.onCreateOptionsMenu(menu); } From cb0f252d7457e9bcd19d1290ff986f6f1731f0a9 Mon Sep 17 00:00:00 2001 From: Peter Serwylo Date: Tue, 8 Dec 2015 00:30:38 +1100 Subject: [PATCH 05/11] Don't `finish()` activity after showing app details. When calling `finish()` after handling an intent to show app details, the ability to navigate "up" disappears. --- F-Droid/src/org/fdroid/fdroid/FDroid.java | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/F-Droid/src/org/fdroid/fdroid/FDroid.java b/F-Droid/src/org/fdroid/fdroid/FDroid.java index 0013cd264..e0fa5b58c 100644 --- a/F-Droid/src/org/fdroid/fdroid/FDroid.java +++ b/F-Droid/src/org/fdroid/fdroid/FDroid.java @@ -44,7 +44,6 @@ import android.view.View; import android.widget.TextView; import android.widget.Toast; -import org.fdroid.fdroid.compat.Compatibility; import org.fdroid.fdroid.compat.TabManager; import org.fdroid.fdroid.compat.UriCompat; import org.fdroid.fdroid.data.AppProvider; @@ -52,7 +51,6 @@ import org.fdroid.fdroid.data.NewRepoConfig; import org.fdroid.fdroid.privileged.install.InstallExtensionDialogActivity; import org.fdroid.fdroid.views.AppListFragmentPagerAdapter; import org.fdroid.fdroid.views.ManageReposActivity; -import org.fdroid.fdroid.views.fragments.AppListFragment; import org.fdroid.fdroid.views.swap.SwapWorkflowActivity; public class FDroid extends AppCompatActivity implements SearchView.OnQueryTextListener { @@ -98,11 +96,7 @@ public class FDroid extends AppCompatActivity implements SearchView.OnQueryTextL setDefaultKeyMode(DEFAULT_KEYS_SEARCH_LOCAL); Intent intent = getIntent(); - - // If the intent can be handled via AppDetails it will call finish() - // and the rest of the code won't execute. If it looks like a search term, - // this will prompt the SearchView to update itself. - handleIntent(intent); + handleSearchOrAppViewIntent(intent); if (intent.hasExtra(EXTRA_TAB_UPDATE)) { boolean showUpdateTab = intent.getBooleanExtra(EXTRA_TAB_UPDATE, false); @@ -147,10 +141,10 @@ public class FDroid extends AppCompatActivity implements SearchView.OnQueryTextL @Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); - handleIntent(intent); + handleSearchOrAppViewIntent(intent); } - private void handleIntent(Intent intent) { + private void handleSearchOrAppViewIntent(Intent intent) { final Uri data = intent.getData(); if (data == null) { return; @@ -243,7 +237,6 @@ public class FDroid extends AppCompatActivity implements SearchView.OnQueryTextL if (call != null) { startActivity(call); - finish(); } } From 59c6e360346d4701fe575bebb36d40f25dba38f4 Mon Sep 17 00:00:00 2001 From: Peter Serwylo Date: Tue, 8 Dec 2015 00:53:56 +1100 Subject: [PATCH 06/11] Minor formatting/lint fixes/cleanup before CR. --- F-Droid/src/org/fdroid/fdroid/FDroid.java | 28 +++++++++---------- .../org/fdroid/fdroid/compat/TabManager.java | 4 --- .../views/AppListFragmentPagerAdapter.java | 22 ++++----------- .../views/fragments/AppListFragment.java | 5 ++-- F-Droid/tools/test-search-intents.sh | 4 +++ 5 files changed, 25 insertions(+), 38 deletions(-) diff --git a/F-Droid/src/org/fdroid/fdroid/FDroid.java b/F-Droid/src/org/fdroid/fdroid/FDroid.java index e0fa5b58c..b7e04012b 100644 --- a/F-Droid/src/org/fdroid/fdroid/FDroid.java +++ b/F-Droid/src/org/fdroid/fdroid/FDroid.java @@ -145,17 +145,17 @@ public class FDroid extends AppCompatActivity implements SearchView.OnQueryTextL } private void handleSearchOrAppViewIntent(Intent intent) { - final Uri data = intent.getData(); - if (data == null) { - return; - } - if (Intent.ACTION_SEARCH.equals(intent.getAction())) { String query = intent.getStringExtra(SearchManager.QUERY); performSearch(query); return; } + final Uri data = intent.getData(); + if (data == null) { + return; + } + final String scheme = data.getScheme(); final String path = data.getPath(); String appId = null; @@ -225,19 +225,15 @@ public class FDroid extends AppCompatActivity implements SearchView.OnQueryTextL query = query.split(":")[1]; } - Intent call = null; if (!TextUtils.isEmpty(appId)) { Utils.debugLog(TAG, "FDroid launched via app link for '" + appId + "'"); - call = new Intent(this, AppDetails.class); - call.putExtra(AppDetails.EXTRA_APPID, appId); + Intent intentToInvoke = new Intent(this, AppDetails.class); + intentToInvoke.putExtra(AppDetails.EXTRA_APPID, appId); + startActivity(intentToInvoke); } else if (!TextUtils.isEmpty(query)) { Utils.debugLog(TAG, "FDroid launched via search link for '" + query + "'"); performSearch(query); } - - if (call != null) { - startActivity(call); - } } private void checkForAddRepoIntent() { @@ -285,6 +281,8 @@ public class FDroid extends AppCompatActivity implements SearchView.OnQueryTextL searchView.setMaxWidth(1000000); searchView.setOnQueryTextListener(this); + // If we were asked to execute a search before getting around to building the options + // menu, then we should deal with that now that the options menu is all sorted out. if (pendingSearchQuery != null) { performSearch(pendingSearchQuery); pendingSearchQuery = null; @@ -376,8 +374,8 @@ public class FDroid extends AppCompatActivity implements SearchView.OnQueryTextL private void createViews() { viewPager = (ViewPager) findViewById(R.id.main_pager); - this.adapter = new AppListFragmentPagerAdapter(this); - viewPager.setAdapter(this.adapter); + adapter = new AppListFragmentPagerAdapter(this); + viewPager.setAdapter(adapter); viewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() { @Override public void onPageSelected(int position) { @@ -414,7 +412,7 @@ public class FDroid extends AppCompatActivity implements SearchView.OnQueryTextL @Override public boolean onQueryTextChange(String newText) { - adapter.updateSearchQuery(newText, getTabManager().getSelectedIndex()); + adapter.updateSearchQuery(newText); return true; } diff --git a/F-Droid/src/org/fdroid/fdroid/compat/TabManager.java b/F-Droid/src/org/fdroid/fdroid/compat/TabManager.java index 17a65f4d4..524f1a2ad 100644 --- a/F-Droid/src/org/fdroid/fdroid/compat/TabManager.java +++ b/F-Droid/src/org/fdroid/fdroid/compat/TabManager.java @@ -35,10 +35,6 @@ public class TabManager { this.pager = pager; } - public int getSelectedIndex() { - return actionBar != null ? actionBar.getSelectedNavigationIndex() : -1; - } - protected CharSequence getLabel(int index) { return pager.getAdapter().getPageTitle(index); } diff --git a/F-Droid/src/org/fdroid/fdroid/views/AppListFragmentPagerAdapter.java b/F-Droid/src/org/fdroid/fdroid/views/AppListFragmentPagerAdapter.java index f0c48be64..7ce790d3c 100644 --- a/F-Droid/src/org/fdroid/fdroid/views/AppListFragmentPagerAdapter.java +++ b/F-Droid/src/org/fdroid/fdroid/views/AppListFragmentPagerAdapter.java @@ -20,22 +20,13 @@ import org.fdroid.fdroid.views.fragments.InstalledAppsFragment; */ public class AppListFragmentPagerAdapter extends FragmentPagerAdapter { - @NonNull - private final FDroid parent; + @NonNull private final FDroid parent; - @NonNull - private final AppListFragment availableFragment; - - @NonNull - private final AppListFragment installedFragment; - - @NonNull - private final AppListFragment canUpdateFragment; - - @Nullable - private String searchQuery; + @NonNull private final AppListFragment availableFragment; + @NonNull private final AppListFragment installedFragment; + @NonNull private final AppListFragment canUpdateFragment; - public AppListFragmentPagerAdapter(FDroid parent) { + public AppListFragmentPagerAdapter(@NonNull FDroid parent) { super(parent.getSupportFragmentManager()); this.parent = parent; @@ -54,8 +45,7 @@ public class AppListFragmentPagerAdapter extends FragmentPagerAdapter { return parent.getString(R.string.tab_updates_count, updateCount); } - public void updateSearchQuery(@Nullable String query, int tabIndex) { - searchQuery = query; + public void updateSearchQuery(@Nullable String query) { availableFragment.updateSearchQuery(query); installedFragment.updateSearchQuery(query); canUpdateFragment.updateSearchQuery(query); diff --git a/F-Droid/src/org/fdroid/fdroid/views/fragments/AppListFragment.java b/F-Droid/src/org/fdroid/fdroid/views/fragments/AppListFragment.java index 985e4e5e9..21c7b8071 100644 --- a/F-Droid/src/org/fdroid/fdroid/views/fragments/AppListFragment.java +++ b/F-Droid/src/org/fdroid/fdroid/views/fragments/AppListFragment.java @@ -54,8 +54,7 @@ public abstract class AppListFragment extends ListFragment implements protected AppListAdapter appAdapter; - @Nullable - private String searchQuery; + @Nullable private String searchQuery; protected abstract AppListAdapter getAppListAdapter(); @@ -157,7 +156,7 @@ public abstract class AppListFragment extends ListFragment implements } public void updateSearchQuery(@Nullable String query) { - this.searchQuery = query; + searchQuery = query; if (isAdded()) { getLoaderManager().restartLoader(0, null, this); } diff --git a/F-Droid/tools/test-search-intents.sh b/F-Droid/tools/test-search-intents.sh index c93f77c7a..172eaddde 100755 --- a/F-Droid/tools/test-search-intents.sh +++ b/F-Droid/tools/test-search-intents.sh @@ -1,5 +1,9 @@ #!/bin/sh +echo "A helper script to send all of the various intents that F-droid should be able to handle via ADB." +echo "Use this to ensure that things which should trigger searches, do trigger searches, and those which should bring up the app details screen, do bring it up." +echo "" + function view { DESCRIPTION=$1 DATA=$2 From cc759b17a4d4319a43b88b305ddb31839f92dbcb Mon Sep 17 00:00:00 2001 From: Peter Serwylo Date: Thu, 10 Dec 2015 07:53:00 +1100 Subject: [PATCH 07/11] Fixed typo in doc comments about % and sqlite. % means wildcard, not case insensitive in sqlite3. --- F-Droid/src/org/fdroid/fdroid/data/AppProvider.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/F-Droid/src/org/fdroid/fdroid/data/AppProvider.java b/F-Droid/src/org/fdroid/fdroid/data/AppProvider.java index fd98601e6..a5a94ea95 100644 --- a/F-Droid/src/org/fdroid/fdroid/data/AppProvider.java +++ b/F-Droid/src/org/fdroid/fdroid/data/AppProvider.java @@ -650,7 +650,7 @@ public class AppProvider extends FDroidProvider { getTableName() + ".description", }; - // Remove duplicates, surround in % for case insensitive searching + // Remove duplicates, surround in % for wildcard searching final Set keywordSet = new HashSet<>(Arrays.asList(query.split("\\s"))); final String[] keywords = new String[keywordSet.size()]; int iKeyword = 0; From 86fb652fc35ed08c9fdfb95db149b7818227a17c Mon Sep 17 00:00:00 2001 From: Peter Serwylo Date: Thu, 10 Dec 2015 07:57:52 +1100 Subject: [PATCH 08/11] When searching "Available" tab, search all the things. Removed the option to search the currently selected category, as suggested by others on gitlab. --- F-Droid/res/layout/available_app_list.xml | 3 +- .../org/fdroid/fdroid/data/AppProvider.java | 50 ------------------- .../views/fragments/AppListFragment.java | 37 +++++++++++++- .../fragments/AvailableAppsFragment.java | 23 ++++++--- 4 files changed, 54 insertions(+), 59 deletions(-) diff --git a/F-Droid/res/layout/available_app_list.xml b/F-Droid/res/layout/available_app_list.xml index 1ff394163..da7cfe111 100644 --- a/F-Droid/res/layout/available_app_list.xml +++ b/F-Droid/res/layout/available_app_list.xml @@ -2,7 +2,8 @@ + android:layout_height="match_parent" + android:animateLayoutChanges="true"> multiple times, every time the user changes the + * search query. + */ + protected void onSearch() { + // Do nothing by default. + } + + /** + * Alerts the child class that the user is no longer performing a search. + * This is triggered every time the search query is blank. + * @see AppListFragment#onSearch() + */ + protected void onSearchStopped() { + // Do nothing by default. + } + @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); @@ -150,11 +170,26 @@ public abstract class AppListFragment extends ListFragment implements @Override public Loader onCreateLoader(int id, Bundle args) { - Uri uri = TextUtils.isEmpty(searchQuery) ? getDataUri() : getDataUri(searchQuery); + Uri uri = updateSearchStatus() ? getDataUri(searchQuery) : getDataUri(); return new CursorLoader( getActivity(), uri, APP_PROJECTION, null, null, APP_SORT); } + /** + * Notifies the subclass via {@link AppListFragment#onSearch()} and {@link AppListFragment#onSearchStopped()} + * about whether or not a search is taking place. + * @return True if a user is searching. + */ + private boolean updateSearchStatus() { + if (TextUtils.isEmpty(searchQuery)) { + onSearchStopped(); + return false; + } else { + onSearch(); + return true; + } + } + public void updateSearchQuery(@Nullable String query) { searchQuery = query; if (isAdded()) { diff --git a/F-Droid/src/org/fdroid/fdroid/views/fragments/AvailableAppsFragment.java b/F-Droid/src/org/fdroid/fdroid/views/fragments/AvailableAppsFragment.java index 554fd6009..6fafeb431 100644 --- a/F-Droid/src/org/fdroid/fdroid/views/fragments/AvailableAppsFragment.java +++ b/F-Droid/src/org/fdroid/fdroid/views/fragments/AvailableAppsFragment.java @@ -164,14 +164,9 @@ public class AvailableAppsFragment extends AppListFragment implements return AppProvider.getCategoryUri(currentCategory); } + @Override protected Uri getDataUri(String query) { - if (currentCategory == null || currentCategory.equals(AppProvider.Helper.getCategoryAll(getActivity()))) - return AppProvider.getSearchUri(query); - if (currentCategory.equals(AppProvider.Helper.getCategoryRecentlyUpdated(getActivity()))) - return AppProvider.getSearchRecentlyUpdatedUri(query); - if (currentCategory.equals(AppProvider.Helper.getCategoryWhatsNew(getActivity()))) - return AppProvider.getSearchNewlyAddedUri(query); - return AppProvider.getSearchCategoryUri(currentCategory, query); + return AppProvider.getSearchUri(query); } private void setCurrentCategory(String category) { @@ -207,4 +202,18 @@ public class AvailableAppsFragment extends AppListFragment implements e.putString(CATEGORY_KEY, currentCategory); e.commit(); } + + @Override + protected void onSearch() { + if (categorySpinner != null) { + categorySpinner.setVisibility(View.GONE); + } + } + + @Override + protected void onSearchStopped() { + if (categorySpinner != null) { + categorySpinner.setVisibility(View.VISIBLE); + } + } } From 49ffe065766e0f0f2d36bc533ad9ed0c082f7b60 Mon Sep 17 00:00:00 2001 From: Peter Serwylo Date: Sat, 12 Dec 2015 10:02:45 +1100 Subject: [PATCH 09/11] Don't remove +'s from an fdroid.search intent. As per CR comment. These don't really ressemble URIs very much, so I don't think they will require sanitization like this at all. --- F-Droid/src/org/fdroid/fdroid/FDroid.java | 2 +- F-Droid/src/org/fdroid/fdroid/compat/UriCompat.java | 6 +----- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/F-Droid/src/org/fdroid/fdroid/FDroid.java b/F-Droid/src/org/fdroid/fdroid/FDroid.java index b7e04012b..4a41f1b4b 100644 --- a/F-Droid/src/org/fdroid/fdroid/FDroid.java +++ b/F-Droid/src/org/fdroid/fdroid/FDroid.java @@ -212,7 +212,7 @@ public class FDroid extends AppCompatActivity implements SearchView.OnQueryTextL appId = data.getSchemeSpecificPart(); } else if ("fdroid.search".equals(scheme)) { // fdroid.search:query - query = UriCompat.replacePlusWithSpace(data.getSchemeSpecificPart()); + query = data.getSchemeSpecificPart(); } if (!TextUtils.isEmpty(query)) { diff --git a/F-Droid/src/org/fdroid/fdroid/compat/UriCompat.java b/F-Droid/src/org/fdroid/fdroid/compat/UriCompat.java index c703b1efd..90ffff0ca 100644 --- a/F-Droid/src/org/fdroid/fdroid/compat/UriCompat.java +++ b/F-Droid/src/org/fdroid/fdroid/compat/UriCompat.java @@ -13,13 +13,9 @@ public class UriCompat { public static String getQueryParameter(Uri uri, String key) { String value = uri.getQueryParameter(key); if (value != null && Build.VERSION.SDK_INT < Build.VERSION_CODES.ICE_CREAM_SANDWICH) { - value = replacePlusWithSpace(value); + value = value.replaceAll("\\+", " "); } return value; } - public static String replacePlusWithSpace(String input) { - return input.replaceAll("\\+", " "); - } - } From 58205fefec456e733938dcd5b6d9fbdacf084fba Mon Sep 17 00:00:00 2001 From: Peter Serwylo Date: Sun, 13 Dec 2015 08:25:41 +1100 Subject: [PATCH 10/11] Don't animate category spinner hiding This caused the entire list view to e animated when navigating back to the Available tab. Tried switching the `animateLayoutChanged=true` to a child view only containing the category spinner, but this is not how the animation handling works. It needs to animate both the thing being hidden/shown, and also the next sibling of that thing to work properly. Thus, moving the spinner to its own child and leaving the list didn't work. --- F-Droid/res/layout/available_app_list.xml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/F-Droid/res/layout/available_app_list.xml b/F-Droid/res/layout/available_app_list.xml index da7cfe111..1ff394163 100644 --- a/F-Droid/res/layout/available_app_list.xml +++ b/F-Droid/res/layout/available_app_list.xml @@ -2,8 +2,7 @@ + android:layout_height="match_parent"> Date: Mon, 14 Dec 2015 22:45:37 +1100 Subject: [PATCH 11/11] Also hide the coloured bar below the category spinner. In addition, added a @Nullable constraint on the categorySpinner and a null guard when resuming the fragment to handle possible null cases (though I don't think there will be any). --- F-Droid/res/layout/available_app_list.xml | 34 ++++++++++++------- .../fragments/AvailableAppsFragment.java | 30 ++++++++++------ 2 files changed, 41 insertions(+), 23 deletions(-) diff --git a/F-Droid/res/layout/available_app_list.xml b/F-Droid/res/layout/available_app_list.xml index 1ff394163..e1b35d157 100644 --- a/F-Droid/res/layout/available_app_list.xml +++ b/F-Droid/res/layout/available_app_list.xml @@ -4,27 +4,35 @@ android:layout_width="match_parent" android:layout_height="match_parent"> - + android:layout_height="wrap_content" + android:id="@+id/category_wrapper" + android:layout_alignParentTop="true"> - + + + + + + android:layout_below="@id/category_wrapper" /> diff --git a/F-Droid/src/org/fdroid/fdroid/views/fragments/AvailableAppsFragment.java b/F-Droid/src/org/fdroid/fdroid/views/fragments/AvailableAppsFragment.java index 6fafeb431..0b7aab7e5 100644 --- a/F-Droid/src/org/fdroid/fdroid/views/fragments/AvailableAppsFragment.java +++ b/F-Droid/src/org/fdroid/fdroid/views/fragments/AvailableAppsFragment.java @@ -8,6 +8,7 @@ import android.database.ContentObserver; import android.database.Cursor; import android.net.Uri; import android.os.Bundle; +import android.support.annotation.Nullable; import android.support.v4.app.LoaderManager; import android.view.LayoutInflater; import android.view.View; @@ -37,6 +38,11 @@ public class AvailableAppsFragment extends AppListFragment implements private static String defaultCategory; private List categories; + + @Nullable + private View categoryWrapper; + + @Nullable private Spinner categorySpinner; private String currentCategory; private AppListAdapter adapter; @@ -147,6 +153,7 @@ public class AvailableAppsFragment extends AppListFragment implements public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.available_app_list, container, false); + categoryWrapper = view.findViewById(R.id.category_wrapper); setupCategorySpinner((Spinner) view.findViewById(R.id.category_spinner)); defaultCategory = AppProvider.Helper.getCategoryWhatsNew(getActivity()); @@ -180,15 +187,18 @@ public class AvailableAppsFragment extends AppListFragment implements super.onResume(); /* restore the saved Category Spinner position */ Activity activity = getActivity(); - SharedPreferences p = activity.getSharedPreferences(PREFERENCES_FILE, - Context.MODE_PRIVATE); + SharedPreferences p = activity.getSharedPreferences(PREFERENCES_FILE, Context.MODE_PRIVATE); currentCategory = p.getString(CATEGORY_KEY, defaultCategory); - for (int i = 0; i < categorySpinner.getCount(); i++) { - if (currentCategory.equals(categorySpinner.getItemAtPosition(i).toString())) { - categorySpinner.setSelection(i); - break; + + if (categorySpinner != null) { + for (int i = 0; i < categorySpinner.getCount(); i++) { + if (currentCategory.equals(categorySpinner.getItemAtPosition(i).toString())) { + categorySpinner.setSelection(i); + break; + } } } + setCurrentCategory(currentCategory); } @@ -205,15 +215,15 @@ public class AvailableAppsFragment extends AppListFragment implements @Override protected void onSearch() { - if (categorySpinner != null) { - categorySpinner.setVisibility(View.GONE); + if (categoryWrapper != null) { + categoryWrapper.setVisibility(View.GONE); } } @Override protected void onSearchStopped() { - if (categorySpinner != null) { - categorySpinner.setVisibility(View.VISIBLE); + if (categoryWrapper != null) { + categoryWrapper.setVisibility(View.VISIBLE); } } }