From e6844a5f4fead85fd2d3bdf74b492052fd41076f Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Thu, 13 Apr 2017 20:49:18 +0200 Subject: [PATCH 1/5] do not override original description with nulls The original single language description gets stuck straight into App.description by Jackson. getLocalizedEntry() might return a null, in which case it was overriding the original description. This only overrides the original description if there is actually a localized description. --- app/src/main/java/org/fdroid/fdroid/data/App.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/org/fdroid/fdroid/data/App.java b/app/src/main/java/org/fdroid/fdroid/data/App.java index 236b3f9af..3afa786e1 100644 --- a/app/src/main/java/org/fdroid/fdroid/data/App.java +++ b/app/src/main/java/org/fdroid/fdroid/data/App.java @@ -397,7 +397,7 @@ public class App extends ValueObject implements Comparable, Parcelable { if (!TextUtils.isEmpty(value)) { summary = value; } - description = getLocalizedEntry(localized, localesToUse, "Description"); + value = getLocalizedEntry(localized, localesToUse, "Description"); if (!TextUtils.isEmpty(value)) { description = value; } From 3121a106e0ab0364d537d234c22872b8e98ce40f Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Thu, 13 Apr 2017 21:19:36 +0200 Subject: [PATCH 2/5] fix "DefaultLocale: Implied default locale in case conversion" The point here is to use the English work all lowercase, so make sure that the English lowercasing rules are always active, regardless of the system's locale. --- .../fdroid/fdroid/views/categories/CategoryController.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/org/fdroid/fdroid/views/categories/CategoryController.java b/app/src/main/java/org/fdroid/fdroid/views/categories/CategoryController.java index 50d02e3ee..60f4ac2e5 100644 --- a/app/src/main/java/org/fdroid/fdroid/views/categories/CategoryController.java +++ b/app/src/main/java/org/fdroid/fdroid/views/categories/CategoryController.java @@ -32,6 +32,7 @@ import org.fdroid.fdroid.data.Schema; import org.fdroid.fdroid.views.apps.AppListActivity; import org.fdroid.fdroid.views.apps.FeatureImage; +import java.util.Locale; import java.util.Random; public class CategoryController extends RecyclerView.ViewHolder implements LoaderManager.LoaderCallbacks { @@ -108,7 +109,7 @@ public class CategoryController extends RecyclerView.ViewHolder implements Loade private static int getCategoryResource(Context context, @NonNull String categoryName, String resourceType, boolean requiresLowerCaseId) { String suffix = categoryName.replace(" & ", "_").replace(" ", "_").replace("'", ""); if (requiresLowerCaseId) { - suffix = suffix.toLowerCase(); + suffix = suffix.toLowerCase(Locale.ENGLISH); } return context.getResources().getIdentifier("category_" + suffix, resourceType, context.getPackageName()); } @@ -121,7 +122,7 @@ public class CategoryController extends RecyclerView.ViewHolder implements Loade // Seed based on the categoryName, so that each time we try to choose a colour for the same // category it will look the same for each different user, and each different session. - Random random = new Random(categoryName.toLowerCase().hashCode()); + Random random = new Random(categoryName.toLowerCase(Locale.ENGLISH).hashCode()); float[] hsv = new float[3]; hsv[0] = random.nextFloat() * 360; From 8cb277e90d5b37607ea03d3b2760e19f26cc25b6 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Thu, 13 Apr 2017 21:21:23 +0200 Subject: [PATCH 3/5] AppDetails2: add missing paddingEnd to match paddingRight --- app/src/main/res/layout/app_details2_header.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/res/layout/app_details2_header.xml b/app/src/main/res/layout/app_details2_header.xml index b9d242400..965cc4a3b 100755 --- a/app/src/main/res/layout/app_details2_header.xml +++ b/app/src/main/res/layout/app_details2_header.xml @@ -33,6 +33,7 @@ android:layout_alignParentTop="true" android:paddingBottom="8dp" android:paddingRight="8dp" + android:paddingEnd="8dp" android:src="@drawable/ic_repo_app_default" /> Date: Thu, 13 Apr 2017 21:45:56 +0200 Subject: [PATCH 4/5] added Esperanto and Shqip back to the language chooser I added Esperanto because someone asked, and Shqip since it is not available in Android 5.1 and people who speak Shqip would be likely to open the language menu to switch away from English, then they'd see Shqip as an option. This still won't take effect until those languages are fully translated. closes #941 --- app/src/main/java/org/fdroid/fdroid/Languages.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/src/main/java/org/fdroid/fdroid/Languages.java b/app/src/main/java/org/fdroid/fdroid/Languages.java index 5891d9123..ed5c572e6 100644 --- a/app/src/main/java/org/fdroid/fdroid/Languages.java +++ b/app/src/main/java/org/fdroid/fdroid/Languages.java @@ -226,6 +226,7 @@ public final class Languages { new Locale("da"), new Locale("el"), new Locale("es"), + new Locale("eo"), new Locale("et"), new Locale("eu"), new Locale("fa"), @@ -267,6 +268,7 @@ public final class Languages { new Locale("sk"), new Locale("sl"), new Locale("sn"), + new Locale("sq"), new Locale("sr"), new Locale("sv"), new Locale("sw"), From 97fd3f0bad080f60443a091db69814f3ff6b0d41 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Fri, 14 Apr 2017 01:31:33 +0200 Subject: [PATCH 5/5] support "What's New" and "Video" fields from index-v1 fdroidserver currently only supports a single WhatsNew field that comes from the CurrentVersionCode of the app. Google Play and fastlane supply support a WhatsNew field per-release, but we don't use that data anywhere, and implementing that in the data structures would add a lot of complexity since Apk would then need to have its own "localized" section like App does. The "Video" field is just a URL pointing to a video. closes #910 --- .../main/java/org/fdroid/fdroid/data/App.java | 23 +++++++++++++++++-- .../java/org/fdroid/fdroid/data/DBHelper.java | 19 ++++++++++++++- .../java/org/fdroid/fdroid/data/Schema.java | 10 ++++---- .../views/AppDetailsRecyclerViewAdapter.java | 12 ++++------ .../fdroid/updater/IndexV1UpdaterTest.java | 1 + 5 files changed, 50 insertions(+), 15 deletions(-) diff --git a/app/src/main/java/org/fdroid/fdroid/data/App.java b/app/src/main/java/org/fdroid/fdroid/data/App.java index 3afa786e1..305ae9654 100644 --- a/app/src/main/java/org/fdroid/fdroid/data/App.java +++ b/app/src/main/java/org/fdroid/fdroid/data/App.java @@ -110,7 +110,10 @@ public class App extends ValueObject implements Comparable, Parcelable { public String description; - public String video; + /** + * A descriptive text for what has changed in this version. + */ + public String whatsNew; public String featureGraphic; public String promoGraphic; @@ -133,6 +136,8 @@ public class App extends ValueObject implements Comparable, Parcelable { public String sourceCode; + public String video; + public String changelog; public String donate; @@ -230,6 +235,9 @@ public class App extends ValueObject implements Comparable, Parcelable { case Cols.DESCRIPTION: description = cursor.getString(i); break; + case Cols.WHATSNEW: + whatsNew = cursor.getString(i); + break; case Cols.LICENSE: license = cursor.getString(i); break; @@ -248,6 +256,9 @@ public class App extends ValueObject implements Comparable, Parcelable { case Cols.SOURCE_CODE: sourceCode = cursor.getString(i); break; + case Cols.VIDEO: + video = cursor.getString(i); + break; case Cols.CHANGELOG: changelog = cursor.getString(i); break; @@ -387,8 +398,10 @@ public class App extends ValueObject implements Comparable, Parcelable { } } // if key starts with Upper case, its set by humans - // Name, Summary, Description existed before localization so their values can be set directly video = getLocalizedEntry(localized, localesToUse, "Video"); + whatsNew = getLocalizedEntry(localized, localesToUse, "WhatsNew"); + // Name, Summary, Description existed before localization so they shouldn't replace + // non-localized old data format with a null or blank string String value = getLocalizedEntry(localized, localesToUse, "Name"); if (!TextUtils.isEmpty(value)) { name = value; @@ -733,12 +746,14 @@ public class App extends ValueObject implements Comparable, Parcelable { values.put(Cols.ICON_URL, iconUrl); values.put(Cols.ICON_URL_LARGE, iconUrlLarge); values.put(Cols.DESCRIPTION, description); + values.put(Cols.WHATSNEW, whatsNew); values.put(Cols.LICENSE, license); values.put(Cols.AUTHOR_NAME, authorName); values.put(Cols.AUTHOR_EMAIL, authorEmail); values.put(Cols.WEBSITE, webSite); values.put(Cols.ISSUE_TRACKER, issueTracker); values.put(Cols.SOURCE_CODE, sourceCode); + values.put(Cols.VIDEO, video); values.put(Cols.CHANGELOG, changelog); values.put(Cols.DONATE, donate); values.put(Cols.BITCOIN, bitcoin); @@ -887,12 +902,14 @@ public class App extends ValueObject implements Comparable, Parcelable { dest.writeString(this.summary); dest.writeString(this.icon); dest.writeString(this.description); + dest.writeString(this.whatsNew); dest.writeString(this.license); dest.writeString(this.authorName); dest.writeString(this.authorEmail); dest.writeString(this.webSite); dest.writeString(this.issueTracker); dest.writeString(this.sourceCode); + dest.writeString(this.video); dest.writeString(this.changelog); dest.writeString(this.donate); dest.writeString(this.bitcoin); @@ -932,12 +949,14 @@ public class App extends ValueObject implements Comparable, Parcelable { this.summary = in.readString(); this.icon = in.readString(); this.description = in.readString(); + this.whatsNew = in.readString(); this.license = in.readString(); this.authorName = in.readString(); this.authorEmail = in.readString(); this.webSite = in.readString(); this.issueTracker = in.readString(); this.sourceCode = in.readString(); + this.video = in.readString(); this.changelog = in.readString(); this.donate = in.readString(); this.bitcoin = in.readString(); diff --git a/app/src/main/java/org/fdroid/fdroid/data/DBHelper.java b/app/src/main/java/org/fdroid/fdroid/data/DBHelper.java index 0dd87abb9..fad99be1e 100644 --- a/app/src/main/java/org/fdroid/fdroid/data/DBHelper.java +++ b/app/src/main/java/org/fdroid/fdroid/data/DBHelper.java @@ -119,12 +119,14 @@ class DBHelper extends SQLiteOpenHelper { + AppMetadataTable.Cols.SUMMARY + " text not null, " + AppMetadataTable.Cols.ICON + " text, " + AppMetadataTable.Cols.DESCRIPTION + " text not null, " + + AppMetadataTable.Cols.WHATSNEW + " text, " + AppMetadataTable.Cols.LICENSE + " text not null, " + AppMetadataTable.Cols.AUTHOR_NAME + " text, " + AppMetadataTable.Cols.AUTHOR_EMAIL + " text, " + AppMetadataTable.Cols.WEBSITE + " text, " + AppMetadataTable.Cols.ISSUE_TRACKER + " text, " + AppMetadataTable.Cols.SOURCE_CODE + " text, " + + AppMetadataTable.Cols.VIDEO + " string, " + AppMetadataTable.Cols.CHANGELOG + " text, " + AppMetadataTable.Cols.SUGGESTED_VERSION_CODE + " text," + AppMetadataTable.Cols.UPSTREAM_VERSION_NAME + " text," @@ -190,7 +192,7 @@ class DBHelper extends SQLiteOpenHelper { + InstalledAppTable.Cols.HASH + " TEXT NOT NULL" + " );"; - protected static final int DB_VERSION = 68; + protected static final int DB_VERSION = 69; private final Context context; @@ -273,6 +275,21 @@ class DBHelper extends SQLiteOpenHelper { addIndexV1Fields(db, oldVersion); addIndexV1AppFields(db, oldVersion); recalculatePreferredMetadata(db, oldVersion); + addWhatsNewAndVideo(db, oldVersion); + } + + private void addWhatsNewAndVideo(SQLiteDatabase db, int oldVersion) { + if (oldVersion >= 69) { + return; + } + if (!columnExists(db, AppMetadataTable.NAME, AppMetadataTable.Cols.WHATSNEW)) { + Utils.debugLog(TAG, "Adding " + AppMetadataTable.Cols.WHATSNEW + " field to " + AppMetadataTable.NAME + " table in db."); + db.execSQL("alter table " + AppMetadataTable.NAME + " add column " + AppMetadataTable.Cols.WHATSNEW + " text;"); + } + if (!columnExists(db, AppMetadataTable.NAME, AppMetadataTable.Cols.VIDEO)) { + Utils.debugLog(TAG, "Adding " + AppMetadataTable.Cols.VIDEO + " field to " + AppMetadataTable.NAME + " table in db."); + db.execSQL("alter table " + AppMetadataTable.NAME + " add column " + AppMetadataTable.Cols.VIDEO + " string;"); + } } private void recalculatePreferredMetadata(SQLiteDatabase db, int oldVersion) { diff --git a/app/src/main/java/org/fdroid/fdroid/data/Schema.java b/app/src/main/java/org/fdroid/fdroid/data/Schema.java index 73d26baec..7ae47d8c5 100644 --- a/app/src/main/java/org/fdroid/fdroid/data/Schema.java +++ b/app/src/main/java/org/fdroid/fdroid/data/Schema.java @@ -123,12 +123,14 @@ public interface Schema { String SUMMARY = "summary"; String ICON = "icon"; String DESCRIPTION = "description"; + String WHATSNEW = "whatsNew"; String LICENSE = "license"; String AUTHOR_NAME = "author"; String AUTHOR_EMAIL = "email"; String WEBSITE = "webURL"; String ISSUE_TRACKER = "trackerURL"; String SOURCE_CODE = "sourceURL"; + String VIDEO = "video"; String CHANGELOG = "changelogURL"; String DONATE = "donateURL"; String BITCOIN = "bitcoinAddr"; @@ -184,8 +186,8 @@ public interface Schema { */ String[] ALL_COLS = { ROW_ID, PACKAGE_ID, REPO_ID, IS_COMPATIBLE, NAME, SUMMARY, ICON, DESCRIPTION, - LICENSE, AUTHOR_NAME, AUTHOR_EMAIL, WEBSITE, ISSUE_TRACKER, SOURCE_CODE, - CHANGELOG, DONATE, BITCOIN, LITECOIN, FLATTR_ID, + WHATSNEW, LICENSE, AUTHOR_NAME, AUTHOR_EMAIL, WEBSITE, ISSUE_TRACKER, SOURCE_CODE, + VIDEO, CHANGELOG, DONATE, BITCOIN, LITECOIN, FLATTR_ID, UPSTREAM_VERSION_NAME, UPSTREAM_VERSION_CODE, ADDED, LAST_UPDATED, ANTI_FEATURES, REQUIREMENTS, ICON_URL, ICON_URL_LARGE, FEATURE_GRAPHIC, PROMO_GRAPHIC, TV_BANNER, PHONE_SCREENSHOTS, @@ -200,8 +202,8 @@ public interface Schema { */ String[] ALL = { _ID, ROW_ID, REPO_ID, IS_COMPATIBLE, NAME, SUMMARY, ICON, DESCRIPTION, - LICENSE, AUTHOR_NAME, AUTHOR_EMAIL, WEBSITE, ISSUE_TRACKER, SOURCE_CODE, - CHANGELOG, DONATE, BITCOIN, LITECOIN, FLATTR_ID, + WHATSNEW, LICENSE, AUTHOR_NAME, AUTHOR_EMAIL, WEBSITE, ISSUE_TRACKER, SOURCE_CODE, + VIDEO, CHANGELOG, DONATE, BITCOIN, LITECOIN, FLATTR_ID, UPSTREAM_VERSION_NAME, UPSTREAM_VERSION_CODE, ADDED, LAST_UPDATED, ANTI_FEATURES, REQUIREMENTS, ICON_URL, ICON_URL_LARGE, FEATURE_GRAPHIC, PROMO_GRAPHIC, TV_BANNER, PHONE_SCREENSHOTS, diff --git a/app/src/main/java/org/fdroid/fdroid/views/AppDetailsRecyclerViewAdapter.java b/app/src/main/java/org/fdroid/fdroid/views/AppDetailsRecyclerViewAdapter.java index 9e26721f8..d09b78e60 100644 --- a/app/src/main/java/org/fdroid/fdroid/views/AppDetailsRecyclerViewAdapter.java +++ b/app/src/main/java/org/fdroid/fdroid/views/AppDetailsRecyclerViewAdapter.java @@ -410,21 +410,17 @@ public class AppDetailsRecyclerViewAdapter lastUpdateView.setVisibility(View.GONE); } - Apk suggestedApk = getSuggestedApk(); - - // TODO populate whatsNew with suggestedApk.whatsNew once that exists - String whatsNew = null; - //noinspection ConstantConditions - if (suggestedApk == null || TextUtils.isEmpty(whatsNew)) { + if (TextUtils.isEmpty(app.whatsNew)) { whatsNewView.setVisibility(View.GONE); } else { //noinspection deprecation Ignore deprecation because the suggested way is only available in API 24. Locale locale = context.getResources().getConfiguration().locale; StringBuilder sbWhatsNew = new StringBuilder(); - sbWhatsNew.append(whatsNewView.getContext().getString(R.string.details_new_in_version, suggestedApk.versionName).toUpperCase(locale)); + sbWhatsNew.append(whatsNewView.getContext().getString(R.string.details_new_in_version, + getSuggestedApk().versionName).toUpperCase(locale)); sbWhatsNew.append("\n\n"); - sbWhatsNew.append(whatsNew); + sbWhatsNew.append(app.whatsNew); whatsNewView.setText(sbWhatsNew); whatsNewView.setVisibility(View.VISIBLE); } diff --git a/app/src/test/java/org/fdroid/fdroid/updater/IndexV1UpdaterTest.java b/app/src/test/java/org/fdroid/fdroid/updater/IndexV1UpdaterTest.java index 970f4ec84..e44ae40a0 100644 --- a/app/src/test/java/org/fdroid/fdroid/updater/IndexV1UpdaterTest.java +++ b/app/src/test/java/org/fdroid/fdroid/updater/IndexV1UpdaterTest.java @@ -251,6 +251,7 @@ public class IndexV1UpdaterTest extends FDroidProviderTest { "upstreamVersionCode", "upstreamVersionName", "video", + "whatsNew", "wearScreenshots", "webSite", };