From da566b44cea0ddc4d105b4475f9f6700925c41a4 Mon Sep 17 00:00:00 2001 From: Peter Serwylo Date: Wed, 18 Mar 2015 08:09:57 +1100 Subject: [PATCH] Don't show swap apps in the main list of apps. Achieve this by joining the fdroid_app table onto fdroid_apk and then fdroid_repo, then checking if fdroid_repo.isSwap is 1. --- .../org/fdroid/fdroid/data/AppProvider.java | 48 ++++++++++++++++++- .../org/fdroid/fdroid/data/QueryBuilder.java | 15 +++++- .../swap/ConfirmReceiveSwapFragment.java | 10 ++-- .../views/swap/ConnectSwapActivity.java | 6 ++- .../views/swap/SwapAppListActivity.java | 29 ++++++++++- 5 files changed, 99 insertions(+), 9 deletions(-) diff --git a/F-Droid/src/org/fdroid/fdroid/data/AppProvider.java b/F-Droid/src/org/fdroid/fdroid/data/AppProvider.java index 3e1fce0f1..e3ec1b4ba 100644 --- a/F-Droid/src/org/fdroid/fdroid/data/AppProvider.java +++ b/F-Droid/src/org/fdroid/fdroid/data/AppProvider.java @@ -262,7 +262,13 @@ public class AppProvider extends FDroidProvider { @Override protected String getRequiredTables() { - return DBHelper.TABLE_APP; + final String app = DBHelper.TABLE_APP; + final String apk = DBHelper.TABLE_APK; + final String repo = DBHelper.TABLE_REPO; + + return app + + " LEFT JOIN " + apk + " ON ( " + apk + ".id = " + app + ".id ) " + + " LEFT JOIN " + repo + " ON ( " + apk + ".repo = " + repo + "._id )"; } @Override @@ -270,6 +276,11 @@ public class AppProvider extends FDroidProvider { return fieldCount() == 1 && categoryFieldAdded; } + @Override + protected String groupBy() { + return DBHelper.TABLE_APP + ".id"; + } + public void addSelection(AppQuerySelection selection) { addSelection(selection.getSelection()); if (selection.naturalJoinToInstalled()) { @@ -372,6 +383,7 @@ public class AppProvider extends FDroidProvider { private static final String PATH_CATEGORY = "category"; 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"; private static final int CAN_UPDATE = CODE_SINGLE + 1; private static final int INSTALLED = CAN_UPDATE + 1; @@ -383,6 +395,7 @@ public class AppProvider extends FDroidProvider { 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; static { matcher.addURI(getAuthority(), null, CODE_LIST); @@ -392,6 +405,7 @@ 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_REPO + "/#", REPO); matcher.addURI(getAuthority(), PATH_CAN_UPDATE, CAN_UPDATE); matcher.addURI(getAuthority(), PATH_INSTALLED, INSTALLED); matcher.addURI(getAuthority(), PATH_NO_APKS, NO_APKS); @@ -438,6 +452,13 @@ public class AppProvider extends FDroidProvider { return Uri.withAppendedPath(getContentUri(), PATH_CAN_UPDATE); } + public static Uri getRepoUri(Repo repo) { + return getContentUri().buildUpon() + .appendPath(PATH_REPO) + .appendPath(String.valueOf(repo.id)) + .build(); + } + public static Uri getContentUri(List apps) { StringBuilder builder = new StringBuilder(); for (int i = 0; i < apps.size(); i ++) { @@ -494,6 +515,12 @@ public class AppProvider extends FDroidProvider { return new AppQuerySelection(where).requireNaturalInstalledTable(); } + private AppQuerySelection queryRepo(long repoId) { + String selection = " fdroid_apk.repo = ? "; + String[] args = { String.valueOf(repoId) }; + return new AppQuerySelection(selection, args); + } + private AppQuerySelection queryInstalled() { return new AppQuerySelection().requireNaturalInstalledTable(); } @@ -555,6 +582,14 @@ public class AppProvider extends FDroidProvider { return new AppQuerySelection(selection); } + private AppQuerySelection queryExcludeSwap() { + // fdroid_repo will have null fields if the LEFT JOIN didn't resolve, e.g. due to there + // being no apks for the app in the result set. In that case, we can't tell if it is from + // a swap repo or not. + String selection = " fdroid_repo.isSwap = 0 OR fdroid_repo.isSwap is null "; + return new AppQuerySelection(selection); + } + private AppQuerySelection queryNewlyAdded() { String selection = "fdroid_app.added > ?"; String[] args = { Utils.DATE_FORMAT.format(Preferences.get().calcMaxHistory()) }; @@ -599,11 +634,13 @@ public class AppProvider extends FDroidProvider { public Cursor query(Uri uri, String[] projection, String customSelection, String[] selectionArgs, String sortOrder) { Query query = new Query(); AppQuerySelection selection = new AppQuerySelection(customSelection, selectionArgs); + boolean includeSwap = false; switch (matcher.match(uri)) { case CODE_LIST: break; case CODE_SINGLE: + includeSwap = true; selection = selection.add(querySingle(uri.getLastPathSegment())); break; @@ -611,6 +648,11 @@ public class AppProvider extends FDroidProvider { selection = selection.add(queryCanUpdate()); break; + case REPO: + includeSwap = true; + selection = selection.add(queryRepo(Long.parseLong(uri.getLastPathSegment()))); + break; + case INSTALLED: selection = selection.add(queryInstalled()); break; @@ -650,6 +692,10 @@ public class AppProvider extends FDroidProvider { throw new UnsupportedOperationException("Invalid URI for app content provider: " + uri); } + if (!includeSwap) { + selection = selection.add(queryExcludeSwap()); + } + if (AppProvider.DataColumns.NAME.equals(sortOrder)) { sortOrder = " lower( fdroid_app." + sortOrder + " ) "; } diff --git a/F-Droid/src/org/fdroid/fdroid/data/QueryBuilder.java b/F-Droid/src/org/fdroid/fdroid/data/QueryBuilder.java index 63cb4dd37..d74086262 100644 --- a/F-Droid/src/org/fdroid/fdroid/data/QueryBuilder.java +++ b/F-Droid/src/org/fdroid/fdroid/data/QueryBuilder.java @@ -28,6 +28,10 @@ abstract class QueryBuilder { return false; } + protected String groupBy() { + return null; + } + protected void appendField(String field) { appendField(field, null, null); } @@ -85,6 +89,10 @@ abstract class QueryBuilder { .append(')'); } + private String distinctSql() { + return isDistinct() ? " DISTINCT " : ""; + } + private String fieldsSql() { StringBuilder sb = new StringBuilder(); for (int i = 0; i < fields.size(); i ++) { @@ -104,12 +112,15 @@ abstract class QueryBuilder { return orderBy != null ? " ORDER BY " + orderBy : ""; } + private String groupBySql() { + return groupBy() != null ? " GROUP BY " + groupBy() : ""; + } + private String tablesSql() { return tables.toString(); } public String toString() { - String distinct = isDistinct() ? " DISTINCT " : ""; - return "SELECT " + distinct + fieldsSql() + " FROM " + tablesSql() + whereSql() + orderBySql(); + return "SELECT " + distinctSql() + fieldsSql() + " FROM " + tablesSql() + whereSql() + groupBySql() + orderBySql(); } } diff --git a/F-Droid/src/org/fdroid/fdroid/views/swap/ConfirmReceiveSwapFragment.java b/F-Droid/src/org/fdroid/fdroid/views/swap/ConfirmReceiveSwapFragment.java index 7daf35690..9f0401cf1 100644 --- a/F-Droid/src/org/fdroid/fdroid/views/swap/ConfirmReceiveSwapFragment.java +++ b/F-Droid/src/org/fdroid/fdroid/views/swap/ConfirmReceiveSwapFragment.java @@ -5,6 +5,7 @@ import android.content.ContentValues; import android.net.Uri; import android.os.Bundle; import android.support.annotation.NonNull; +import android.support.annotation.Nullable; import android.support.v4.app.Fragment; import android.util.Log; import android.view.LayoutInflater; @@ -24,6 +25,9 @@ public class ConfirmReceiveSwapFragment extends Fragment implements ProgressList private NewRepoConfig newRepoConfig; + @Nullable + private Repo repo; + @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { @@ -64,8 +68,8 @@ public class ConfirmReceiveSwapFragment extends Fragment implements ProgressList } private void confirm() { - Repo repo = ensureRepoExists(); - UpdateService.updateRepoNow(repo.address, getActivity()).setListener(this); + this.repo = ensureRepoExists(); + UpdateService.updateRepoNow(this.repo.address, getActivity()).setListener(this); } @NonNull @@ -104,7 +108,7 @@ public class ConfirmReceiveSwapFragment extends Fragment implements ProgressList if (event.type.equals(UpdateService.EVENT_COMPLETE_AND_SAME) || event.type.equals(UpdateService.EVENT_COMPLETE_WITH_CHANGES)) { - ((ConnectSwapActivity)getActivity()).onRepoUpdated(); + ((ConnectSwapActivity)getActivity()).onRepoUpdated(repo); /*Intent intent = new Intent(); intent.putExtra("category", newRepoConfig.getHost()); // TODO: Load repo from database to get proper name. This is what the category we want to select will be called. getActivity().setResult(Activity.RESULT_OK, intent); diff --git a/F-Droid/src/org/fdroid/fdroid/views/swap/ConnectSwapActivity.java b/F-Droid/src/org/fdroid/fdroid/views/swap/ConnectSwapActivity.java index 56231bef5..60f065ec7 100644 --- a/F-Droid/src/org/fdroid/fdroid/views/swap/ConnectSwapActivity.java +++ b/F-Droid/src/org/fdroid/fdroid/views/swap/ConnectSwapActivity.java @@ -5,10 +5,11 @@ import android.os.Bundle; import android.support.v4.app.FragmentActivity; import android.support.v4.app.FragmentManager; +import org.fdroid.fdroid.data.Repo; + public class ConnectSwapActivity extends FragmentActivity { private static final String STATE_CONFIRM = "startSwap"; - private static final String STATE_APP_LIST = "swapAppList"; @Override public void onCreate(Bundle savedInstanceState) { @@ -42,9 +43,10 @@ public class ConnectSwapActivity extends FragmentActivity { return lastFragment.getName(); } - public void onRepoUpdated() { + public void onRepoUpdated(Repo repo) { Intent intent = new Intent(this, SwapAppListActivity.class); + intent.putExtra(SwapAppListActivity.EXTRA_REPO_ADDRESS, repo.address); startActivity(intent); } diff --git a/F-Droid/src/org/fdroid/fdroid/views/swap/SwapAppListActivity.java b/F-Droid/src/org/fdroid/fdroid/views/swap/SwapAppListActivity.java index f45670508..fd1ed73a3 100644 --- a/F-Droid/src/org/fdroid/fdroid/views/swap/SwapAppListActivity.java +++ b/F-Droid/src/org/fdroid/fdroid/views/swap/SwapAppListActivity.java @@ -1,5 +1,6 @@ package org.fdroid.fdroid.views.swap; +import android.app.Activity; import android.net.Uri; import android.os.Bundle; import android.os.Handler; @@ -9,12 +10,18 @@ import android.support.v7.app.ActionBarActivity; import org.fdroid.fdroid.AppDetails; import org.fdroid.fdroid.R; import org.fdroid.fdroid.data.AppProvider; +import org.fdroid.fdroid.data.Repo; +import org.fdroid.fdroid.data.RepoProvider; import org.fdroid.fdroid.views.AppListAdapter; import org.fdroid.fdroid.views.AvailableAppListAdapter; import org.fdroid.fdroid.views.fragments.AppListFragment; public class SwapAppListActivity extends ActionBarActivity { + public static String EXTRA_REPO_ADDRESS = "repoAddress"; + + private Repo repo; + @Override public void onCreate(Bundle savedInstanceState) { @@ -36,8 +43,28 @@ public class SwapAppListActivity extends ActionBarActivity { } + @Override + protected void onResume() { + super.onResume(); + + String repoAddress = getIntent().getStringExtra(EXTRA_REPO_ADDRESS); + repo = RepoProvider.Helper.findByAddress(this, repoAddress); + } + + public Repo getRepo() { + return repo; + } + public static class SwapAppListFragment extends AppListFragment { + private Repo repo; + + @Override + public void onAttach(Activity activity) { + super.onAttach(activity); + repo = ((SwapAppListActivity)activity).getRepo(); + } + @Override protected int getHeaderLayout() { return R.layout.swap_success_header; @@ -61,7 +88,7 @@ public class SwapAppListActivity extends ActionBarActivity { @Override protected Uri getDataUri() { - return AppProvider.getCategoryUri("LocalRepo"); + return AppProvider.getRepoUri(repo); } }