From 58e48399d54616937d90ea0fad91553e2f20c85e Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Mon, 22 Apr 2013 16:14:28 -0700 Subject: [PATCH 01/19] Work in progress: Category class and content provider for recently-used categories list --- .../wikimedia/commons/category/Category.java | 151 ++++++++++++++++ .../category/CategoryContentProvider.java | 170 ++++++++++++++++++ 2 files changed, 321 insertions(+) create mode 100644 commons/src/main/java/org/wikimedia/commons/category/Category.java create mode 100644 commons/src/main/java/org/wikimedia/commons/category/CategoryContentProvider.java diff --git a/commons/src/main/java/org/wikimedia/commons/category/Category.java b/commons/src/main/java/org/wikimedia/commons/category/Category.java new file mode 100644 index 000000000..1e787ef6c --- /dev/null +++ b/commons/src/main/java/org/wikimedia/commons/category/Category.java @@ -0,0 +1,151 @@ +package org.wikimedia.commons.category; + +import android.content.ContentProviderClient; +import android.content.ContentValues; +import android.database.Cursor; +import android.database.sqlite.SQLiteDatabase; +import android.net.Uri; +import android.os.Parcel; +import android.os.Parcelable; +import android.os.RemoteException; +import android.text.TextUtils; +import org.wikimedia.commons.contributions.ContributionsContentProvider; + +import java.util.Date; + +/** + * Created with IntelliJ IDEA. + * User: brion + * Date: 4/22/13 + * Time: 3:37 PM + * To change this template use File | Settings | File Templates. + */ +public class Category /*implements Parcelable */{ + private ContentProviderClient client; + private Uri contentUri; + + private String name; + private Date lastUsed; + private int timesUsed; + + /* + // Do we need parcelable stuff? + @Override + public void writeToParcel(Parcel parcel, int flags) { + parcel.writeString(name); + parcel.writeSerializable(lastUsed); + parcel.writeInt(timesUsed); + } + + public Category(Parcel in) { + name = in.readString(); + lastUsed = (Date)in.readSerializable(); + timesUsed = in.readInt(); + } + + public int describeContents() { + return 0; + } + */ + + // Getters/setters + public String getName() { + return name; + } + + public void setName(String name_) { + name = name_; + } + + public Date getLastUsed() { + // warning: Date objects are mutable. + return (Date)lastUsed.clone(); + } + + public void setLastUsed(Date lastUsed_) { + // warning: Date objects are mutable. + lastUsed = (Date)lastUsed_.clone(); + } + + public int getTimesUsed() { + return timesUsed; + } + + public void setTimesUsed(int timesUsed_) { + timesUsed = timesUsed_; + } + + public void incTimesUsed() { + timesUsed++; + } + + // Database/content-provider stuff + public void setContentProviderClient(ContentProviderClient client) { + this.client = client; + } + + public void save() { + try { + if(contentUri == null) { + contentUri = client.insert(CategoryContentProvider.BASE_URI, this.toContentValues()); + } else { + client.update(contentUri, toContentValues(), null, null); + } + } catch(RemoteException e) { + throw new RuntimeException(e); + } + } + + public ContentValues toContentValues() { + ContentValues cv = new ContentValues(); + cv.put(Table.COLUMN_NAME, getName()); + cv.put(Table.COLUMN_LAST_USED, getLastUsed().getTime()); + cv.put(Table.COLUMN_TIMES_USED, getTimesUsed()); + return cv; + } + + public static Category fromCursor(Cursor cursor) { + // Hardcoding column positions! + Category c = new Category(); + c.name = cursor.getString(0); + c.lastUsed = new Date(cursor.getLong(1)); + c.timesUsed = cursor.getInt(2); + return c; + } + + public static class Table { + public static final String TABLE_NAME = "categories"; + + public static final String COLUMN_ID = "_id"; + public static final String COLUMN_NAME = "name"; + public static final String COLUMN_LAST_USED = "last_used"; + public static final String COLUMN_TIMES_USED = "times_used"; + + // NOTE! KEEP IN SAME ORDER AS THEY ARE DEFINED UP THERE. HELPS HARD CODE COLUMN INDICES. + public static final String[] ALL_FIELDS = { + COLUMN_ID, + COLUMN_NAME, + COLUMN_LAST_USED, + COLUMN_TIMES_USED + }; + + + private static final String CREATE_TABLE_STATEMENT = "CREATE TABLE " + TABLE_NAME + " (" + + COLUMN_ID + " INTEGER PRIMARY KEY," + + COLUMN_NAME + " STRING," + + COLUMN_LAST_USED + " INTEGER," // Will this roll over in 2038? :) + + COLUMN_TIMES_USED + " INTEGER" + + ");"; + + + public static void onCreate(SQLiteDatabase db) { + db.execSQL(CREATE_TABLE_STATEMENT); + } + + public static void onUpdate(SQLiteDatabase db, int from, int to) { + if(from == to) { + return; + } + } + } +} diff --git a/commons/src/main/java/org/wikimedia/commons/category/CategoryContentProvider.java b/commons/src/main/java/org/wikimedia/commons/category/CategoryContentProvider.java new file mode 100644 index 000000000..0276b29ca --- /dev/null +++ b/commons/src/main/java/org/wikimedia/commons/category/CategoryContentProvider.java @@ -0,0 +1,170 @@ +package org.wikimedia.commons.category; + +import android.content.ContentProvider; +import android.content.ContentValues; +import android.content.UriMatcher; +import android.database.Cursor; +import android.database.sqlite.SQLiteDatabase; +import android.database.sqlite.SQLiteQueryBuilder; +import android.net.Uri; +import android.text.TextUtils; +import android.util.Log; +import org.wikimedia.commons.CommonsApplication; +import org.wikimedia.commons.data.DBOpenHelper; + +/** + * Created with IntelliJ IDEA. + * User: brion + * Date: 4/22/13 + * Time: 4:09 PM + * To change this template use File | Settings | File Templates. + */ +public class CategoryContentProvider extends ContentProvider { + + // ???? + private static final int CATEGORIES = 1; + private static final int CATEGORIES_ID = 2; + + public static final String AUTHORITY = "org.wikimedia.commons.categories.contentprovider"; + private static final String BASE_PATH = "categories"; + + public static final Uri BASE_URI = Uri.parse("content://" + AUTHORITY + "/" + BASE_PATH); + + private static final UriMatcher uriMatcher = new UriMatcher(UriMatcher.NO_MATCH); + static { + uriMatcher.addURI(AUTHORITY, BASE_PATH, CATEGORIES); + uriMatcher.addURI(AUTHORITY, BASE_PATH + "/#", CATEGORIES_ID); + } + + + public static Uri uriForId(int id) { + return Uri.parse(BASE_URI.toString() + "/" + id); + } + + private DBOpenHelper dbOpenHelper; + @Override + public boolean onCreate() { + dbOpenHelper = ((CommonsApplication)this.getContext().getApplicationContext()).getDbOpenHelper(); + return false; + } + + @Override + public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { + SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder(); + queryBuilder.setTables(Category.Table.TABLE_NAME); + + int uriType = uriMatcher.match(uri); + + SQLiteDatabase db = dbOpenHelper.getReadableDatabase(); + Cursor cursor; + + switch(uriType) { + case CATEGORIES: + cursor = queryBuilder.query(db, projection, selection, selectionArgs, null, null, sortOrder); + break; + case CATEGORIES_ID: + cursor = queryBuilder.query(db, + Category.Table.ALL_FIELDS, + "_id = ?", + new String[] { uri.getLastPathSegment() }, + null, + null, + sortOrder + ); + break; + default: + throw new IllegalArgumentException("Unknown URI" + uri); + } + + cursor.setNotificationUri(getContext().getContentResolver(), uri); + + return cursor; + } + + @Override + public String getType(Uri uri) { + return null; + } + + @Override + public Uri insert(Uri uri, ContentValues contentValues) { + int uriType = uriMatcher.match(uri); + SQLiteDatabase sqlDB = dbOpenHelper.getWritableDatabase(); + long id = 0; + switch (uriType) { + case CATEGORIES: + id = sqlDB.insert(Category.Table.TABLE_NAME, null, contentValues); + break; + default: + throw new IllegalArgumentException("Unknown URI: " + uri); + } + getContext().getContentResolver().notifyChange(uri, null); + return Uri.parse(BASE_URI + "/" + id); + } + + @Override + public int delete(Uri uri, String s, String[] strings) { + return 0; + } + + @Override + public int bulkInsert(Uri uri, ContentValues[] values) { + Log.d("Commons", "Hello, bulk insert!"); + int uriType = uriMatcher.match(uri); + SQLiteDatabase sqlDB = dbOpenHelper.getWritableDatabase(); + sqlDB.beginTransaction(); + switch (uriType) { + case CATEGORIES: + for(ContentValues value: values) { + Log.d("Commons", "Inserting! " + value.toString()); + sqlDB.insert(Category.Table.TABLE_NAME, null, value); + } + break; + default: + throw new IllegalArgumentException("Unknown URI: " + uri); + } + sqlDB.setTransactionSuccessful(); + sqlDB.endTransaction(); + getContext().getContentResolver().notifyChange(uri, null); + return values.length; + } + + @Override + public int update(Uri uri, ContentValues contentValues, String selection, String[] selectionArgs) { + /* + SQL Injection warnings: First, note that we're not exposing this to the outside world (exported="false") + Even then, we should make sure to sanitize all user input appropriately. Input that passes through ContentValues + should be fine. So only issues are those that pass in via concating. + + In here, the only concat created argument is for id. It is cast to an int, and will error out otherwise. + */ + int uriType = uriMatcher.match(uri); + SQLiteDatabase sqlDB = dbOpenHelper.getWritableDatabase(); + int rowsUpdated = 0; + switch (uriType) { + case CATEGORIES: + rowsUpdated = sqlDB.update(Category.Table.TABLE_NAME, + contentValues, + selection, + selectionArgs); + break; + case CATEGORIES_ID: + int id = Integer.valueOf(uri.getLastPathSegment()); + + if (TextUtils.isEmpty(selection)) { + rowsUpdated = sqlDB.update(Category.Table.TABLE_NAME, + contentValues, + Category.Table.COLUMN_ID + " = ?", + new String[] { String.valueOf(id) } ); + } else { + throw new IllegalArgumentException("Parameter `selection` should be empty when updating an ID"); + } + break; + default: + throw new IllegalArgumentException("Unknown URI: " + uri + " with type " + uriType); + } + getContext().getContentResolver().notifyChange(uri, null); + return rowsUpdated; + } +} + From 0e23531f59a2142988fbc6af0e2d44dfe0e91663 Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Mon, 22 Apr 2013 16:29:28 -0700 Subject: [PATCH 02/19] Tweak column order...? --- .../main/java/org/wikimedia/commons/category/Category.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/commons/src/main/java/org/wikimedia/commons/category/Category.java b/commons/src/main/java/org/wikimedia/commons/category/Category.java index 1e787ef6c..b1fce6424 100644 --- a/commons/src/main/java/org/wikimedia/commons/category/Category.java +++ b/commons/src/main/java/org/wikimedia/commons/category/Category.java @@ -107,9 +107,10 @@ public class Category /*implements Parcelable */{ public static Category fromCursor(Cursor cursor) { // Hardcoding column positions! Category c = new Category(); - c.name = cursor.getString(0); - c.lastUsed = new Date(cursor.getLong(1)); - c.timesUsed = cursor.getInt(2); + c.contentUri = ContributionsContentProvider.uriForId(cursor.getInt(0)); + c.name = cursor.getString(1); + c.lastUsed = new Date(cursor.getLong(2)); + c.timesUsed = cursor.getInt(3); return c; } From fd1de3cdd87cbf10fe9f3de56cacb326b542ba47 Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Mon, 22 Apr 2013 16:51:29 -0700 Subject: [PATCH 03/19] Stub adapter for the recent cats view... --- .../commons/CategorizationFragment.java | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/commons/src/main/java/org/wikimedia/commons/CategorizationFragment.java b/commons/src/main/java/org/wikimedia/commons/CategorizationFragment.java index 5e02701bb..b88c77809 100644 --- a/commons/src/main/java/org/wikimedia/commons/CategorizationFragment.java +++ b/commons/src/main/java/org/wikimedia/commons/CategorizationFragment.java @@ -2,6 +2,7 @@ package org.wikimedia.commons; import android.app.Activity; import android.content.Context; +import android.database.Cursor; import android.os.AsyncTask; import android.os.Bundle; import android.os.Parcel; @@ -18,6 +19,8 @@ import com.actionbarsherlock.view.Menu; import com.actionbarsherlock.view.MenuItem; import org.mediawiki.api.ApiResult; import org.mediawiki.api.MWApi; +import org.wikimedia.commons.category.Category; +import org.wikimedia.commons.contributions.Contribution; import java.io.IOException; import java.io.Serializable; @@ -201,6 +204,30 @@ public class CategorizationFragment extends SherlockFragment{ } } + private class RecentCategoriesAdapter extends CursorAdapter { + + public RecentCategoriesAdapter(Context context, Cursor c, int flags) { + super(context, c, flags); + } + + @Override + public View newView(Context context, Cursor cursor, ViewGroup viewGroup) { + return getSherlockActivity().getLayoutInflater().inflate(R.layout.layout_categories_item, null); + } + + @Override + public void bindView(View view, Context context, Cursor cursor) { + CheckedTextView checkedView; + + Category category = Category.fromCursor(cursor); + checkedView = (CheckedTextView) view; + + checkedView.setChecked(false); + checkedView.setText(category.getName()); + checkedView.setTag(category.getName()); + } + } + public int getCurrentSelectedCount() { int count = 0; for(CategoryItem item: categoriesAdapter.getItems()) { From a9b431cde015cafc3e1e7d2cd2778a46c9eb02d8 Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Tue, 23 Apr 2013 06:57:09 -0700 Subject: [PATCH 04/19] Add XML/manifest bits for internal category content provider --- commons/AndroidManifest.xml | 7 +++++++ commons/res/values/strings.xml | 1 + 2 files changed, 8 insertions(+) diff --git a/commons/AndroidManifest.xml b/commons/AndroidManifest.xml index c6317582c..c6b93aacc 100644 --- a/commons/AndroidManifest.xml +++ b/commons/AndroidManifest.xml @@ -130,6 +130,13 @@ android:authorities="org.wikimedia.commons.modifications.contentprovider" android:exported="false"> + + diff --git a/commons/res/values/strings.xml b/commons/res/values/strings.xml index db693cd1b..91ab3261d 100644 --- a/commons/res/values/strings.xml +++ b/commons/res/values/strings.xml @@ -80,4 +80,5 @@ Privacy policy About Send Feedback (via Email) + Recently used categories From d8942680565dc1500636b3aa6b27e14288cc1d1e Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Tue, 23 Apr 2013 07:00:17 -0700 Subject: [PATCH 05/19] Drop Parcelable interface, not needed --- .../wikimedia/commons/category/Category.java | 22 +------------------ 1 file changed, 1 insertion(+), 21 deletions(-) diff --git a/commons/src/main/java/org/wikimedia/commons/category/Category.java b/commons/src/main/java/org/wikimedia/commons/category/Category.java index b1fce6424..f7ff437ed 100644 --- a/commons/src/main/java/org/wikimedia/commons/category/Category.java +++ b/commons/src/main/java/org/wikimedia/commons/category/Category.java @@ -20,7 +20,7 @@ import java.util.Date; * Time: 3:37 PM * To change this template use File | Settings | File Templates. */ -public class Category /*implements Parcelable */{ +public class Category { private ContentProviderClient client; private Uri contentUri; @@ -28,26 +28,6 @@ public class Category /*implements Parcelable */{ private Date lastUsed; private int timesUsed; - /* - // Do we need parcelable stuff? - @Override - public void writeToParcel(Parcel parcel, int flags) { - parcel.writeString(name); - parcel.writeSerializable(lastUsed); - parcel.writeInt(timesUsed); - } - - public Category(Parcel in) { - name = in.readString(); - lastUsed = (Date)in.readSerializable(); - timesUsed = in.readInt(); - } - - public int describeContents() { - return 0; - } - */ - // Getters/setters public String getName() { return name; From 8d67c5c2d5b62e7b7914244699851365dba3123c Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Tue, 23 Apr 2013 07:31:46 -0700 Subject: [PATCH 06/19] Initial stab at pulling cats from content provider We don't put anything in the provider yet though. :) --- .../commons/CategorizationFragment.java | 41 ++++++++----------- 1 file changed, 16 insertions(+), 25 deletions(-) diff --git a/commons/src/main/java/org/wikimedia/commons/CategorizationFragment.java b/commons/src/main/java/org/wikimedia/commons/CategorizationFragment.java index b88c77809..723dbe4ab 100644 --- a/commons/src/main/java/org/wikimedia/commons/CategorizationFragment.java +++ b/commons/src/main/java/org/wikimedia/commons/CategorizationFragment.java @@ -20,6 +20,7 @@ import com.actionbarsherlock.view.MenuItem; import org.mediawiki.api.ApiResult; import org.mediawiki.api.MWApi; import org.wikimedia.commons.category.Category; +import org.wikimedia.commons.category.CategoryContentProvider; import org.wikimedia.commons.contributions.Contribution; import java.io.IOException; @@ -126,7 +127,20 @@ public class CategorizationFragment extends SherlockFragment{ @Override protected ArrayList doInBackground(Void... voids) { if(TextUtils.isEmpty(filter)) { - return new ArrayList(); + ArrayList items = new ArrayList(); + // fixme add a limit? + // fixme sort by last_used descending? + Cursor cursor = getActivity().getContentResolver().query( + CategoryContentProvider.BASE_URI, + Category.Table.ALL_FIELDS, + null, + new String[] {}, + null); + while (cursor.moveToNext()) { + Category cat = Category.fromCursor(cursor); + items.add(cat.getName()); + } + return items; } if(categoriesCache.containsKey(filter)) { return categoriesCache.get(filter); @@ -204,30 +218,6 @@ public class CategorizationFragment extends SherlockFragment{ } } - private class RecentCategoriesAdapter extends CursorAdapter { - - public RecentCategoriesAdapter(Context context, Cursor c, int flags) { - super(context, c, flags); - } - - @Override - public View newView(Context context, Cursor cursor, ViewGroup viewGroup) { - return getSherlockActivity().getLayoutInflater().inflate(R.layout.layout_categories_item, null); - } - - @Override - public void bindView(View view, Context context, Cursor cursor) { - CheckedTextView checkedView; - - Category category = Category.fromCursor(cursor); - checkedView = (CheckedTextView) view; - - checkedView.setChecked(false); - checkedView.setText(category.getName()); - checkedView.setTag(category.getName()); - } - } - public int getCurrentSelectedCount() { int count = 0; for(CategoryItem item: categoriesAdapter.getItems()) { @@ -272,6 +262,7 @@ public class CategorizationFragment extends SherlockFragment{ CategoryItem item = (CategoryItem) adapterView.getAdapter().getItem(index); item.selected = !item.selected; checkedView.setChecked(item.selected); + // fixme save/update the item in the most recently used list } }); From 8b7095042deaf655eb572c1bf46713371f6e8dc1 Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Tue, 23 Apr 2013 08:31:01 -0700 Subject: [PATCH 07/19] Work in progress: hook up content provider for recent cats --- .../commons/CategorizationFragment.java | 36 +++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/commons/src/main/java/org/wikimedia/commons/CategorizationFragment.java b/commons/src/main/java/org/wikimedia/commons/CategorizationFragment.java index 723dbe4ab..129dfa5ef 100644 --- a/commons/src/main/java/org/wikimedia/commons/CategorizationFragment.java +++ b/commons/src/main/java/org/wikimedia/commons/CategorizationFragment.java @@ -26,6 +26,7 @@ import org.wikimedia.commons.contributions.Contribution; import java.io.IOException; import java.io.Serializable; import java.util.ArrayList; +import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.concurrent.ScheduledThreadPoolExecutor; @@ -134,7 +135,7 @@ public class CategorizationFragment extends SherlockFragment{ CategoryContentProvider.BASE_URI, Category.Table.ALL_FIELDS, null, - new String[] {}, + new String[]{}, null); while (cursor.moveToNext()) { Category cat = Category.fromCursor(cursor); @@ -228,6 +229,36 @@ public class CategorizationFragment extends SherlockFragment{ return count; } + private Category lookupCategory(String name) { + Cursor cursor = getActivity().getContentResolver().query( + CategoryContentProvider.BASE_URI, + Category.Table.ALL_FIELDS, + null, + new String[] {}, + null); + // fixme move to conditions + while (cursor.moveToNext()) { + Category cat = Category.fromCursor(cursor); + if (cat.getName().equals(name)) { + return cat; + } + } + + // Newly used category... + Category cat = new Category(); + cat.setName(name); + cat.setLastUsed(new Date()); + cat.setTimesUsed(0); + // fixme do we have to dispose of this ContentProviderClient? + cat.setContentProviderClient(getActivity().getContentResolver().acquireContentProviderClient(CategoryContentProvider.AUTHORITY)); + return cat; + } + private void updateCategoryCount(String name) { + Category cat = lookupCategory(name); + cat.incTimesUsed(); + cat.save(); + } + @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View rootView = inflater.inflate(R.layout.fragment_categorization, null); @@ -262,7 +293,8 @@ public class CategorizationFragment extends SherlockFragment{ CategoryItem item = (CategoryItem) adapterView.getAdapter().getItem(index); item.selected = !item.selected; checkedView.setChecked(item.selected); - // fixme save/update the item in the most recently used list + // fixme do this asynchronously? + updateCategoryCount(item.name); } }); From 79f6185f8c7a245f18af080c9b5a425f8499b2b6 Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Tue, 23 Apr 2013 10:27:46 -0700 Subject: [PATCH 08/19] Add DB updaters for Category table --- .../java/org/wikimedia/commons/category/Category.java | 10 ++++++++++ .../wikimedia/commons/contributions/Contribution.java | 5 +++++ .../java/org/wikimedia/commons/data/DBOpenHelper.java | 5 ++++- 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/commons/src/main/java/org/wikimedia/commons/category/Category.java b/commons/src/main/java/org/wikimedia/commons/category/Category.java index f7ff437ed..33609962b 100644 --- a/commons/src/main/java/org/wikimedia/commons/category/Category.java +++ b/commons/src/main/java/org/wikimedia/commons/category/Category.java @@ -127,6 +127,16 @@ public class Category { if(from == to) { return; } + if(from < 4) { + // doesn't exist yet + from++; + onUpdate(db, from, to); + return; + } + if(from == 4) { + // table added in version 5 + onCreate(db); + } } } } diff --git a/commons/src/main/java/org/wikimedia/commons/contributions/Contribution.java b/commons/src/main/java/org/wikimedia/commons/contributions/Contribution.java index 81892ac48..ece2719b6 100644 --- a/commons/src/main/java/org/wikimedia/commons/contributions/Contribution.java +++ b/commons/src/main/java/org/wikimedia/commons/contributions/Contribution.java @@ -302,6 +302,11 @@ public class Contribution extends Media { from++; return; } + if(from == 4) { + // Do nothing -- added Category + from++; + return; + } } } } diff --git a/commons/src/main/java/org/wikimedia/commons/data/DBOpenHelper.java b/commons/src/main/java/org/wikimedia/commons/data/DBOpenHelper.java index 011baa429..4430ac59a 100644 --- a/commons/src/main/java/org/wikimedia/commons/data/DBOpenHelper.java +++ b/commons/src/main/java/org/wikimedia/commons/data/DBOpenHelper.java @@ -3,13 +3,14 @@ package org.wikimedia.commons.data; import android.content.*; import android.database.sqlite.*; +import org.wikimedia.commons.category.Category; import org.wikimedia.commons.contributions.*; import org.wikimedia.commons.modifications.ModifierSequence; public class DBOpenHelper extends SQLiteOpenHelper{ private static final String DATABASE_NAME = "commons.db"; - private static final int DATABASE_VERSION = 4; + private static final int DATABASE_VERSION = 5; public DBOpenHelper(Context context) { super(context, DATABASE_NAME, null, DATABASE_VERSION); @@ -19,11 +20,13 @@ public class DBOpenHelper extends SQLiteOpenHelper{ public void onCreate(SQLiteDatabase sqLiteDatabase) { Contribution.Table.onCreate(sqLiteDatabase); ModifierSequence.Table.onCreate(sqLiteDatabase); + Category.Table.onCreate(sqLiteDatabase); } @Override public void onUpgrade(SQLiteDatabase sqLiteDatabase, int from, int to) { Contribution.Table.onUpdate(sqLiteDatabase, from, to); ModifierSequence.Table.onUpdate(sqLiteDatabase, from, to); + Category.Table.onUpdate(sqLiteDatabase, from, to); } } From 25191a968f84d0cb504f0668321e52878d7ada8a Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Tue, 23 Apr 2013 12:21:54 -0700 Subject: [PATCH 09/19] Categories now save :D Still to do: * limit number of entries * order by last-used * show entries on the initial screen before searching --- .../commons/CategorizationFragment.java | 16 +++++++++++++--- .../org/wikimedia/commons/category/Category.java | 2 +- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/commons/src/main/java/org/wikimedia/commons/CategorizationFragment.java b/commons/src/main/java/org/wikimedia/commons/CategorizationFragment.java index 129dfa5ef..d85c28fe3 100644 --- a/commons/src/main/java/org/wikimedia/commons/CategorizationFragment.java +++ b/commons/src/main/java/org/wikimedia/commons/CategorizationFragment.java @@ -1,6 +1,7 @@ package org.wikimedia.commons; import android.app.Activity; +import android.content.ContentProviderClient; import android.content.Context; import android.database.Cursor; import android.os.AsyncTask; @@ -249,14 +250,21 @@ public class CategorizationFragment extends SherlockFragment{ cat.setName(name); cat.setLastUsed(new Date()); cat.setTimesUsed(0); - // fixme do we have to dispose of this ContentProviderClient? - cat.setContentProviderClient(getActivity().getContentResolver().acquireContentProviderClient(CategoryContentProvider.AUTHORITY)); return cat; } private void updateCategoryCount(String name) { Category cat = lookupCategory(name); cat.incTimesUsed(); + + ContentProviderClient client = getActivity().getContentResolver().acquireContentProviderClient(CategoryContentProvider.AUTHORITY); + if (client == null) { + // explode + throw new RuntimeException("wtf"); + } + cat.setContentProviderClient(client); cat.save(); + cat.setContentProviderClient(null); + client.release(); } @Override @@ -294,7 +302,9 @@ public class CategorizationFragment extends SherlockFragment{ item.selected = !item.selected; checkedView.setChecked(item.selected); // fixme do this asynchronously? - updateCategoryCount(item.name); + if (item.selected) { + updateCategoryCount(item.name); + } } }); diff --git a/commons/src/main/java/org/wikimedia/commons/category/Category.java b/commons/src/main/java/org/wikimedia/commons/category/Category.java index 33609962b..6ea7f5076 100644 --- a/commons/src/main/java/org/wikimedia/commons/category/Category.java +++ b/commons/src/main/java/org/wikimedia/commons/category/Category.java @@ -87,7 +87,7 @@ public class Category { public static Category fromCursor(Cursor cursor) { // Hardcoding column positions! Category c = new Category(); - c.contentUri = ContributionsContentProvider.uriForId(cursor.getInt(0)); + c.contentUri = CategoryContentProvider.uriForId(cursor.getInt(0)); c.name = cursor.getString(1); c.lastUsed = new Date(cursor.getLong(2)); c.timesUsed = cursor.getInt(3); From d9746307047d4fa80e0f256759add0567b680e00 Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Tue, 23 Apr 2013 12:40:23 -0700 Subject: [PATCH 10/19] Use a single content provider client for all cat queries --- .../commons/CategorizationFragment.java | 45 ++++++++++--------- 1 file changed, 25 insertions(+), 20 deletions(-) diff --git a/commons/src/main/java/org/wikimedia/commons/CategorizationFragment.java b/commons/src/main/java/org/wikimedia/commons/CategorizationFragment.java index d85c28fe3..5ed0b6c87 100644 --- a/commons/src/main/java/org/wikimedia/commons/CategorizationFragment.java +++ b/commons/src/main/java/org/wikimedia/commons/CategorizationFragment.java @@ -4,10 +4,7 @@ import android.app.Activity; import android.content.ContentProviderClient; import android.content.Context; import android.database.Cursor; -import android.os.AsyncTask; -import android.os.Bundle; -import android.os.Parcel; -import android.os.Parcelable; +import android.os.*; import android.text.Editable; import android.text.TextUtils; import android.text.TextWatcher; @@ -51,6 +48,8 @@ public class CategorizationFragment extends SherlockFragment{ private HashMap> categoriesCache; + private ContentProviderClient client; + public static class CategoryItem implements Parcelable { public String name; public boolean selected; @@ -132,15 +131,20 @@ public class CategorizationFragment extends SherlockFragment{ ArrayList items = new ArrayList(); // fixme add a limit? // fixme sort by last_used descending? - Cursor cursor = getActivity().getContentResolver().query( - CategoryContentProvider.BASE_URI, - Category.Table.ALL_FIELDS, - null, - new String[]{}, - null); - while (cursor.moveToNext()) { - Category cat = Category.fromCursor(cursor); - items.add(cat.getName()); + try { + Cursor cursor = client.query( + CategoryContentProvider.BASE_URI, + Category.Table.ALL_FIELDS, + null, + new String[]{}, + null); + while (cursor.moveToNext()) { + Category cat = Category.fromCursor(cursor); + items.add(cat.getName()); + } + } catch (RemoteException e) { + // faaaail + throw new RuntimeException(e); } return items; } @@ -256,15 +260,8 @@ public class CategorizationFragment extends SherlockFragment{ Category cat = lookupCategory(name); cat.incTimesUsed(); - ContentProviderClient client = getActivity().getContentResolver().acquireContentProviderClient(CategoryContentProvider.AUTHORITY); - if (client == null) { - // explode - throw new RuntimeException("wtf"); - } cat.setContentProviderClient(client); cat.save(); - cat.setContentProviderClient(null); - client.release(); } @Override @@ -340,6 +337,14 @@ public class CategorizationFragment extends SherlockFragment{ super.onCreate(savedInstanceState); setHasOptionsMenu(true); getActivity().setTitle(R.string.categories_activity_title); + client = getActivity().getContentResolver().acquireContentProviderClient(CategoryContentProvider.AUTHORITY); + } + + @Override + public void onDestroy() { + client.release(); + client = null; + super.onDestroy(); } @Override From 29ebce5ab0e6a8855926c9ced25c0ce2b7c0a7c9 Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Wed, 24 Apr 2013 07:57:10 -0700 Subject: [PATCH 11/19] Show used cats in MRU order --- .../java/org/wikimedia/commons/CategorizationFragment.java | 2 +- .../main/java/org/wikimedia/commons/category/Category.java | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/commons/src/main/java/org/wikimedia/commons/CategorizationFragment.java b/commons/src/main/java/org/wikimedia/commons/CategorizationFragment.java index 5ed0b6c87..5caf75d95 100644 --- a/commons/src/main/java/org/wikimedia/commons/CategorizationFragment.java +++ b/commons/src/main/java/org/wikimedia/commons/CategorizationFragment.java @@ -137,7 +137,7 @@ public class CategorizationFragment extends SherlockFragment{ Category.Table.ALL_FIELDS, null, new String[]{}, - null); + Category.Table.COLUMN_LAST_USED + " DESC"); while (cursor.moveToNext()) { Category cat = Category.fromCursor(cursor); items.add(cat.getName()); diff --git a/commons/src/main/java/org/wikimedia/commons/category/Category.java b/commons/src/main/java/org/wikimedia/commons/category/Category.java index 6ea7f5076..920afbf98 100644 --- a/commons/src/main/java/org/wikimedia/commons/category/Category.java +++ b/commons/src/main/java/org/wikimedia/commons/category/Category.java @@ -47,6 +47,10 @@ public class Category { lastUsed = (Date)lastUsed_.clone(); } + public void touch() { + lastUsed = new Date(); + } + public int getTimesUsed() { return timesUsed; } @@ -57,6 +61,7 @@ public class Category { public void incTimesUsed() { timesUsed++; + touch(); } // Database/content-provider stuff From 308b28dd23dded4ab1e09536e56f44cc8ceb5f44 Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Wed, 24 Apr 2013 08:01:17 -0700 Subject: [PATCH 12/19] Use query conditions for the name lookup :D --- .../org/wikimedia/commons/CategorizationFragment.java | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/commons/src/main/java/org/wikimedia/commons/CategorizationFragment.java b/commons/src/main/java/org/wikimedia/commons/CategorizationFragment.java index 5caf75d95..2f915d0b8 100644 --- a/commons/src/main/java/org/wikimedia/commons/CategorizationFragment.java +++ b/commons/src/main/java/org/wikimedia/commons/CategorizationFragment.java @@ -238,15 +238,12 @@ public class CategorizationFragment extends SherlockFragment{ Cursor cursor = getActivity().getContentResolver().query( CategoryContentProvider.BASE_URI, Category.Table.ALL_FIELDS, - null, - new String[] {}, + Category.Table.COLUMN_NAME + "=?", + new String[] {name}, null); - // fixme move to conditions - while (cursor.moveToNext()) { + if (cursor.moveToNext()) { Category cat = Category.fromCursor(cursor); - if (cat.getName().equals(name)) { - return cat; - } + return cat; } // Newly used category... From 84c2054fb03000cefc3821fc30c902327b9d1d07 Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Wed, 24 Apr 2013 08:55:24 -0700 Subject: [PATCH 13/19] Limit view of recent cats to 20 --- .../java/org/wikimedia/commons/CategorizationFragment.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/commons/src/main/java/org/wikimedia/commons/CategorizationFragment.java b/commons/src/main/java/org/wikimedia/commons/CategorizationFragment.java index 2f915d0b8..d9adf8ca8 100644 --- a/commons/src/main/java/org/wikimedia/commons/CategorizationFragment.java +++ b/commons/src/main/java/org/wikimedia/commons/CategorizationFragment.java @@ -50,6 +50,8 @@ public class CategorizationFragment extends SherlockFragment{ private ContentProviderClient client; + private final int RECENT_CATS_LIMIT = 20; + public static class CategoryItem implements Parcelable { public String name; public boolean selected; @@ -129,8 +131,6 @@ public class CategorizationFragment extends SherlockFragment{ protected ArrayList doInBackground(Void... voids) { if(TextUtils.isEmpty(filter)) { ArrayList items = new ArrayList(); - // fixme add a limit? - // fixme sort by last_used descending? try { Cursor cursor = client.query( CategoryContentProvider.BASE_URI, @@ -138,7 +138,8 @@ public class CategorizationFragment extends SherlockFragment{ null, new String[]{}, Category.Table.COLUMN_LAST_USED + " DESC"); - while (cursor.moveToNext()) { + // fixme add a limit on the original query instead of falling out of the loop? + while (cursor.moveToNext() && cursor.getPosition() < RECENT_CATS_LIMIT) { Category cat = Category.fromCursor(cursor); items.add(cat.getName()); } From 6e8e8048616e57a7907d6b65cde4e568bb2c5142 Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Wed, 24 Apr 2013 13:27:13 -0700 Subject: [PATCH 14/19] Use same limit for recent cats and cat search --- .../java/org/wikimedia/commons/CategorizationFragment.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/commons/src/main/java/org/wikimedia/commons/CategorizationFragment.java b/commons/src/main/java/org/wikimedia/commons/CategorizationFragment.java index d9adf8ca8..14bbffcae 100644 --- a/commons/src/main/java/org/wikimedia/commons/CategorizationFragment.java +++ b/commons/src/main/java/org/wikimedia/commons/CategorizationFragment.java @@ -50,7 +50,7 @@ public class CategorizationFragment extends SherlockFragment{ private ContentProviderClient client; - private final int RECENT_CATS_LIMIT = 20; + private final int SEARCH_CATS_LIMIT = 25; public static class CategoryItem implements Parcelable { public String name; @@ -139,7 +139,7 @@ public class CategorizationFragment extends SherlockFragment{ new String[]{}, Category.Table.COLUMN_LAST_USED + " DESC"); // fixme add a limit on the original query instead of falling out of the loop? - while (cursor.moveToNext() && cursor.getPosition() < RECENT_CATS_LIMIT) { + while (cursor.moveToNext() && cursor.getPosition() < SEARCH_CATS_LIMIT) { Category cat = Category.fromCursor(cursor); items.add(cat.getName()); } @@ -159,7 +159,7 @@ public class CategorizationFragment extends SherlockFragment{ result = api.action("query") .param("list", "allcategories") .param("acprefix", filter) - .param("aclimit", 25) + .param("aclimit", SEARCH_CATS_LIMIT) .get(); } catch (IOException e) { throw new RuntimeException(e); From 8b351d94a3b2989b64e5c6c5da0b44a52fbe08a2 Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Wed, 24 Apr 2013 13:50:35 -0700 Subject: [PATCH 15/19] Hide the "skip" message if we load up some recent cats --- .../commons/CategorizationFragment.java | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/commons/src/main/java/org/wikimedia/commons/CategorizationFragment.java b/commons/src/main/java/org/wikimedia/commons/CategorizationFragment.java index 14bbffcae..b294dd1af 100644 --- a/commons/src/main/java/org/wikimedia/commons/CategorizationFragment.java +++ b/commons/src/main/java/org/wikimedia/commons/CategorizationFragment.java @@ -124,6 +124,9 @@ public class CategorizationFragment extends SherlockFragment{ if(!TextUtils.isEmpty(filter) && categories.size() == 0) { categoriesNotFoundView.setText(getString(R.string.categories_not_found, filter)); categoriesNotFoundView.setVisibility(View.VISIBLE); + } else { + // If we found recent cats, hide the skip message! + categoriesSkip.setVisibility(View.GONE); } } @@ -308,11 +311,7 @@ public class CategorizationFragment extends SherlockFragment{ } public void onTextChanged(CharSequence charSequence, int i, int i2, int i3) { - if(lastUpdater != null) { - lastUpdater.cancel(true); - } - lastUpdater = new CategoriesUpdater(); - Utils.executeAsyncTask(lastUpdater, executor); + startUpdatingCategoryList(); } public void afterTextChanged(Editable editable) { @@ -320,10 +319,19 @@ public class CategorizationFragment extends SherlockFragment{ } }); + startUpdatingCategoryList(); return rootView; } + private void startUpdatingCategoryList() { + if (lastUpdater != null) { + lastUpdater.cancel(true); + } + lastUpdater = new CategoriesUpdater(); + Utils.executeAsyncTask(lastUpdater, executor); + } + @Override public void onCreateOptionsMenu(Menu menu, com.actionbarsherlock.view.MenuInflater inflater) { menu.clear(); From 290ac007673037e7651b7f05a4cfbd39c061ff5b Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Thu, 25 Apr 2013 06:34:37 -0700 Subject: [PATCH 16/19] Fixups per Yuvi's notes --- commons/commons.iml | 17 ------ .../commons/CategorizationFragment.java | 52 +++++++++++++------ .../wikimedia/commons/category/Category.java | 21 +++----- .../category/CategoryContentProvider.java | 9 +--- 4 files changed, 43 insertions(+), 56 deletions(-) diff --git a/commons/commons.iml b/commons/commons.iml index 0fec16f50..55cc5b2fb 100644 --- a/commons/commons.iml +++ b/commons/commons.iml @@ -5,28 +5,11 @@ diff --git a/commons/src/main/java/org/wikimedia/commons/CategorizationFragment.java b/commons/src/main/java/org/wikimedia/commons/CategorizationFragment.java index b294dd1af..3ffa89498 100644 --- a/commons/src/main/java/org/wikimedia/commons/CategorizationFragment.java +++ b/commons/src/main/java/org/wikimedia/commons/CategorizationFragment.java @@ -239,15 +239,20 @@ public class CategorizationFragment extends SherlockFragment{ } private Category lookupCategory(String name) { - Cursor cursor = getActivity().getContentResolver().query( - CategoryContentProvider.BASE_URI, - Category.Table.ALL_FIELDS, - Category.Table.COLUMN_NAME + "=?", - new String[] {name}, - null); - if (cursor.moveToNext()) { - Category cat = Category.fromCursor(cursor); - return cat; + try { + Cursor cursor = client.query( + CategoryContentProvider.BASE_URI, + Category.Table.ALL_FIELDS, + Category.Table.COLUMN_NAME + "=?", + new String[] {name}, + null); + if (cursor.moveToFirst()) { + Category cat = Category.fromCursor(cursor); + return cat; + } + } catch (RemoteException e) { + // This feels lazy, but to hell with checked exceptions. :) + throw new RuntimeException(e); } // Newly used category... @@ -257,12 +262,27 @@ public class CategorizationFragment extends SherlockFragment{ cat.setTimesUsed(0); return cat; } - private void updateCategoryCount(String name) { - Category cat = lookupCategory(name); - cat.incTimesUsed(); - cat.setContentProviderClient(client); - cat.save(); + private class CategoryCountUpdater extends AsyncTask { + + private String name; + + public CategoryCountUpdater(String name) { + this.name = name; + } + + @Override + protected void doInBackground(Void... voids) { + Category cat = lookupCategory(name); + cat.incTimesUsed(); + + cat.setContentProviderClient(client); + cat.save(); + } + } + + private void updateCategoryCount(String name) { + Utils.executeAsyncTask(new CategoryCountUpdater(name), executor); } @Override @@ -299,7 +319,6 @@ public class CategorizationFragment extends SherlockFragment{ CategoryItem item = (CategoryItem) adapterView.getAdapter().getItem(index); item.selected = !item.selected; checkedView.setChecked(item.selected); - // fixme do this asynchronously? if (item.selected) { updateCategoryCount(item.name); } @@ -348,9 +367,8 @@ public class CategorizationFragment extends SherlockFragment{ @Override public void onDestroy() { - client.release(); - client = null; super.onDestroy(); + client.release(); } @Override diff --git a/commons/src/main/java/org/wikimedia/commons/category/Category.java b/commons/src/main/java/org/wikimedia/commons/category/Category.java index 920afbf98..ae2045867 100644 --- a/commons/src/main/java/org/wikimedia/commons/category/Category.java +++ b/commons/src/main/java/org/wikimedia/commons/category/Category.java @@ -13,13 +13,6 @@ import org.wikimedia.commons.contributions.ContributionsContentProvider; import java.util.Date; -/** - * Created with IntelliJ IDEA. - * User: brion - * Date: 4/22/13 - * Time: 3:37 PM - * To change this template use File | Settings | File Templates. - */ public class Category { private ContentProviderClient client; private Uri contentUri; @@ -33,8 +26,8 @@ public class Category { return name; } - public void setName(String name_) { - name = name_; + public void setName(String name) { + this.name = name; } public Date getLastUsed() { @@ -42,9 +35,9 @@ public class Category { return (Date)lastUsed.clone(); } - public void setLastUsed(Date lastUsed_) { + public void setLastUsed(Date lastUsed) { // warning: Date objects are mutable. - lastUsed = (Date)lastUsed_.clone(); + this.lastUsed = (Date)lastUsed.clone(); } public void touch() { @@ -55,8 +48,8 @@ public class Category { return timesUsed; } - public void setTimesUsed(int timesUsed_) { - timesUsed = timesUsed_; + public void setTimesUsed(int timesUsed) { + this.timesUsed = timesUsed; } public void incTimesUsed() { @@ -119,7 +112,7 @@ public class Category { private static final String CREATE_TABLE_STATEMENT = "CREATE TABLE " + TABLE_NAME + " (" + COLUMN_ID + " INTEGER PRIMARY KEY," + COLUMN_NAME + " STRING," - + COLUMN_LAST_USED + " INTEGER," // Will this roll over in 2038? :) + + COLUMN_LAST_USED + " INTEGER," + COLUMN_TIMES_USED + " INTEGER" + ");"; diff --git a/commons/src/main/java/org/wikimedia/commons/category/CategoryContentProvider.java b/commons/src/main/java/org/wikimedia/commons/category/CategoryContentProvider.java index 0276b29ca..c8dccd062 100644 --- a/commons/src/main/java/org/wikimedia/commons/category/CategoryContentProvider.java +++ b/commons/src/main/java/org/wikimedia/commons/category/CategoryContentProvider.java @@ -12,16 +12,9 @@ import android.util.Log; import org.wikimedia.commons.CommonsApplication; import org.wikimedia.commons.data.DBOpenHelper; -/** - * Created with IntelliJ IDEA. - * User: brion - * Date: 4/22/13 - * Time: 4:09 PM - * To change this template use File | Settings | File Templates. - */ public class CategoryContentProvider extends ContentProvider { - // ???? + // For URI matcher private static final int CATEGORIES = 1; private static final int CATEGORIES_ID = 2; From ae01386018fc5943bb21d74cff781104c4a95683 Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Thu, 25 Apr 2013 08:55:50 -0700 Subject: [PATCH 17/19] Remove generic update from categories provider --- .../wikimedia/commons/category/CategoryContentProvider.java | 6 ------ 1 file changed, 6 deletions(-) diff --git a/commons/src/main/java/org/wikimedia/commons/category/CategoryContentProvider.java b/commons/src/main/java/org/wikimedia/commons/category/CategoryContentProvider.java index c8dccd062..fa1f86c36 100644 --- a/commons/src/main/java/org/wikimedia/commons/category/CategoryContentProvider.java +++ b/commons/src/main/java/org/wikimedia/commons/category/CategoryContentProvider.java @@ -135,12 +135,6 @@ public class CategoryContentProvider extends ContentProvider { SQLiteDatabase sqlDB = dbOpenHelper.getWritableDatabase(); int rowsUpdated = 0; switch (uriType) { - case CATEGORIES: - rowsUpdated = sqlDB.update(Category.Table.TABLE_NAME, - contentValues, - selection, - selectionArgs); - break; case CATEGORIES_ID: int id = Integer.valueOf(uri.getLastPathSegment()); From 4922e615fd1496c64bc3a13993e7667ff239f19a Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Thu, 25 Apr 2013 08:55:24 -0700 Subject: [PATCH 18/19] Compile fix for method that returns Void. :P --- .../java/org/wikimedia/commons/CategorizationFragment.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/commons/src/main/java/org/wikimedia/commons/CategorizationFragment.java b/commons/src/main/java/org/wikimedia/commons/CategorizationFragment.java index 3ffa89498..8b3512c5c 100644 --- a/commons/src/main/java/org/wikimedia/commons/CategorizationFragment.java +++ b/commons/src/main/java/org/wikimedia/commons/CategorizationFragment.java @@ -272,12 +272,14 @@ public class CategorizationFragment extends SherlockFragment{ } @Override - protected void doInBackground(Void... voids) { + protected Void doInBackground(Void... voids) { Category cat = lookupCategory(name); cat.incTimesUsed(); cat.setContentProviderClient(client); cat.save(); + + return null; // Make the compiler happy. } } From f9ca376bf32a1903c7e6b8dabea5565f060526f1 Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Thu, 25 Apr 2013 09:07:52 -0700 Subject: [PATCH 19/19] Fix regression in first-categorization experience The skip message now shows when there are no recently-used categories. --- .../org/wikimedia/commons/CategorizationFragment.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/commons/src/main/java/org/wikimedia/commons/CategorizationFragment.java b/commons/src/main/java/org/wikimedia/commons/CategorizationFragment.java index 8b3512c5c..a95172937 100644 --- a/commons/src/main/java/org/wikimedia/commons/CategorizationFragment.java +++ b/commons/src/main/java/org/wikimedia/commons/CategorizationFragment.java @@ -121,9 +121,11 @@ public class CategorizationFragment extends SherlockFragment{ categoriesAdapter.setItems(items); categoriesAdapter.notifyDataSetInvalidated(); categoriesSearchInProgress.setVisibility(View.GONE); - if(!TextUtils.isEmpty(filter) && categories.size() == 0) { - categoriesNotFoundView.setText(getString(R.string.categories_not_found, filter)); - categoriesNotFoundView.setVisibility(View.VISIBLE); + if (categories.size() == 0) { + if(!TextUtils.isEmpty(filter)) { + categoriesNotFoundView.setText(getString(R.string.categories_not_found, filter)); + categoriesNotFoundView.setVisibility(View.VISIBLE); + } } else { // If we found recent cats, hide the skip message! categoriesSkip.setVisibility(View.GONE);