diff --git a/TODO-before-release.md b/TODO-before-release.md index e635a2463..bcca63f4e 100644 --- a/TODO-before-release.md +++ b/TODO-before-release.md @@ -3,9 +3,3 @@ These issues are a must-fix before the next stable release: * Right after updating a repo, `Recently Updated` shows the apps correctly but the new apks don't show up on App Details until the whole app is restarted (or until the repos are wiped and re-downloaded) - -* `App.curVersion` is now used in some places where before we used - `App.curApk.version`, which means that e.g. app lists now show the current - version at upstream and not the latest stable version in the repository - (highly misleading to users, who might end up looking for versions not in - the repo yet) diff --git a/src/org/fdroid/fdroid/AppDetails.java b/src/org/fdroid/fdroid/AppDetails.java index 0cafa5e91..2e8f49867 100644 --- a/src/org/fdroid/fdroid/AppDetails.java +++ b/src/org/fdroid/fdroid/AppDetails.java @@ -128,7 +128,7 @@ public class AppDetails extends ListActivity { holder.version.setText(getString(R.string.version) + " " + apk.version - + (apk.vercode == app.curVercode ? " ☆" : "")); + + (apk.vercode == app.suggestedVercode ? " ☆" : "")); if (apk.vercode == app.getInstalledVerCode(getContext()) && mInstalledSigID != null && apk.sig != null @@ -534,7 +534,7 @@ public class AppDetails extends ListActivity { Apk curApk = null; for (int i = 0; i < adapter.getCount(); i ++) { Apk apk = adapter.getItem(i); - if (apk.vercode == app.curVercode) { + if (apk.vercode == app.suggestedVercode) { curApk = apk; break; } @@ -678,7 +678,7 @@ public class AppDetails extends ListActivity { } // Check count > 0 due to incompatible apps resulting in an empty list. - if (app.getInstalledVersion(this) == null && app.curVercode > 0 && + if (app.getInstalledVersion(this) == null && app.suggestedVercode > 0 && adapter.getCount() > 0) { MenuItemCompat.setShowAsAction(menu.add( Menu.NONE, INSTALL, 1, R.string.menu_install) @@ -716,7 +716,7 @@ public class AppDetails extends ListActivity { menu.add(Menu.NONE, IGNORETHIS, 2, R.string.menu_ignore_this) .setIcon(android.R.drawable.ic_menu_close_clear_cancel) .setCheckable(true) - .setChecked(app.ignoreThisUpdate >= app.curVercode); + .setChecked(app.ignoreThisUpdate >= app.suggestedVercode); } if (app.webURL.length() > 0) { menu.add(Menu.NONE, WEBSITE, 3, R.string.menu_website).setIcon( @@ -783,8 +783,8 @@ public class AppDetails extends ListActivity { case INSTALL: // Note that this handles updating as well as installing. - if (app.curVercode > 0) { - final Apk apkToInstall = ApkProvider.Helper.find(this, app.id, app.curVercode); + if (app.suggestedVercode > 0) { + final Apk apkToInstall = ApkProvider.Helper.find(this, app.id, app.suggestedVercode); install(apkToInstall); } return true; @@ -799,10 +799,10 @@ public class AppDetails extends ListActivity { return true; case IGNORETHIS: - if (app.ignoreThisUpdate >= app.curVercode) + if (app.ignoreThisUpdate >= app.suggestedVercode) app.ignoreThisUpdate = 0; else - app.ignoreThisUpdate = app.curVercode; + app.ignoreThisUpdate = app.suggestedVercode; item.setChecked(app.ignoreThisUpdate > 0); return true; diff --git a/src/org/fdroid/fdroid/RepoXMLHandler.java b/src/org/fdroid/fdroid/RepoXMLHandler.java index a123c70ed..1c7fb5009 100644 --- a/src/org/fdroid/fdroid/RepoXMLHandler.java +++ b/src/org/fdroid/fdroid/RepoXMLHandler.java @@ -226,12 +226,12 @@ public class RepoXMLHandler extends DefaultHandler { curapp.lastUpdated = null; } } else if (curel.equals("marketversion")) { - curapp.curVersion = str; + curapp.upstreamVersion = str; } else if (curel.equals("marketvercode")) { try { - curapp.curVercode = Integer.parseInt(str); + curapp.upstreamVercode = Integer.parseInt(str); } catch (NumberFormatException ex) { - curapp.curVercode = -1; + curapp.upstreamVercode = -1; } } else if (curel.equals("categories")) { curapp.categories = Utils.CommaSeparatedList.make(str); diff --git a/src/org/fdroid/fdroid/UpdateService.java b/src/org/fdroid/fdroid/UpdateService.java index dc3aa0711..bd53a2f36 100644 --- a/src/org/fdroid/fdroid/UpdateService.java +++ b/src/org/fdroid/fdroid/UpdateService.java @@ -400,19 +400,19 @@ public class UpdateService extends IntentService implements ProgressListener { private static void calcCurrentApkForApp(App app, List apksForApp) { Apk latestApk = null; // Try and return the real current version first. It will find the - // closest version smaller than the curVercode, being the same + // closest version smaller than the upstreamVercode, being the same // vercode if it exists. - if (app.curVercode > 0) { + if (app.upstreamVercode > 0) { int latestcode = -1; for (Apk apk : apksForApp) { if ((!app.compatible || apk.compatible) - && apk.vercode <= app.curVercode + && apk.vercode <= app.upstreamVercode && apk.vercode > latestcode) { latestApk = apk; latestcode = apk.vercode; } } - } else if (app.curVercode == -1) { + } else if (app.upstreamVercode == -1) { // If the current version was not set we return the most recent apk. int latestCode = -1; for (Apk apk : apksForApp) { @@ -425,8 +425,7 @@ public class UpdateService extends IntentService implements ProgressListener { } if (latestApk != null) { - app.curVercode = latestApk.vercode; - app.curVersion = latestApk.version; + app.suggestedVercode = latestApk.vercode; } } diff --git a/src/org/fdroid/fdroid/data/ApkProvider.java b/src/org/fdroid/fdroid/data/ApkProvider.java index 0d070653f..8216c3c86 100644 --- a/src/org/fdroid/fdroid/data/ApkProvider.java +++ b/src/org/fdroid/fdroid/data/ApkProvider.java @@ -221,15 +221,16 @@ public class ApkProvider extends FDroidProvider { return matcher; } - private static class QueryBuilder { - - private StringBuilder fields = new StringBuilder(); - private StringBuilder tables = new StringBuilder(DBHelper.TABLE_APK + " AS apk"); - private String selection = null; - private String orderBy = null; + private static class Query extends QueryBuilder { private boolean repoTableRequired = false; + @Override + protected String getRequiredTables() { + return DBHelper.TABLE_APK + " AS apk"; + } + + @Override public void addField(String field) { if (REPO_FIELDS.containsKey(field)) { addRepoField(REPO_FIELDS.get(field), field); @@ -242,63 +243,14 @@ public class ApkProvider extends FDroidProvider { } } - public void addRepoField(String field, String alias) { + private void addRepoField(String field, String alias) { if (!repoTableRequired) { repoTableRequired = true; - tables.append(" LEFT JOIN "); - tables.append(DBHelper.TABLE_REPO); - tables.append(" AS repo ON (apk.repo = repo._id) "); + leftJoin(DBHelper.TABLE_REPO, "repo", "apk.repo = repo._id"); } appendField(field, "repo", alias); } - private void appendField(String field) { - appendField(field, null, null); - } - - private void appendField(String field, String tableAlias) { - appendField(field, tableAlias, null); - } - - private void appendField(String field, String tableAlias, - String fieldAlias) { - if (fields.length() != 0) { - fields.append(','); - } - - if (tableAlias != null) { - fields.append(tableAlias).append('.'); - } - - fields.append(field); - - if (fieldAlias != null) { - fields.append(" AS ").append(fieldAlias); - } - } - - public void addSelection(String selection) { - this.selection = selection; - } - - public void addOrderBy(String orderBy) { - this.orderBy = orderBy; - } - - @Override - public String toString() { - - StringBuilder suffix = new StringBuilder(); - if (selection != null) { - suffix.append(" WHERE ").append(selection); - } - - if (orderBy != null) { - suffix.append(" ORDER BY ").append(orderBy); - } - - return "SELECT " + fields + " FROM " + tables + suffix; - } } private QuerySelection queryApp(String appId) { @@ -377,7 +329,7 @@ public class ApkProvider extends FDroidProvider { throw new UnsupportedOperationException("Invalid URI for apk content provider: " + uri); } - QueryBuilder queryBuilder = new QueryBuilder(); + Query queryBuilder = new Query(); for (String field : projection) { queryBuilder.addField(field); } diff --git a/src/org/fdroid/fdroid/data/App.java b/src/org/fdroid/fdroid/data/App.java index cec9b452f..30688b21a 100644 --- a/src/org/fdroid/fdroid/data/App.java +++ b/src/org/fdroid/fdroid/data/App.java @@ -41,8 +41,18 @@ public class App extends ValueObject implements Comparable { public String flattrID; - public String curVersion; - public int curVercode; + public String upstreamVersion; + public int upstreamVercode; + + /** + * Unlike other public fields, this is only accessible via a getter, to + * emphasise that setting it wont do anything. In order to change this, + * you need to change suggestedVercode to an apk which is in the apk table. + */ + private String suggestedVersion; + + public int suggestedVercode; + public Date added; public Date lastUpdated; @@ -114,10 +124,14 @@ public class App extends ValueObject implements Comparable { dogecoinAddr = cursor.getString(i); } else if (column.equals(AppProvider.DataColumns.FLATTR_ID)) { flattrID = cursor.getString(i); - } else if (column.equals(AppProvider.DataColumns.CURRENT_VERSION)) { - curVersion = cursor.getString(i); - } else if (column.equals(AppProvider.DataColumns.CURRENT_VERSION_CODE)) { - curVercode = cursor.getInt(i); + } else if (column.equals(AppProvider.DataColumns.SuggestedApk.VERSION)) { + suggestedVersion = cursor.getString(i); + } else if (column.equals(AppProvider.DataColumns.SUGGESTED_VERSION_CODE)) { + suggestedVercode = cursor.getInt(i); + } else if (column.equals(AppProvider.DataColumns.UPSTREAM_VERSION_CODE)) { + upstreamVercode = cursor.getInt(i); + } else if (column.equals(AppProvider.DataColumns.UPSTREAM_VERSION)) { + upstreamVersion = cursor.getString(i); } else if (column.equals(AppProvider.DataColumns.ADDED)) { added = ValueObject.toDate(cursor.getString(i)); } else if (column.equals(AppProvider.DataColumns.LAST_UPDATED)) { @@ -158,8 +172,9 @@ public class App extends ValueObject implements Comparable { values.put(AppProvider.DataColumns.FLATTR_ID, flattrID); values.put(AppProvider.DataColumns.ADDED, added == null ? "" : Utils.DATE_FORMAT.format(added)); values.put(AppProvider.DataColumns.LAST_UPDATED, added == null ? "" : Utils.DATE_FORMAT.format(lastUpdated)); - values.put(AppProvider.DataColumns.CURRENT_VERSION, curVersion); - values.put(AppProvider.DataColumns.CURRENT_VERSION_CODE, curVercode); + values.put(AppProvider.DataColumns.SUGGESTED_VERSION_CODE, suggestedVercode); + values.put(AppProvider.DataColumns.UPSTREAM_VERSION, upstreamVersion); + values.put(AppProvider.DataColumns.UPSTREAM_VERSION_CODE, upstreamVercode); values.put(AppProvider.DataColumns.CATEGORIES, Utils.CommaSeparatedList.str(categories)); values.put(AppProvider.DataColumns.ANTI_FEATURES, Utils.CommaSeparatedList.str(antiFeatures)); values.put(AppProvider.DataColumns.REQUIREMENTS, Utils.CommaSeparatedList.str(requirements)); @@ -207,9 +222,9 @@ public class App extends ValueObject implements Comparable { */ public boolean hasUpdates(Context context) { boolean updates = false; - if (curVercode > 0) { + if (suggestedVercode > 0) { int installedVerCode = getInstalledVerCode(context); - updates = (installedVerCode > 0 && installedVerCode < curVercode); + updates = (installedVerCode > 0 && installedVerCode < suggestedVercode); } return updates; } @@ -218,7 +233,7 @@ public class App extends ValueObject implements Comparable { // to be notified about them public boolean canAndWantToUpdate(Context context) { boolean canUpdate = hasUpdates(context); - boolean wantsUpdate = !ignoreAllUpdates && ignoreThisUpdate < curVercode; + boolean wantsUpdate = !ignoreAllUpdates && ignoreThisUpdate < suggestedVercode; return canUpdate && wantsUpdate && !isFiltered(); } @@ -227,4 +242,8 @@ public class App extends ValueObject implements Comparable { public boolean isFiltered() { return new AppFilter().filter(this); } + + public String getSuggestedVersion() { + return suggestedVersion; + } } diff --git a/src/org/fdroid/fdroid/data/AppProvider.java b/src/org/fdroid/fdroid/data/AppProvider.java index f404df0c0..9475cfb62 100644 --- a/src/org/fdroid/fdroid/data/AppProvider.java +++ b/src/org/fdroid/fdroid/data/AppProvider.java @@ -60,7 +60,7 @@ public class AppProvider extends FDroidProvider { public static List categories(Context context) { ContentResolver resolver = context.getContentResolver(); Uri uri = getContentUri(); - String[] projection = { "DISTINCT " + DataColumns.CATEGORIES }; + String[] projection = { DataColumns.CATEGORIES }; Cursor cursor = resolver.query(uri, projection, null, null, null ); Set categorySet = new HashSet(); if (cursor != null) { @@ -110,7 +110,7 @@ public class AppProvider extends FDroidProvider { public interface DataColumns { - public static final String _ID = "rowid as _id"; + public static final String _ID = "rowid as _id"; // Required for CursorLoaders public static final String _COUNT = "_count"; public static final String IS_COMPATIBLE = "compatible"; public static final String APP_ID = "id"; @@ -127,8 +127,9 @@ public class AppProvider extends FDroidProvider { public static final String LITECOIN_ADDR = "litecoinAddr"; public static final String DOGECOIN_ADDR = "dogecoinAddr"; public static final String FLATTR_ID = "flattrID"; - public static final String CURRENT_VERSION = "curVersion"; - public static final String CURRENT_VERSION_CODE = "curVercode"; + public static final String SUGGESTED_VERSION_CODE = "suggestedVercode"; + public static final String UPSTREAM_VERSION = "upstreamVersion"; + public static final String UPSTREAM_VERSION_CODE = "upstreamVercode"; public static final String CURRENT_APK = null; public static final String ADDED = "added"; public static final String LAST_UPDATED = "lastUpdated"; @@ -147,16 +148,73 @@ public class AppProvider extends FDroidProvider { public static final String UPDATED = null; public static final String APKS = null; + public interface SuggestedApk { + public static final String VERSION = "suggestedApkVersion"; + } + public static String[] ALL = { IS_COMPATIBLE, APP_ID, NAME, SUMMARY, ICON, DESCRIPTION, LICENSE, WEB_URL, TRACKER_URL, SOURCE_URL, DONATE_URL, BITCOIN_ADDR, LITECOIN_ADDR, DOGECOIN_ADDR, FLATTR_ID, - CURRENT_VERSION, CURRENT_VERSION_CODE, ADDED, LAST_UPDATED, + UPSTREAM_VERSION, UPSTREAM_VERSION_CODE, ADDED, LAST_UPDATED, CATEGORIES, ANTI_FEATURES, REQUIREMENTS, IGNORE_ALLUPDATES, - IGNORE_THISUPDATE, ICON_URL + IGNORE_THISUPDATE, ICON_URL, SUGGESTED_VERSION_CODE, + SuggestedApk.VERSION }; } + private static class Query extends QueryBuilder { + + private boolean isSuggestedApkTableAdded = false; + + private boolean categoryFieldAdded = false; + + @Override + protected String getRequiredTables() { + return DBHelper.TABLE_APP; + } + + @Override + protected boolean isDistinct() { + return fieldCount() == 1 && categoryFieldAdded; + } + + @Override + public void addField(String field) { + if (field.equals(DataColumns.SuggestedApk.VERSION)) { + addSuggestedApkVersionField(); + } else if (field.equals(DataColumns._COUNT)) { + appendCountField(); + } else { + if (field.equals(DataColumns.CATEGORIES)) { + categoryFieldAdded = true; + } + appendField(field, "fdroid_app"); + } + } + + private void appendCountField() { + appendField("COUNT(*) AS " + DataColumns._COUNT); + } + + private void addSuggestedApkVersionField() { + addSuggestedApkField( + ApkProvider.DataColumns.VERSION, + DataColumns.SuggestedApk.VERSION); + } + + private void addSuggestedApkField(String fieldName, String alias) { + if (!isSuggestedApkTableAdded) { + isSuggestedApkTableAdded = true; + leftJoin( + DBHelper.TABLE_APK, + "suggestedApk", + "fdroid_app.suggestedVercode = suggestedApk.vercode AND fdroid_app.id = suggestedApk.id"); + } + appendField(fieldName, "suggestedApk", alias); + } + } + private static final String PROVIDER_NAME = "AppProvider"; private static final UriMatcher matcher = new UriMatcher(-1); @@ -274,18 +332,18 @@ public class AppProvider extends FDroidProvider { private QuerySelection queryCanUpdate() { Map installedApps = Utils.getInstalledApps(getContext()); - String ignoreCurrent = " ignoreThisUpdate != curVercode "; - String ignoreAll = " ignoreAllUpdates != 1 "; + String ignoreCurrent = " fdroid_app.ignoreThisUpdate != fdroid_app.suggestedVercode "; + String ignoreAll = " fdroid_app.ignoreAllUpdates != 1 "; String ignore = " ( " + ignoreCurrent + " AND " + ignoreAll + " ) "; StringBuilder where = new StringBuilder( ignore + " AND ( 0 "); String[] selectionArgs = new String[installedApps.size() * 2]; int i = 0; for (PackageInfo info : installedApps.values() ) { - where.append(" OR ( ") - .append(AppProvider.DataColumns.APP_ID) - .append(" = ? AND ") - .append(DataColumns.CURRENT_VERSION_CODE) + where.append(" OR ( fdroid_app.") + .append(DataColumns.APP_ID) + .append(" = ? AND fdroid_app.") + .append(DataColumns.SUGGESTED_VERSION_CODE) .append(" > ?) "); selectionArgs[ i * 2 ] = info.packageName; selectionArgs[ i * 2 + 1 ] = Integer.toString(info.versionCode); @@ -302,7 +360,7 @@ public class AppProvider extends FDroidProvider { String[] selectionArgs = new String[installedApps.size()]; int i = 0; for (Map.Entry entry : installedApps.entrySet() ) { - where.append(" OR ") + where.append(" OR fdroid_app.") .append(AppProvider.DataColumns.APP_ID) .append(" = ? "); selectionArgs[i] = entry.getKey(); @@ -316,27 +374,29 @@ public class AppProvider extends FDroidProvider { private QuerySelection querySearch(String keywords) { keywords = "%" + keywords + "%"; String selection = - "id like ? OR " + - "name like ? OR " + - "summary like ? OR " + - "description like ? "; + "fdroid_app.id like ? OR " + + "fdroid_app.name like ? OR " + + "fdroid_app.summary like ? OR " + + "fdroid_app.description like ? "; String[] args = new String[] { keywords, keywords, keywords, keywords}; return new QuerySelection(selection, args); } + private QuerySelection querySingle(String id) { + String selection = "fdroid_app.id = ?"; + String[] args = { id }; + return new QuerySelection(selection, args); + } + private QuerySelection queryNewlyAdded() { - String selection = "added > ?"; - String[] args = new String[] { - Utils.DATE_FORMAT.format(Preferences.get().calcMaxHistory()) - }; + String selection = "fdroid_app.added > ?"; + String[] args = { Utils.DATE_FORMAT.format(Preferences.get().calcMaxHistory()) }; return new QuerySelection(selection, args); } private QuerySelection queryRecentlyUpdated() { - String selection = "added != lastUpdated AND lastUpdated > ?"; - String[] args = new String[] { - Utils.DATE_FORMAT.format(Preferences.get().calcMaxHistory()) - }; + String selection = "fdroid_app.added != fdroid_app.lastUpdated AND fdroid_app.lastUpdated > ?"; + String[] args = { Utils.DATE_FORMAT.format(Preferences.get().calcMaxHistory()) }; return new QuerySelection(selection, args); } @@ -344,11 +404,11 @@ public class AppProvider extends FDroidProvider { // TODO: In the future, add a new table for categories, // so we can join onto it. String selection = - " categories = ? OR " + // Only category e.g. "internet" - " categories LIKE ? OR " + // First category e.g. "internet,%" - " categories LIKE ? OR " + // Last category e.g. "%,internet" - " categories LIKE ? "; // One of many categories e.g. "%,internet,%" - String[] args = new String[] { + " fdroid_app.categories = ? OR " + // Only category e.g. "internet" + " fdroid_app.categories LIKE ? OR " + // First category e.g. "internet,%" + " fdroid_app.categories LIKE ? OR " + // Last category e.g. "%,internet" + " fdroid_app.categories LIKE ? "; // One of many categories e.g. "%,internet,%" + String[] args = { category, category + ",%", "%," + category, @@ -364,7 +424,7 @@ public class AppProvider extends FDroidProvider { private QuerySelection queryApps(String appIds) { String[] args = appIds.split(","); - String selection = "id IN (" + generateQuestionMarksForInClause(args.length) + ")"; + String selection = "fdroid_app.id IN (" + generateQuestionMarksForInClause(args.length) + ")"; return new QuerySelection(selection, args); } @@ -376,9 +436,7 @@ public class AppProvider extends FDroidProvider { break; case CODE_SINGLE: - query = query.add( - DataColumns.APP_ID + " = ?", - new String[] { uri.getLastPathSegment() } ); + query = query.add(querySingle(uri.getLastPathSegment())); break; case CAN_UPDATE: @@ -406,12 +464,12 @@ public class AppProvider extends FDroidProvider { break; case RECENTLY_UPDATED: - sortOrder = DataColumns.LAST_UPDATED + " DESC"; + sortOrder = " fdroid_app.lastUpdated DESC"; query = query.add(queryRecentlyUpdated()); break; case NEWLY_ADDED: - sortOrder = DataColumns.ADDED + " DESC"; + sortOrder = " fdroid_app.added DESC"; query = query.add(queryNewlyAdded()); break; @@ -421,18 +479,15 @@ public class AppProvider extends FDroidProvider { } if (AppProvider.DataColumns.NAME.equals(sortOrder)) { - sortOrder = " lower( " + sortOrder + " ) "; + sortOrder = " lower( fdroid_app." + sortOrder + " ) "; } - for (String field : projection) { - if (field.equals(DataColumns._COUNT)) { - projection = new String[] { "COUNT(*) AS " + DataColumns._COUNT }; - break; - } - } + Query q = new Query(); + q.addFields(projection); + q.addSelection(query.getSelection()); + q.addOrderBy(sortOrder); - Cursor cursor = read().query(getTableName(), projection, query.getSelection(), - query.getArgs(), null, null, sortOrder); + Cursor cursor = read().rawQuery(q.toString(), query.getArgs()); cursor.setNotificationUri(getContext().getContentResolver(), uri); return cursor; } @@ -472,7 +527,7 @@ public class AppProvider extends FDroidProvider { switch (matcher.match(uri)) { case CODE_SINGLE: - query = query.add(new QuerySelection("id = ?", new String[] { uri.getLastPathSegment()})); + query = query.add(querySingle(uri.getLastPathSegment())); break; default: diff --git a/src/org/fdroid/fdroid/data/DBHelper.java b/src/org/fdroid/fdroid/data/DBHelper.java index 2a531362f..43a435efd 100644 --- a/src/org/fdroid/fdroid/data/DBHelper.java +++ b/src/org/fdroid/fdroid/data/DBHelper.java @@ -67,8 +67,9 @@ public class DBHelper extends SQLiteOpenHelper { + "webURL text, " + "trackerURL text, " + "sourceURL text, " - + "curVersion text," - + "curVercode integer," + + "suggestedVercode text," + + "upstreamVersion text," + + "upstreamVercode integer," + "antiFeatures string," + "donateURL string," + "bitcoinAddr string," @@ -85,7 +86,7 @@ public class DBHelper extends SQLiteOpenHelper { + "iconUrl text, " + "primary key(id));"; - private static final int DB_VERSION = 40; + private static final int DB_VERSION = 41; private Context context; diff --git a/src/org/fdroid/fdroid/data/QueryBuilder.java b/src/org/fdroid/fdroid/data/QueryBuilder.java new file mode 100644 index 000000000..6c988efc0 --- /dev/null +++ b/src/org/fdroid/fdroid/data/QueryBuilder.java @@ -0,0 +1,105 @@ +package org.fdroid.fdroid.data; + +import java.util.ArrayList; +import java.util.List; + +abstract class QueryBuilder { + + private List fields = new ArrayList(); + private StringBuilder tables = new StringBuilder(getRequiredTables()); + private String selection = null; + private String orderBy = null; + + protected abstract String getRequiredTables(); + + public abstract void addField(String field); + + protected int fieldCount() { + return fields.size(); + } + + public void addFields(String[] fields) { + for (String field : fields) { + addField(field); + } + } + + protected boolean isDistinct() { + return false; + } + + protected void appendField(String field) { + appendField(field, null, null); + } + + protected void appendField(String field, String tableAlias) { + appendField(field, tableAlias, null); + } + + protected final void appendField(String field, String tableAlias, + String fieldAlias) { + + StringBuilder fieldBuilder = new StringBuilder(); + + if (tableAlias != null) { + fieldBuilder.append(tableAlias).append('.'); + } + + fieldBuilder.append(field); + + if (fieldAlias != null) { + fieldBuilder.append(" AS ").append(fieldAlias); + } + + fields.add(fieldBuilder.toString()); + } + + public void addSelection(String selection) { + this.selection = selection; + } + + public void addOrderBy(String orderBy) { + this.orderBy = orderBy; + } + + protected final void leftJoin(String table, String alias, + String condition) { + tables.append(" LEFT JOIN "); + tables.append(table); + if (alias != null) { + tables.append(" AS "); + tables.append(alias); + } + tables.append(" ON ("); + tables.append(condition); + tables.append(")"); + } + + private String fieldsSql() { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < fields.size(); i ++) { + if (i > 0) { + sb.append(','); + } + sb.append(fields.get(i)); + } + return sb.toString(); + } + + private String whereSql() { + return selection != null ? " WHERE " + selection : ""; + } + + private String orderBySql() { + return orderBy != null ? " ORDER BY " + orderBy : ""; + } + + private String tablesSql() { + return tables.toString(); + } + + public String toString() { + String distinct = isDistinct() ? " DISTINCT " : ""; + return "SELECT " + distinct + fieldsSql() + " FROM " + tablesSql() + whereSql() + orderBySql(); + } +} diff --git a/src/org/fdroid/fdroid/views/AppListAdapter.java b/src/org/fdroid/fdroid/views/AppListAdapter.java index 5659283fd..ca0336d87 100644 --- a/src/org/fdroid/fdroid/views/AppListAdapter.java +++ b/src/org/fdroid/fdroid/views/AppListAdapter.java @@ -130,14 +130,14 @@ abstract public class AppListAdapter extends CursorAdapter { private String getVersionInfo(App app) { - if (app.curVercode <= 0) { + if (app.suggestedVercode <= 0) { return null; } PackageInfo installedInfo = app.getInstalledInfo(mContext); if (installedInfo == null) { - return ellipsize(app.curVersion, 12); + return ellipsize(app.getSuggestedVersion(), 12); } String installedVersionString = installedInfo.versionName; @@ -145,7 +145,7 @@ abstract public class AppListAdapter extends CursorAdapter { if (app.canAndWantToUpdate(mContext) && showStatusUpdate()) { return ellipsize(installedVersionString, 8) + - " → " + ellipsize(app.curVersion, 8); + " → " + ellipsize(app.getSuggestedVersion(), 8); } if (installedVersionCode > 0 && showStatusInstalled()) { diff --git a/src/org/fdroid/fdroid/views/fragments/AppListFragment.java b/src/org/fdroid/fdroid/views/fragments/AppListFragment.java index 3ad2c08a3..b3f2a91a4 100644 --- a/src/org/fdroid/fdroid/views/fragments/AppListFragment.java +++ b/src/org/fdroid/fdroid/views/fragments/AppListFragment.java @@ -27,7 +27,7 @@ abstract public class AppListFragment extends ListFragment implements LoaderManager.LoaderCallbacks { public static final String[] APP_PROJECTION = { - AppProvider.DataColumns._ID, + AppProvider.DataColumns._ID, // Required for cursor loader to work. AppProvider.DataColumns.APP_ID, AppProvider.DataColumns.NAME, AppProvider.DataColumns.SUMMARY, @@ -35,8 +35,8 @@ abstract public class AppListFragment extends ListFragment implements AppProvider.DataColumns.LICENSE, AppProvider.DataColumns.ICON, AppProvider.DataColumns.ICON_URL, - AppProvider.DataColumns.CURRENT_VERSION, - AppProvider.DataColumns.CURRENT_VERSION_CODE, + AppProvider.DataColumns.SuggestedApk.VERSION, + AppProvider.DataColumns.SUGGESTED_VERSION_CODE, AppProvider.DataColumns.REQUIREMENTS, // Needed for filtering apps that require root. };