From 9e0b8f0377d8578fd552d1ddf7aab6af894638c7 Mon Sep 17 00:00:00 2001 From: Ashish Kumar Date: Mon, 13 Jan 2020 11:39:17 +0530 Subject: [PATCH] Part of #3127 * Added Room Dependency * Shifted ContributionsDao to use RoomDB --- app/build.gradle | 5 + app/src/main/AndroidManifest.xml | 18 - .../free/nrw/commons/CommonsApplication.java | 7 +- .../main/java/fr/free/nrw/commons/Media.java | 47 +-- .../commons/contributions/Contribution.java | 22 +- .../contributions/ContributionDao.java | 341 ++---------------- .../ContributionsContentProvider.java | 186 ---------- .../contributions/ContributionsContract.java | 14 +- .../contributions/ContributionsFragment.java | 28 +- .../ContributionsListAdapter.java | 18 +- .../ContributionsListFragment.java | 24 +- .../ContributionsLocalDataSource.java | 21 +- .../contributions/ContributionsPresenter.java | 188 ++++------ .../ContributionsRepository.java | 21 +- .../ContributionsSyncAdapter.java | 84 ----- .../ContributionsSyncService.java | 27 -- .../commons/contributions/MainActivity.java | 2 - .../free/nrw/commons/data/DBOpenHelper.java | 3 - .../fr/free/nrw/commons/db/AppDatabase.java | 14 + .../fr/free/nrw/commons/db/Converters.java | 67 ++++ .../di/CommonsApplicationComponent.java | 3 - .../commons/di/CommonsApplicationModule.java | 7 + .../di/ContentProviderBuilderModule.java | 4 - .../nrw/commons/upload/UploadService.java | 26 +- .../free/nrw/commons/utils/ExecutorUtils.java | 7 + .../ContributionsPresenterTest.kt | 2 +- ....free.nrw.commons.beta_2020.01.13_11.01.li | Bin 0 -> 722867 bytes 27 files changed, 315 insertions(+), 871 deletions(-) delete mode 100644 app/src/main/java/fr/free/nrw/commons/contributions/ContributionsContentProvider.java delete mode 100644 app/src/main/java/fr/free/nrw/commons/contributions/ContributionsSyncAdapter.java delete mode 100644 app/src/main/java/fr/free/nrw/commons/contributions/ContributionsSyncService.java create mode 100644 app/src/main/java/fr/free/nrw/commons/db/AppDatabase.java create mode 100644 app/src/main/java/fr/free/nrw/commons/db/Converters.java create mode 100644 captures/fr.free.nrw.commons.beta_2020.01.13_11.01.li diff --git a/app/build.gradle b/app/build.gradle index 2197573ab4..52f240813c 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -102,6 +102,11 @@ dependencies { //swipe_layout implementation 'com.daimajia.swipelayout:library:1.2.0@aar' + + //Room + def room_version= '2.2.3' + implementation "androidx.room:room-runtime:$room_version" + kapt "androidx.room:room-compiler:$room_version" // For Kotlin use kapt instead of annotationProcessor } android { diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index ad88b720cf..baabce2f08 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -150,18 +150,6 @@ android:name="android.accounts.AccountAuthenticator" android:resource="@xml/authenticator" /> - - - - - - - - categories; // as loaded at runtime? - protected boolean requestedDeletion; - private Map descriptions; // multilingual descriptions as loaded - private HashMap tags = new HashMap<>(); - private @Nullable LatLng coordinates; + @PrimaryKey + @NonNull + public Uri localUri; + public String thumbUrl; + public String imageUrl; + public String filename; + public String description; // monolingual description on input... + public String discussion; + long dataLength; + public Date dateCreated; + @Nullable public Date dateUploaded; + public int width; + public int height; + public String license; + public String licenseUrl; + public String creator; + public ArrayList categories; // as loaded at runtime? + public boolean requestedDeletion; + public HashMap descriptions; // multilingual descriptions as loaded + public HashMap tags = new HashMap<>(); + @Nullable public LatLng coordinates; /** * Provides local constructor @@ -118,7 +123,7 @@ public Media(Parcel in) { dateCreated = (Date) in.readSerializable(); dateUploaded = (Date) in.readSerializable(); creator = in.readString(); - tags = (HashMap) in.readSerializable(); + tags = (HashMap) in.readSerializable(); width = in.readInt(); height = in.readInt(); license = in.readString(); @@ -218,7 +223,7 @@ public Object getTag(String key) { * @param key Media key * @param value Media value */ - public void setTag(String key, Object value) { + public void setTag(String key, String value) { tags.put(key, value); } diff --git a/app/src/main/java/fr/free/nrw/commons/contributions/Contribution.java b/app/src/main/java/fr/free/nrw/commons/contributions/Contribution.java index a9bda62532..7198b34c6f 100644 --- a/app/src/main/java/fr/free/nrw/commons/contributions/Contribution.java +++ b/app/src/main/java/fr/free/nrw/commons/contributions/Contribution.java @@ -6,6 +6,7 @@ import androidx.annotation.NonNull; import androidx.annotation.StringDef; +import androidx.room.Entity; import org.apache.commons.lang3.StringUtils; @@ -21,6 +22,7 @@ import static java.lang.annotation.RetentionPolicy.SOURCE; +@Entity public class Contribution extends Media { //{{According to EXIF data|2009-01-09}} @@ -55,16 +57,16 @@ public Contribution[] newArray(int i) { public static final String SOURCE_GALLERY = "gallery"; public static final String SOURCE_EXTERNAL = "external"; - private Uri contentUri; - private String source; - private String editSummary; - private int state; - private long transferred; - private String decimalCoords; - private boolean isMultiple; - private String wikiDataEntityId; - private Uri contentProviderUri; - private String dateCreatedSource; + public Uri contentUri; + public String source; + public String editSummary; + public int state; + public long transferred; + public String decimalCoords; + public boolean isMultiple; + public String wikiDataEntityId; + public Uri contentProviderUri; + public String dateCreatedSource; public Contribution(Uri contentUri, String filename, Uri localUri, String imageUrl, Date dateCreated, int state, long dataLength, Date dateUploaded, long transferred, diff --git a/app/src/main/java/fr/free/nrw/commons/contributions/ContributionDao.java b/app/src/main/java/fr/free/nrw/commons/contributions/ContributionDao.java index e1c134111e..ed0da4dac4 100644 --- a/app/src/main/java/fr/free/nrw/commons/contributions/ContributionDao.java +++ b/app/src/main/java/fr/free/nrw/commons/contributions/ContributionDao.java @@ -1,331 +1,36 @@ package fr.free.nrw.commons.contributions; -import android.content.ContentProviderClient; -import android.content.ContentValues; -import android.database.Cursor; -import android.database.sqlite.SQLiteDatabase; -import android.database.sqlite.SQLiteException; -import android.net.Uri; -import android.os.RemoteException; -import android.text.TextUtils; +import androidx.room.Dao; +import androidx.room.Delete; +import androidx.room.Insert; +import androidx.room.Query; -import androidx.annotation.Nullable; +import java.util.List; -import org.apache.commons.lang3.StringUtils; +@Dao +public interface ContributionDao { -import java.util.Date; + @Query("SELECT * FROM contribution") + List loadAllContributions(); -import javax.inject.Inject; -import javax.inject.Named; -import javax.inject.Provider; + @Insert + public void save(Contribution contribution); -import fr.free.nrw.commons.settings.Prefs; -import timber.log.Timber; + @Insert + public void save(List contribution); -import static fr.free.nrw.commons.contributions.ContributionDao.Table.ALL_FIELDS; -import static fr.free.nrw.commons.contributions.ContributionDao.Table.COLUMN_WIKI_DATA_ENTITY_ID; -import static fr.free.nrw.commons.contributions.ContributionsContentProvider.BASE_URI; -import static fr.free.nrw.commons.contributions.ContributionsContentProvider.uriForId; + @Delete + public void delete(Contribution contribution); -public class ContributionDao { - /* - This sorts in the following order: - Currently Uploading - Failed (Sorted in ascending order of time added - FIFO) - Queued to Upload (Sorted in ascending order of time added - FIFO) - Completed (Sorted in descending order of time added) + @Query("SELECT * from contribution WHERE contentProviderUri=:uri") + public List getContributionWithUri(String uri); - This is why Contribution.STATE_COMPLETED is -1. - */ - static final String CONTRIBUTION_SORT = Table.COLUMN_STATE + " DESC, " - + Table.COLUMN_UPLOADED + " DESC , (" - + Table.COLUMN_TIMESTAMP + " * " - + Table.COLUMN_STATE + ")"; + @Query("SELECT * from contribution WHERE filename=:fileName") + public List getContributionWithTitle(String fileName); - private final Provider clientProvider; + @Query("UPDATE contribution SET state=:state WHERE state in (:toUpdateStates)") + public void updateStates(int state, int[] toUpdateStates); - @Inject - public ContributionDao(@Named("contribution") Provider clientProvider) { - this.clientProvider = clientProvider; - } - - Cursor loadAllContributions() { - ContentProviderClient db = clientProvider.get(); - try { - return db.query(BASE_URI, ALL_FIELDS, "", null, CONTRIBUTION_SORT); - } catch (RemoteException e) { - return null; - } finally { - db.release(); - } - } - - public void save(Contribution contribution) { - ContentProviderClient db = clientProvider.get(); - try { - if (contribution.getContentUri() == null) { - contribution.setContentUri(db.insert(BASE_URI, toContentValues(contribution))); - } else { - db.update(contribution.getContentUri(), toContentValues(contribution), null, null); - } - } catch (RemoteException e) { - throw new RuntimeException(e); - } finally { - db.release(); - } - } - - public void delete(Contribution contribution) { - ContentProviderClient db = clientProvider.get(); - try { - if (contribution.getContentUri() == null) { - // noooo - throw new RuntimeException("tried to delete item with no content URI"); - } else { - db.delete(contribution.getContentUri(), null, null); - } - } catch (RemoteException e) { - throw new RuntimeException(e); - } finally { - db.release(); - } - } - - ContentValues toContentValues(Contribution contribution) { - ContentValues cv = new ContentValues(); - cv.put(Table.COLUMN_FILENAME, contribution.getFilename()); - if (contribution.getLocalUri() != null) { - cv.put(Table.COLUMN_LOCAL_URI, contribution.getLocalUri().toString()); - } - if (contribution.getImageUrl() != null) { - cv.put(Table.COLUMN_IMAGE_URL, contribution.getImageUrl()); - } - if (contribution.getDateUploaded() != null) { - cv.put(Table.COLUMN_UPLOADED, contribution.getDateUploaded().getTime()); - } - cv.put(Table.COLUMN_LENGTH, contribution.getDataLength()); - //This was always meant to store the date created..If somehow date created is not fetched while actually saving the contribution, lets saveValue today's date - cv.put(Table.COLUMN_TIMESTAMP, contribution.getDateCreated()==null?System.currentTimeMillis():contribution.getDateCreated().getTime()); - cv.put(Table.COLUMN_STATE, contribution.getState()); - cv.put(Table.COLUMN_TRANSFERRED, contribution.getTransferred()); - cv.put(Table.COLUMN_SOURCE, contribution.getSource()); - cv.put(Table.COLUMN_DESCRIPTION, contribution.getDescription()); - cv.put(Table.COLUMN_CREATOR, contribution.getCreator()); - cv.put(Table.COLUMN_MULTIPLE, contribution.getMultiple() ? 1 : 0); - cv.put(Table.COLUMN_WIDTH, contribution.getWidth()); - cv.put(Table.COLUMN_HEIGHT, contribution.getHeight()); - cv.put(Table.COLUMN_LICENSE, contribution.getLicense()); - cv.put(Table.COLUMN_WIKI_DATA_ENTITY_ID, contribution.getWikiDataEntityId()); - return cv; - } - - public Contribution fromCursor(Cursor cursor) { - // Hardcoding column positions! - //Check that cursor has a value to avoid CursorIndexOutOfBoundsException - if (cursor.getCount() > 0) { - int index; - if (cursor.getColumnIndex(Table.COLUMN_LICENSE) == -1){ - index = 15; - } else { - index = cursor.getColumnIndex(Table.COLUMN_LICENSE); - } - Contribution contribution = new Contribution( - uriForId(cursor.getInt(cursor.getColumnIndex(Table.COLUMN_ID))), - cursor.getString(cursor.getColumnIndex(Table.COLUMN_FILENAME)), - parseUri(cursor.getString(cursor.getColumnIndex(Table.COLUMN_LOCAL_URI))), - cursor.getString(cursor.getColumnIndex(Table.COLUMN_IMAGE_URL)), - parseTimestamp(cursor.getLong(cursor.getColumnIndex(Table.COLUMN_TIMESTAMP))), - cursor.getInt(cursor.getColumnIndex(Table.COLUMN_STATE)), - cursor.getLong(cursor.getColumnIndex(Table.COLUMN_LENGTH)), - parseTimestamp(cursor.getLong(cursor.getColumnIndex(Table.COLUMN_UPLOADED))), - cursor.getLong(cursor.getColumnIndex(Table.COLUMN_TRANSFERRED)), - cursor.getString(cursor.getColumnIndex(Table.COLUMN_SOURCE)), - cursor.getString(cursor.getColumnIndex(Table.COLUMN_DESCRIPTION)), - cursor.getString(cursor.getColumnIndex(Table.COLUMN_CREATOR)), - cursor.getInt(cursor.getColumnIndex(Table.COLUMN_MULTIPLE)) == 1, - cursor.getInt(cursor.getColumnIndex(Table.COLUMN_WIDTH)), - cursor.getInt(cursor.getColumnIndex(Table.COLUMN_HEIGHT)), - cursor.getString(index) - ); - - String wikidataEntityId = cursor.getString(cursor.getColumnIndex(COLUMN_WIKI_DATA_ENTITY_ID)); - if (!StringUtils.isBlank(wikidataEntityId)) { - contribution.setWikiDataEntityId(wikidataEntityId); - } - - return contribution; - } - - return null; - } - - @Nullable - private static Date parseTimestamp(long timestamp) { - return timestamp == 0 ? null : new Date(timestamp); - } - - @Nullable - private static Uri parseUri(String uriString) { - return TextUtils.isEmpty(uriString) ? null : Uri.parse(uriString); - } - - public static class Table { - public static final String TABLE_NAME = "contributions"; - - public static final String COLUMN_ID = "_id"; - public static final String COLUMN_FILENAME = "filename"; - public static final String COLUMN_LOCAL_URI = "local_uri"; - public static final String COLUMN_IMAGE_URL = "image_url"; - public static final String COLUMN_TIMESTAMP = "timestamp"; - public static final String COLUMN_STATE = "state"; - public static final String COLUMN_LENGTH = "length"; - public static final String COLUMN_UPLOADED = "uploaded"; - public static final String COLUMN_TRANSFERRED = "transferred"; // Currently transferred number of bytes - public static final String COLUMN_SOURCE = "source"; - public static final String COLUMN_DESCRIPTION = "description"; - public static final String COLUMN_CREATOR = "creator"; // Initial uploader - public static final String COLUMN_MULTIPLE = "multiple"; - public static final String COLUMN_WIDTH = "width"; - public static final String COLUMN_HEIGHT = "height"; - public static final String COLUMN_LICENSE = "license"; - public static final String COLUMN_WIKI_DATA_ENTITY_ID = "wikidataEntityID"; - - // 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_FILENAME, - COLUMN_LOCAL_URI, - COLUMN_IMAGE_URL, - COLUMN_TIMESTAMP, - COLUMN_STATE, - COLUMN_LENGTH, - COLUMN_UPLOADED, - COLUMN_TRANSFERRED, - COLUMN_SOURCE, - COLUMN_DESCRIPTION, - COLUMN_CREATOR, - COLUMN_MULTIPLE, - COLUMN_WIDTH, - COLUMN_HEIGHT, - COLUMN_LICENSE, - COLUMN_WIKI_DATA_ENTITY_ID - }; - - public static final String DROP_TABLE_STATEMENT = "DROP TABLE IF EXISTS " + TABLE_NAME; - - public static final String CREATE_TABLE_STATEMENT = "CREATE TABLE " + TABLE_NAME + " (" - + "_id INTEGER PRIMARY KEY," - + "filename STRING," - + "local_uri STRING," - + "image_url STRING," - + "uploaded INTEGER," - + "timestamp INTEGER," - + "state INTEGER," - + "length INTEGER," - + "transferred INTEGER," - + "source STRING," - + "description STRING," - + "creator STRING," - + "multiple INTEGER," - + "width INTEGER," - + "height INTEGER," - + "LICENSE STRING," - + "wikidataEntityID STRING" - + ");"; - - // Upgrade from version 1 -> - static final String ADD_CREATOR_FIELD = "ALTER TABLE " + TABLE_NAME + " ADD COLUMN creator STRING;"; - static final String ADD_DESCRIPTION_FIELD = "ALTER TABLE " + TABLE_NAME + " ADD COLUMN description STRING;"; - - // Upgrade from version 2 -> - static final String ADD_MULTIPLE_FIELD = "ALTER TABLE " + TABLE_NAME + " ADD COLUMN multiple INTEGER;"; - static final String SET_DEFAULT_MULTIPLE = "UPDATE " + TABLE_NAME + " SET multiple = 0"; - - // Upgrade from version 5 -> - static final String ADD_WIDTH_FIELD = "ALTER TABLE " + TABLE_NAME + " ADD COLUMN width INTEGER;"; - static final String SET_DEFAULT_WIDTH = "UPDATE " + TABLE_NAME + " SET width = 0"; - static final String ADD_HEIGHT_FIELD = "ALTER TABLE " + TABLE_NAME + " ADD COLUMN height INTEGER;"; - static final String SET_DEFAULT_HEIGHT = "UPDATE " + TABLE_NAME + " SET height = 0"; - static final String ADD_LICENSE_FIELD = "ALTER TABLE " + TABLE_NAME + " ADD COLUMN license STRING;"; - static final String SET_DEFAULT_LICENSE = "UPDATE " + TABLE_NAME + " SET license='" + Prefs.Licenses.CC_BY_SA_3 + "';"; - - // Upgrade from version 8 -> - static final String ADD_WIKI_DATA_ENTITY_ID_FIELD = "ALTER TABLE " + TABLE_NAME + " ADD COLUMN wikidataEntityID STRING;"; - - - public static void onCreate(SQLiteDatabase db) { - db.execSQL(CREATE_TABLE_STATEMENT); - } - - public static void onDelete(SQLiteDatabase db) { - db.execSQL(DROP_TABLE_STATEMENT); - onCreate(db); - } - - public static void onUpdate(SQLiteDatabase db, int from, int to) { - if (from == to) { - return; - } - - //Considering the crashes we have been facing recently, lets blindly add this column to any table which has ever existed - runQuery(db,ADD_WIKI_DATA_ENTITY_ID_FIELD); - - if (from == 1) { - runQuery(db,ADD_DESCRIPTION_FIELD); - runQuery(db,ADD_CREATOR_FIELD); - from++; - onUpdate(db, from, to); - return; - } - if (from == 2) { - runQuery(db, ADD_MULTIPLE_FIELD); - runQuery(db, SET_DEFAULT_MULTIPLE); - from++; - onUpdate(db, from, to); - return; - } - if (from == 3) { - // Do nothing - from++; - onUpdate(db, from, to); - return; - } - if (from == 4) { - // Do nothing -- added Category - from++; - onUpdate(db, from, to); - return; - } - if (from == 5) { - // Added width and height fields - runQuery(db, ADD_WIDTH_FIELD); - runQuery(db, SET_DEFAULT_WIDTH); - runQuery(db, ADD_HEIGHT_FIELD); - runQuery(db, SET_DEFAULT_HEIGHT); - runQuery(db, ADD_LICENSE_FIELD); - runQuery(db, SET_DEFAULT_LICENSE); - from++; - onUpdate(db, from, to); - return; - } - if (from > 5) { - // Added place field - from=to; - onUpdate(db, from, to); - return; - } - } - - /** - * perform the db.execSQl with handled exceptions - */ - private static void runQuery(SQLiteDatabase db, String query) { - try { - db.execSQL(query); - } catch (SQLiteException e) { - Timber.e("Exception performing query: " + query + " message: " + e.getMessage()); - } - } - - } + @Query("Delete FROM contribution") + void deleteAll(); } diff --git a/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsContentProvider.java b/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsContentProvider.java deleted file mode 100644 index 4a504f1228..0000000000 --- a/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsContentProvider.java +++ /dev/null @@ -1,186 +0,0 @@ -package fr.free.nrw.commons.contributions; - -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 androidx.annotation.NonNull; - -import javax.inject.Inject; - -import fr.free.nrw.commons.BuildConfig; -import fr.free.nrw.commons.data.DBOpenHelper; -import fr.free.nrw.commons.di.CommonsDaggerContentProvider; -import timber.log.Timber; - -import static android.content.UriMatcher.NO_MATCH; -import static fr.free.nrw.commons.contributions.ContributionDao.Table.ALL_FIELDS; -import static fr.free.nrw.commons.contributions.ContributionDao.Table.TABLE_NAME; - -public class ContributionsContentProvider extends CommonsDaggerContentProvider { - - private static final int CONTRIBUTIONS = 1; - private static final int CONTRIBUTIONS_ID = 2; - private static final String BASE_PATH = "contributions"; - private static final UriMatcher uriMatcher = new UriMatcher(NO_MATCH); - - public static final Uri BASE_URI = Uri.parse("content://" + BuildConfig.CONTRIBUTION_AUTHORITY + "/" + BASE_PATH); - - static { - uriMatcher.addURI(BuildConfig.CONTRIBUTION_AUTHORITY, BASE_PATH, CONTRIBUTIONS); - uriMatcher.addURI(BuildConfig.CONTRIBUTION_AUTHORITY, BASE_PATH + "/#", CONTRIBUTIONS_ID); - } - - public static Uri uriForId(int id) { - return Uri.parse(BASE_URI.toString() + "/" + id); - } - - @Inject DBOpenHelper dbOpenHelper; - - @SuppressWarnings("ConstantConditions") - @Override - public Cursor query(@NonNull Uri uri, String[] projection, String selection, - String[] selectionArgs, String sortOrder) { - SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder(); - queryBuilder.setTables(TABLE_NAME); - - int uriType = uriMatcher.match(uri); - - SQLiteDatabase db = dbOpenHelper.getReadableDatabase(); - Cursor cursor; - - switch (uriType) { - case CONTRIBUTIONS: - cursor = queryBuilder.query(db, projection, selection, selectionArgs, - null, null, sortOrder); - break; - case CONTRIBUTIONS_ID: - cursor = queryBuilder.query(db, - 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(@NonNull Uri uri) { - return null; - } - - @SuppressWarnings("ConstantConditions") - @Override - public Uri insert(@NonNull Uri uri, ContentValues contentValues) { - int uriType = uriMatcher.match(uri); - SQLiteDatabase sqlDB = dbOpenHelper.getWritableDatabase(); - long id; - switch (uriType) { - case CONTRIBUTIONS: - id = sqlDB.insert(TABLE_NAME, null, contentValues); - break; - default: - throw new IllegalArgumentException("Unknown URI: " + uri); - } - getContext().getContentResolver().notifyChange(uri, null); - return Uri.parse(BASE_URI + "/" + id); - } - - @SuppressWarnings("ConstantConditions") - @Override - public int delete(@NonNull Uri uri, String s, String[] strings) { - int rows; - int uriType = uriMatcher.match(uri); - - SQLiteDatabase db = dbOpenHelper.getReadableDatabase(); - - switch (uriType) { - case CONTRIBUTIONS_ID: - Timber.d("Deleting contribution id %s", uri.getLastPathSegment()); - rows = db.delete(TABLE_NAME, - "_id = ?", - new String[]{uri.getLastPathSegment()} - ); - break; - default: - throw new IllegalArgumentException("Unknown URI" + uri); - } - getContext().getContentResolver().notifyChange(uri, null); - return rows; - } - - @SuppressWarnings("ConstantConditions") - @Override - public int bulkInsert(@NonNull Uri uri, @NonNull ContentValues[] values) { - Timber.d("Hello, bulk insert! (ContributionsContentProvider)"); - int uriType = uriMatcher.match(uri); - SQLiteDatabase sqlDB = dbOpenHelper.getWritableDatabase(); - sqlDB.beginTransaction(); - switch (uriType) { - case CONTRIBUTIONS: - for (ContentValues value : values) { - Timber.d("Inserting! %s", value); - sqlDB.insert(TABLE_NAME, null, value); - } - break; - default: - throw new IllegalArgumentException("Unknown URI: " + uri); - } - sqlDB.setTransactionSuccessful(); - sqlDB.endTransaction(); - getContext().getContentResolver().notifyChange(uri, null); - return values.length; - } - - @SuppressWarnings("ConstantConditions") - @Override - public int update(@NonNull 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 concatenating. - - 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; - switch (uriType) { - case CONTRIBUTIONS: - rowsUpdated = sqlDB.update(TABLE_NAME, contentValues, selection, selectionArgs); - break; - case CONTRIBUTIONS_ID: - int id = Integer.valueOf(uri.getLastPathSegment()); - - if (TextUtils.isEmpty(selection)) { - rowsUpdated = sqlDB.update(TABLE_NAME, - contentValues, - ContributionDao.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; - } -} diff --git a/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsContract.java b/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsContract.java index d62e4358a1..90120d3791 100644 --- a/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsContract.java +++ b/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsContract.java @@ -1,8 +1,6 @@ package fr.free.nrw.commons.contributions; -import android.database.Cursor; - -import androidx.loader.app.LoaderManager; +import java.util.List; import fr.free.nrw.commons.BasePresenter; import fr.free.nrw.commons.Media; @@ -22,13 +20,13 @@ public interface View { void setUploadCount(int count); - void onDataSetChanged(); - } + void showContributions(List contributionList); - public interface UserActionListener extends BasePresenter, - LoaderManager.LoaderCallbacks { + void showMessage(String localizedMessage); + } - Contribution getContributionsFromCursor(Cursor cursor); + public interface UserActionListener extends BasePresenter { + Contribution getContributionsWithTitle(String uri); void deleteUpload(Contribution contribution); diff --git a/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsFragment.java b/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsFragment.java index 32ddc4400b..7f952d3ae5 100644 --- a/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsFragment.java +++ b/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsFragment.java @@ -20,6 +20,8 @@ import androidx.fragment.app.FragmentManager.OnBackStackChangedListener; import androidx.fragment.app.FragmentTransaction; +import java.util.List; + import javax.inject.Inject; import javax.inject.Named; @@ -71,7 +73,6 @@ public class ContributionsFragment LocationUpdateListener, ICampaignsView, ContributionsContract.View { @Inject @Named("default_preferences") JsonKvStore store; - @Inject ContributionDao contributionDao; @Inject NearbyController nearbyController; @Inject OkHttpJsonApiClient okHttpJsonApiClient; @Inject CampaignsPresenter presenter; @@ -118,6 +119,7 @@ public void onServiceDisconnected(ComponentName componentName) { }; private boolean shouldShowMediaDetailsFragment; private int numberOfContributions; + private boolean isAuthCookieAcquired; @Override public void onCreate(@Nullable Bundle savedInstanceState) { @@ -210,20 +212,10 @@ public void openMediaDetail(int position) { showDetail(position); } - @Override - public int getNumberOfContributions() { - return numberOfContributions; - } - @Override public Contribution getContributionForPosition(int position) { return (Contribution) contributionsPresenter.getItemAtPosition(position); } - - @Override - public int findItemPositionWithId(String id) { - return contributionsPresenter.getChildPositionWithId(id); - } }); if(null==mediaDetailPagerFragment){ @@ -306,11 +298,10 @@ public void onBackStackChanged() { */ void onAuthCookieAcquired() { // Since we call onAuthCookieAcquired method from onAttach, isAdded is still false. So don't use it - + isAuthCookieAcquired=true; if (getActivity() != null) { // If fragment is attached to parent activity getActivity().bindService(getUploadServiceIntent(), uploadServiceConnection, Context.BIND_AUTO_CREATE); isUploadServiceConnected = true; - getActivity().getSupportLoaderManager().initLoader(0, null, contributionsPresenter); } } @@ -336,7 +327,7 @@ private void showDetail(int i) { @Override public void refreshSource() { - getActivity().getSupportLoaderManager().restartLoader(0, null, contributionsPresenter); + contributionsPresenter.fetchContributions(); } @Override @@ -411,6 +402,10 @@ public void onResume() { } fetchCampaigns(); + if(isAuthCookieAcquired){ + contributionsPresenter.fetchContributions(); + } + } private void checkPermissionsAndShowNearbyCardView() { @@ -578,9 +573,8 @@ public void setUploadCount(int count) { } @Override - public void onDataSetChanged() { - contributionsListFragment.onDataSetChanged(); - mediaDetailPagerFragment.onDataSetChanged(); + public void showContributions(List contributionList) { + contributionsListFragment.setContributions(contributionList); } /** diff --git a/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsListAdapter.java b/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsListAdapter.java index 7bad3c8dee..09dab98d16 100644 --- a/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsListAdapter.java +++ b/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsListAdapter.java @@ -6,15 +6,20 @@ import androidx.annotation.NonNull; import androidx.recyclerview.widget.RecyclerView; +import java.util.ArrayList; +import java.util.List; + import fr.free.nrw.commons.R; import fr.free.nrw.commons.contributions.model.DisplayableContribution; public class ContributionsListAdapter extends RecyclerView.Adapter { private Callback callback; + private List contributions; public ContributionsListAdapter(Callback callback) { this.callback = callback; + contributions=new ArrayList<>(); } @NonNull @@ -28,7 +33,7 @@ public ContributionViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int @Override public void onBindViewHolder(@NonNull ContributionViewHolder holder, int position) { - final Contribution contribution = callback.getContributionForPosition(position); + final Contribution contribution = contributions.get(position); DisplayableContribution displayableContribution = new DisplayableContribution(contribution, position); holder.init(position, displayableContribution); @@ -36,7 +41,12 @@ public void onBindViewHolder(@NonNull ContributionViewHolder holder, int positio @Override public int getItemCount() { - return callback.getNumberOfContributions(); + return contributions==null?0:contributions.size(); + } + + public void setContributions(List contributionList) { + this.contributions=contributionList; + notifyDataSetChanged(); } public interface Callback { @@ -47,10 +57,6 @@ public interface Callback { void openMediaDetail(int contribution); - int getNumberOfContributions(); - Contribution getContributionForPosition(int position); - - int findItemPositionWithId(String lastVisibleItemID); } } diff --git a/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsListFragment.java b/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsListFragment.java index de564196f6..8a684ef44b 100644 --- a/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsListFragment.java +++ b/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsListFragment.java @@ -20,6 +20,8 @@ import com.google.android.material.floatingactionbutton.FloatingActionButton; +import java.util.List; + import javax.inject.Inject; import javax.inject.Named; @@ -72,6 +74,13 @@ public class ContributionsListFragment extends CommonsDaggerSupportFragment { private String lastVisibleItemID; private int SPAN_COUNT=3; + private List contributions; + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setRetainInstance(true); + } public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_contributions_list, container, false); @@ -178,16 +187,9 @@ public void showNoContributionsUI(boolean shouldShow) { noContributionsYet.setVisibility(shouldShow ? VISIBLE : GONE); } - public void onDataSetChanged() { - if (null != adapter) { - adapter.notifyDataSetChanged(); - //Restoring last visible item position in cases of orientation change - if (null != lastVisibleItemID) { - int itemPositionWithId = callback.findItemPositionWithId(lastVisibleItemID); - rvContributionsList.scrollToPosition(itemPositionWithId); - lastVisibleItemID = null;//Reset the lastVisibleItemID once we have used it - } - } + public void setContributions(List contributionList) { + this.contributions=contributionList; + adapter.setContributions(contributionList); } public interface SourceRefresher { @@ -228,7 +230,7 @@ public void onViewStateRestored(@Nullable Bundle savedInstanceState) { private String findIdOfItemWithPosition(int position) { Contribution contributionForPosition = callback.getContributionForPosition(position); if (null != contributionForPosition) { - return contributionForPosition.getContentUri().getLastPathSegment(); + return contributionForPosition.getFilename(); } return null; } diff --git a/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsLocalDataSource.java b/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsLocalDataSource.java index 672d8ba6b2..a4e9ee13fa 100644 --- a/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsLocalDataSource.java +++ b/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsLocalDataSource.java @@ -1,10 +1,11 @@ package fr.free.nrw.commons.contributions; -import android.database.Cursor; +import java.util.List; import javax.inject.Inject; import javax.inject.Named; +import fr.free.nrw.commons.db.AppDatabase; import fr.free.nrw.commons.kvstore.JsonKvStore; /** @@ -12,15 +13,15 @@ */ class ContributionsLocalDataSource { - private final ContributionDao contributionsDao; + private final ContributionDao contributionDao; private final JsonKvStore defaultKVStore; @Inject public ContributionsLocalDataSource( @Named("default_preferences") JsonKvStore defaultKVStore, - ContributionDao contributionDao) { + AppDatabase appDatabase) { this.defaultKVStore = defaultKVStore; - this.contributionsDao = contributionDao; + this.contributionDao = appDatabase.getContributionDao(); } /** @@ -32,11 +33,15 @@ public int get(String key) { /** * Get contribution object from cursor - * @param cursor + * @param uri * @return */ - public Contribution getContributionFromCursor(Cursor cursor) { - return contributionsDao.fromCursor(cursor); + public Contribution getContributionWithFileName(String uri) { + List contributionWithUri = contributionDao.getContributionWithTitle(uri); + if(null!=contributionWithUri && contributionWithUri.size()>0){ + return contributionWithUri.get(0); + } + return null; } /** @@ -44,6 +49,6 @@ public Contribution getContributionFromCursor(Cursor cursor) { * @param contribution */ public void deleteContribution(Contribution contribution) { - contributionsDao.delete(contribution); + contributionDao.delete(contribution); } } diff --git a/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsPresenter.java b/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsPresenter.java index cfb848c0fd..3d2fe98cf9 100644 --- a/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsPresenter.java +++ b/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsPresenter.java @@ -3,104 +3,112 @@ import android.content.Context; import android.database.Cursor; import android.database.DataSetObserver; -import android.os.Bundle; -import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import androidx.loader.content.CursorLoader; -import androidx.loader.content.Loader; + +import java.util.ArrayList; +import java.util.List; import javax.inject.Inject; +import fr.free.nrw.commons.CommonsApplication; import fr.free.nrw.commons.Media; +import fr.free.nrw.commons.auth.SessionManager; import fr.free.nrw.commons.contributions.ContributionsContract.UserActionListener; +import fr.free.nrw.commons.db.AppDatabase; +import fr.free.nrw.commons.mwapi.UserClient; +import fr.free.nrw.commons.utils.NetworkUtils; +import io.reactivex.Observable; +import io.reactivex.Scheduler; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.disposables.CompositeDisposable; +import io.reactivex.schedulers.Schedulers; import timber.log.Timber; -import static fr.free.nrw.commons.contributions.ContributionDao.Table.ALL_FIELDS; -import static fr.free.nrw.commons.contributions.ContributionsContentProvider.BASE_URI; -import static fr.free.nrw.commons.settings.Prefs.UPLOADS_SHOWING; +import static fr.free.nrw.commons.contributions.Contribution.STATE_COMPLETED; /** * The presenter class for Contributions */ -public class ContributionsPresenter extends DataSetObserver implements UserActionListener { +public class ContributionsPresenter implements UserActionListener { private final ContributionsRepository repository; + private CompositeDisposable compositeDisposable; private ContributionsContract.View view; - private Cursor cursor; + private List contributionList; @Inject Context context; + @Inject + UserClient userClient; + + @Inject + AppDatabase appDatabase; + + @Inject + SessionManager sessionManager; + @Inject ContributionsPresenter(ContributionsRepository repository) { this.repository = repository; + compositeDisposable=new CompositeDisposable(); } + private String user; + @Override public void onAttachView(ContributionsContract.View view) { this.view = view; - if (null != cursor) { - try { - cursor.registerDataSetObserver(this); - } catch (IllegalStateException e) {//Cursor might be already registered - Timber.d(e); - } - } - } - - @Override - public void onDetachView() { - this.view = null; - if (null != cursor) { - try { - cursor.unregisterDataSetObserver(this); - } catch (Exception e) {//Cursor might not be already registered - Timber.d(e); - } - } - } - - @NonNull - @Override - public Loader onCreateLoader(int id, @Nullable Bundle args) { - int preferredNumberOfUploads = repository.get(UPLOADS_SHOWING); - return new CursorLoader(context, BASE_URI, - ALL_FIELDS, "", null, - ContributionDao.CONTRIBUTION_SORT + "LIMIT " - + (preferredNumberOfUploads>0?preferredNumberOfUploads:100)); + compositeDisposable=new CompositeDisposable(); } - @Override - public void onLoadFinished(@NonNull Loader loader, Cursor cursor) { - view.showProgress(false); - if (null != cursor && cursor.getCount() > 0) { - view.showWelcomeTip(false); - view.showNoContributionsUI(false); - view.setUploadCount(cursor.getCount()); - } else { - view.showWelcomeTip(true); - view.showNoContributionsUI(true); + void fetchContributions() { + if (NetworkUtils.isInternetConnectionEstablished(CommonsApplication.getInstance())) { + view.showProgress(true); + this.user = sessionManager.getUserName(); + view.showContributions(null); + contributionList=new ArrayList<>(); + compositeDisposable.add(userClient.logEvents(user) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .doOnNext(mwQueryLogEvent -> Timber.d("Received image %s", mwQueryLogEvent.title())) + .filter(mwQueryLogEvent -> !mwQueryLogEvent.isDeleted()).doOnNext(mwQueryLogEvent -> Timber.d("Image %s passed filters", mwQueryLogEvent.title())) + .map(image -> new Contribution(null, null, image.title(), + "", -1, image.date(), image.date(), user, + "", "", STATE_COMPLETED)).buffer(100) + .subscribe(imageValues -> { + this.contributionList.addAll(imageValues); + view.showProgress(false); + if (imageValues != null && imageValues.size() > 0) { + view.showWelcomeTip(false); + view.showNoContributionsUI(false); + view.setUploadCount(imageValues.size()); + view.showContributions(contributionList); + } else { + view.showWelcomeTip(true); + view.showNoContributionsUI(true); + } + Observable.fromIterable(contributionList) + .subscribeOn(Schedulers.io()) + .doOnEach(imageValue -> appDatabase.getContributionDao().save(imageValue.getValue())); + }, error -> { + view.showProgress(false); + view.showMessage(error.getLocalizedMessage()); + //TODO show error + })); } - swapCursor(cursor); } @Override - public void onLoaderReset(@NonNull Loader loader) { - this.cursor = null; - //On LoadFinished is not guaranteed to be called - view.showProgress(false); - view.showWelcomeTip(true); - view.showNoContributionsUI(true); - swapCursor(null); + public void onDetachView() { + this.view = null; + compositeDisposable.clear(); } - /** - * Get contribution from the repository - */ @Override - public Contribution getContributionsFromCursor(Cursor cursor) { - return repository.getContributionFromCursor(cursor); + public Contribution getContributionsWithTitle(String title) { + return repository.getContributionWithFileName(title); } /** @@ -120,64 +128,18 @@ public void deleteUpload(Contribution contribution) { @Nullable @Override public Media getItemAtPosition(int i) { - if (null != cursor && cursor.moveToPosition(i)) { - return getContributionsFromCursor(cursor); - } - return null; + return contributionList==null?null:contributionList.get(i); } /** * Get contribution position with id */ - public int getChildPositionWithId(String id) { - int position = 0; - cursor.moveToFirst(); - while (null != cursor && cursor.moveToNext()) { - if (getContributionsFromCursor(cursor).getContentUri().getLastPathSegment() - .equals(id)) { - position = cursor.getPosition(); - break; - } - } - return position; - } - - @Override - public void onChanged() { - super.onChanged(); - view.onDataSetChanged(); - } - - @Override - public void onInvalidated() { - super.onInvalidated(); - //Not letting the view know of this as of now, TODO discuss how to handle this and maybe show a proper ui for this - } - - /** - * Swap in a new Cursor, returning the old Cursor. The returned old Cursor is not - * closed. - * - * @param newCursor The new cursor to be used. - * @return Returns the previously set Cursor, or null if there was not one. If the given new - * Cursor is the same instance is the previously set Cursor, null is also returned. - */ - private void swapCursor(Cursor newCursor) { - try { - if (newCursor == cursor) { - return; - } - Cursor oldCursor = cursor; - if (oldCursor != null) { - oldCursor.unregisterDataSetObserver(this); - } - cursor = newCursor; - if (newCursor != null) { - newCursor.registerDataSetObserver(this); + public int getChildPositionWithId(String fileName) { + for (Contribution contribution : contributionList) { + if (contribution.getFilename().equals(fileName)) { + return contributionList.indexOf(contribution); } - view.onDataSetChanged(); - } catch (IllegalStateException e) {//Cursor might [not] be already registered/unregistered - Timber.e(e); } + return -1; } } diff --git a/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsRepository.java b/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsRepository.java index 4c479e3000..06e8404a49 100644 --- a/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsRepository.java +++ b/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsRepository.java @@ -1,7 +1,5 @@ package fr.free.nrw.commons.contributions; -import android.database.Cursor; - import javax.inject.Inject; /** @@ -23,16 +21,6 @@ public int get(String uploadsShowing) { return localDataSource.get(uploadsShowing); } - - /** - * Get contribution object from cursor from LocalDataSource - * @param cursor - * @return - */ - public Contribution getContributionFromCursor(Cursor cursor) { - return localDataSource.getContributionFromCursor(cursor); - } - /** * Deletes a failed upload from DB * @param contribution @@ -40,4 +28,13 @@ public Contribution getContributionFromCursor(Cursor cursor) { public void deleteContributionFromDB(Contribution contribution) { localDataSource.deleteContribution(contribution); } + + /** + * Get contribution object with title + * @param fileName + * @return + */ + public Contribution getContributionWithFileName(String fileName) { + return localDataSource.getContributionWithFileName(fileName); + } } diff --git a/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsSyncAdapter.java b/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsSyncAdapter.java deleted file mode 100644 index 4ce126f37a..0000000000 --- a/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsSyncAdapter.java +++ /dev/null @@ -1,84 +0,0 @@ -package fr.free.nrw.commons.contributions; - -import android.accounts.Account; -import android.annotation.SuppressLint; -import android.content.AbstractThreadedSyncAdapter; -import android.content.ContentProviderClient; -import android.content.ContentValues; -import android.content.Context; -import android.content.SyncResult; -import android.database.Cursor; -import android.os.Bundle; -import android.os.RemoteException; - -import javax.inject.Inject; -import javax.inject.Named; - -import fr.free.nrw.commons.di.ApplicationlessInjection; -import fr.free.nrw.commons.kvstore.JsonKvStore; -import fr.free.nrw.commons.mwapi.UserClient; -import timber.log.Timber; - -import static fr.free.nrw.commons.contributions.Contribution.STATE_COMPLETED; -import static fr.free.nrw.commons.contributions.ContributionDao.Table.COLUMN_FILENAME; -import static fr.free.nrw.commons.contributions.ContributionsContentProvider.BASE_URI; - -@SuppressWarnings("WeakerAccess") -public class ContributionsSyncAdapter extends AbstractThreadedSyncAdapter { - - private static final String[] existsQuery = {COLUMN_FILENAME}; - private static final String existsSelection = COLUMN_FILENAME + " = ?"; - private static final ContentValues[] EMPTY = {}; - - @Inject - UserClient userClient; - @Inject - @Named("default_preferences") - JsonKvStore defaultKvStore; - - public ContributionsSyncAdapter(Context context, boolean autoInitialize) { - super(context, autoInitialize); - } - - private boolean fileExists(ContentProviderClient client, String filename) { - if (filename == null) { - return false; - } - try (Cursor cursor = client.query(BASE_URI, - existsQuery, - existsSelection, - new String[]{filename}, - "" - )) { - return cursor != null && cursor.getCount() != 0; - } catch (RemoteException e) { - throw new RuntimeException(e); - } - } - - @SuppressLint("CheckResult") - @Override - public void onPerformSync(Account account, Bundle bundle, String authority, - ContentProviderClient contentProviderClient, SyncResult syncResult) { - ApplicationlessInjection - .getInstance(getContext() - .getApplicationContext()) - .getCommonsApplicationComponent() - .inject(this); - // This code is(was?) fraught with possibilities of race conditions, but lalalalala I can't hear you! - String user = account.name; - ContributionDao contributionDao = new ContributionDao(() -> contentProviderClient); - userClient.logEvents(user) - .doOnNext(mwQueryLogEvent->Timber.d("Received image %s", mwQueryLogEvent.title() )) - .filter(mwQueryLogEvent -> !mwQueryLogEvent.isDeleted()) - .filter(mwQueryLogEvent -> !fileExists(contentProviderClient, mwQueryLogEvent.title())) - .doOnNext(mwQueryLogEvent->Timber.d("Image %s passed filters", mwQueryLogEvent.title() )) - .map(image -> new Contribution(null, null, image.title(), - "", -1, image.date(), image.date(), user, - "", "", STATE_COMPLETED)) - .map(contributionDao::toContentValues) - .buffer(10) - .subscribe(imageValues->contentProviderClient.bulkInsert(BASE_URI, imageValues.toArray(EMPTY))); - Timber.d("Oh hai, everyone! Look, a kitty!"); - } -} diff --git a/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsSyncService.java b/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsSyncService.java deleted file mode 100644 index 946da69158..0000000000 --- a/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsSyncService.java +++ /dev/null @@ -1,27 +0,0 @@ -package fr.free.nrw.commons.contributions; - -import android.app.Service; -import android.content.Intent; -import android.os.IBinder; - -public class ContributionsSyncService extends Service { - - private static final Object sSyncAdapterLock = new Object(); - - private static ContributionsSyncAdapter sSyncAdapter = null; - - @Override - public void onCreate() { - super.onCreate(); - synchronized (sSyncAdapterLock) { - if (sSyncAdapter == null) { - sSyncAdapter = new ContributionsSyncAdapter(this, true); - } - } - } - - @Override - public IBinder onBind(Intent intent) { - return sSyncAdapter.getSyncAdapterBinder(); - } -} diff --git a/app/src/main/java/fr/free/nrw/commons/contributions/MainActivity.java b/app/src/main/java/fr/free/nrw/commons/contributions/MainActivity.java index 96c32d5c46..eff6cc2ce2 100644 --- a/app/src/main/java/fr/free/nrw/commons/contributions/MainActivity.java +++ b/app/src/main/java/fr/free/nrw/commons/contributions/MainActivity.java @@ -112,8 +112,6 @@ protected void onSaveInstanceState(Bundle outState) { private void initMain() { //Do not remove this, this triggers the sync service - ContentResolver.setSyncAutomatically(sessionManager.getCurrentAccount(),BuildConfig.CONTRIBUTION_AUTHORITY,true); - requestSync(sessionManager.getCurrentAccount(), BuildConfig.CONTRIBUTION_AUTHORITY, new Bundle()); Intent uploadServiceIntent = new Intent(this, UploadService.class); uploadServiceIntent.setAction(UploadService.ACTION_START_SERVICE); startService(uploadServiceIntent); diff --git a/app/src/main/java/fr/free/nrw/commons/data/DBOpenHelper.java b/app/src/main/java/fr/free/nrw/commons/data/DBOpenHelper.java index aaade6277f..c5498e4566 100644 --- a/app/src/main/java/fr/free/nrw/commons/data/DBOpenHelper.java +++ b/app/src/main/java/fr/free/nrw/commons/data/DBOpenHelper.java @@ -7,7 +7,6 @@ import fr.free.nrw.commons.bookmarks.locations.BookmarkLocationsDao; import fr.free.nrw.commons.bookmarks.pictures.BookmarkPicturesDao; import fr.free.nrw.commons.category.CategoryDao; -import fr.free.nrw.commons.contributions.ContributionDao; import fr.free.nrw.commons.explore.recentsearches.RecentSearchesDao; public class DBOpenHelper extends SQLiteOpenHelper { @@ -25,7 +24,6 @@ public DBOpenHelper(Context context) { @Override public void onCreate(SQLiteDatabase sqLiteDatabase) { - ContributionDao.Table.onCreate(sqLiteDatabase); CategoryDao.Table.onCreate(sqLiteDatabase); BookmarkPicturesDao.Table.onCreate(sqLiteDatabase); BookmarkLocationsDao.Table.onCreate(sqLiteDatabase); @@ -34,7 +32,6 @@ public void onCreate(SQLiteDatabase sqLiteDatabase) { @Override public void onUpgrade(SQLiteDatabase sqLiteDatabase, int from, int to) { - ContributionDao.Table.onUpdate(sqLiteDatabase, from, to); CategoryDao.Table.onUpdate(sqLiteDatabase, from, to); BookmarkPicturesDao.Table.onUpdate(sqLiteDatabase, from, to); BookmarkLocationsDao.Table.onUpdate(sqLiteDatabase, from, to); diff --git a/app/src/main/java/fr/free/nrw/commons/db/AppDatabase.java b/app/src/main/java/fr/free/nrw/commons/db/AppDatabase.java new file mode 100644 index 0000000000..fefb69ae28 --- /dev/null +++ b/app/src/main/java/fr/free/nrw/commons/db/AppDatabase.java @@ -0,0 +1,14 @@ +package fr.free.nrw.commons.db; + +import androidx.room.Database; +import androidx.room.RoomDatabase; +import androidx.room.TypeConverters; + +import fr.free.nrw.commons.contributions.Contribution; +import fr.free.nrw.commons.contributions.ContributionDao; + +@Database(entities = {Contribution.class}, version = 1) +@TypeConverters({Converters.class}) +abstract public class AppDatabase extends RoomDatabase { + public abstract ContributionDao getContributionDao(); +} diff --git a/app/src/main/java/fr/free/nrw/commons/db/Converters.java b/app/src/main/java/fr/free/nrw/commons/db/Converters.java new file mode 100644 index 0000000000..8a3c60b4fa --- /dev/null +++ b/app/src/main/java/fr/free/nrw/commons/db/Converters.java @@ -0,0 +1,67 @@ +package fr.free.nrw.commons.db; + +import android.net.Uri; + +import androidx.room.TypeConverter; + +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; + +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; + +import fr.free.nrw.commons.location.LatLng; + +public class Converters { + @TypeConverter + public static Date fromTimestamp(Long value) { + return value == null ? null : new Date(value); + } + + @TypeConverter + public static Long dateToTimestamp(Date date) { + return date == null ? null : date.getTime(); + } + + @TypeConverter + public static Uri fromString(String value) { + return value == null ? null : Uri.parse(value); + } + + @TypeConverter + public static String uriToString(Uri uri) { + return uri == null ? null : uri.toString(); + } + + @TypeConverter + public static String listObjectToString(ArrayList objectList) { + return objectList == null ? null : new Gson().toJson(objectList); + } + + @TypeConverter + public static ArrayList stringToArrayListObject(String objectList) { + return objectList == null ? null : new Gson().fromJson(objectList,new TypeToken>(){}.getType()); + } + + @TypeConverter + public static String mapObjectToString(HashMap objectList) { + return objectList == null ? null : new Gson().toJson(objectList); + } + + @TypeConverter + public static HashMap stringToMap(String objectList) { + return objectList == null ? null : new Gson().fromJson(objectList,new TypeToken>(){}.getType()); + } + + @TypeConverter + public static String latlngObjectToString(LatLng latlng) { + return latlng == null ? null : new Gson().toJson(latlng); + } + + @TypeConverter + public static LatLng stringToLatLng(String objectList) { + return objectList == null ? null : new Gson().fromJson(objectList,LatLng.class); + } + +} diff --git a/app/src/main/java/fr/free/nrw/commons/di/CommonsApplicationComponent.java b/app/src/main/java/fr/free/nrw/commons/di/CommonsApplicationComponent.java index 242f889df0..83c0154afd 100644 --- a/app/src/main/java/fr/free/nrw/commons/di/CommonsApplicationComponent.java +++ b/app/src/main/java/fr/free/nrw/commons/di/CommonsApplicationComponent.java @@ -10,7 +10,6 @@ import fr.free.nrw.commons.auth.LoginActivity; import fr.free.nrw.commons.contributions.ContributionViewHolder; import fr.free.nrw.commons.contributions.ContributionsModule; -import fr.free.nrw.commons.contributions.ContributionsSyncAdapter; import fr.free.nrw.commons.nearby.PlaceRenderer; import fr.free.nrw.commons.review.ReviewController; import fr.free.nrw.commons.settings.SettingsFragment; @@ -33,8 +32,6 @@ public interface CommonsApplicationComponent extends AndroidInjector { void inject(CommonsApplication application); - void inject(ContributionsSyncAdapter syncAdapter); - void inject(LoginActivity activity); void inject(SettingsFragment fragment); diff --git a/app/src/main/java/fr/free/nrw/commons/di/CommonsApplicationModule.java b/app/src/main/java/fr/free/nrw/commons/di/CommonsApplicationModule.java index f1a2ef5396..04a2e04717 100644 --- a/app/src/main/java/fr/free/nrw/commons/di/CommonsApplicationModule.java +++ b/app/src/main/java/fr/free/nrw/commons/di/CommonsApplicationModule.java @@ -6,6 +6,7 @@ import android.view.inputmethod.InputMethodManager; import androidx.collection.LruCache; +import androidx.room.Room; import com.github.varunpant.quadtree.QuadTree; import com.google.gson.Gson; @@ -29,6 +30,7 @@ import fr.free.nrw.commons.auth.SessionManager; import fr.free.nrw.commons.caching.CacheController; import fr.free.nrw.commons.data.DBOpenHelper; +import fr.free.nrw.commons.db.AppDatabase; import fr.free.nrw.commons.kvstore.JsonKvStore; import fr.free.nrw.commons.location.LocationServiceManager; import fr.free.nrw.commons.settings.Prefs; @@ -209,4 +211,9 @@ public String provideLoggedInUsername() { public QuadTree providesQuadTres() { return new QuadTree<>(-180, -90, +180, +90); } + + @Provides + public AppDatabase provideAppDataBase() { + return Room.databaseBuilder(applicationContext, AppDatabase.class, "commons_room.db").build(); + } } \ No newline at end of file diff --git a/app/src/main/java/fr/free/nrw/commons/di/ContentProviderBuilderModule.java b/app/src/main/java/fr/free/nrw/commons/di/ContentProviderBuilderModule.java index 10c0cfcb14..e508bcd2ed 100644 --- a/app/src/main/java/fr/free/nrw/commons/di/ContentProviderBuilderModule.java +++ b/app/src/main/java/fr/free/nrw/commons/di/ContentProviderBuilderModule.java @@ -5,16 +5,12 @@ import fr.free.nrw.commons.bookmarks.locations.BookmarkLocationsContentProvider; import fr.free.nrw.commons.bookmarks.pictures.BookmarkPicturesContentProvider; import fr.free.nrw.commons.category.CategoryContentProvider; -import fr.free.nrw.commons.contributions.ContributionsContentProvider; import fr.free.nrw.commons.explore.recentsearches.RecentSearchesContentProvider; @Module @SuppressWarnings({"WeakerAccess", "unused"}) public abstract class ContentProviderBuilderModule { - @ContributesAndroidInjector - abstract ContributionsContentProvider bindContributionsContentProvider(); - @ContributesAndroidInjector abstract CategoryContentProvider bindCategoryContentProvider(); diff --git a/app/src/main/java/fr/free/nrw/commons/upload/UploadService.java b/app/src/main/java/fr/free/nrw/commons/upload/UploadService.java index 306a01c980..0a74184336 100644 --- a/app/src/main/java/fr/free/nrw/commons/upload/UploadService.java +++ b/app/src/main/java/fr/free/nrw/commons/upload/UploadService.java @@ -28,10 +28,11 @@ import fr.free.nrw.commons.auth.SessionManager; import fr.free.nrw.commons.contributions.Contribution; import fr.free.nrw.commons.contributions.ContributionDao; -import fr.free.nrw.commons.contributions.ContributionsContentProvider; import fr.free.nrw.commons.contributions.MainActivity; +import fr.free.nrw.commons.db.AppDatabase; import fr.free.nrw.commons.media.MediaClient; import fr.free.nrw.commons.utils.CommonsDateUtil; +import fr.free.nrw.commons.utils.ExecutorUtils; import fr.free.nrw.commons.wikidata.WikidataEditService; import io.reactivex.Observable; import io.reactivex.schedulers.Schedulers; @@ -46,10 +47,10 @@ public class UploadService extends HandlerService { public static final String ACTION_START_SERVICE = EXTRA_PREFIX + ".upload"; public static final String EXTRA_SOURCE = EXTRA_PREFIX + ".source"; public static final String EXTRA_FILES = EXTRA_PREFIX + ".files"; - @Inject WikidataEditService wikidataEditService; @Inject SessionManager sessionManager; - @Inject ContributionDao contributionDao; + @Inject + AppDatabase appDatabase; @Inject UploadClient uploadClient; @Inject MediaClient mediaClient; @@ -105,7 +106,7 @@ public void onProgress(long transferred, long total) { notificationManager.notify(notificationTag, NOTIFICATION_UPLOAD_IN_PROGRESS, curNotification.build()); contribution.setTransferred(transferred); - contributionDao.save(contribution); + ExecutorUtils.get().submit(() -> appDatabase.getContributionDao().save(contribution)); } } @@ -143,7 +144,7 @@ public void queue(int what, Contribution contribution) { contribution.setState(Contribution.STATE_QUEUED); contribution.setTransferred(0); - contributionDao.save(contribution); + ExecutorUtils.get().submit(() -> appDatabase.getContributionDao().save(contribution)); toUpload++; if (curNotification != null && toUpload != 1) { curNotification.setContentText(getResources().getQuantityString(R.plurals.uploads_pending_notification_indicator, toUpload, toUpload)); @@ -163,16 +164,7 @@ public void queue(int what, Contribution contribution) { @Override public int onStartCommand(Intent intent, int flags, int startId) { if (ACTION_START_SERVICE.equals(intent.getAction()) && freshStart) { - ContentValues failedValues = new ContentValues(); - failedValues.put(ContributionDao.Table.COLUMN_STATE, Contribution.STATE_FAILED); - - int updated = getContentResolver().update(ContributionsContentProvider.BASE_URI, - failedValues, - ContributionDao.Table.COLUMN_STATE + " = ? OR " + ContributionDao.Table.COLUMN_STATE + " = ?", - new String[]{ String.valueOf(Contribution.STATE_QUEUED), String.valueOf(Contribution.STATE_IN_PROGRESS) } - ); - Timber.d("Set %d uploads to failed", updated); - Timber.d("Flags is %d id is %d", flags, startId); + ExecutorUtils.get().submit(() -> appDatabase.getContributionDao().updateStates(Contribution.STATE_FAILED,new int[]{Contribution.STATE_QUEUED,Contribution.STATE_IN_PROGRESS})); freshStart = false; } return START_REDELIVER_INTENT; @@ -272,7 +264,7 @@ private void uploadContribution(Contribution contribution) { contribution.setState(Contribution.STATE_COMPLETED); contribution.setDateUploaded(CommonsDateUtil.getIso8601DateFormatShort() .parse(uploadResult.getImageinfo().getTimestamp())); - contributionDao.save(contribution); + ExecutorUtils.get().submit(() -> appDatabase.getContributionDao().save(contribution)); } }, throwable -> { Timber.w(throwable, "Exception during upload"); @@ -291,7 +283,7 @@ private void showFailedNotification(Contribution contribution) { notificationManager.notify(contribution.getLocalUri().toString(), NOTIFICATION_UPLOAD_FAILED, curNotification.build()); contribution.setState(Contribution.STATE_FAILED); - contributionDao.save(contribution); + ExecutorUtils.get().submit(() -> appDatabase.getContributionDao().save(contribution)); } private String findUniqueFilename(String fileName) throws IOException { diff --git a/app/src/main/java/fr/free/nrw/commons/utils/ExecutorUtils.java b/app/src/main/java/fr/free/nrw/commons/utils/ExecutorUtils.java index 57ed86eebb..5ea4a237bc 100644 --- a/app/src/main/java/fr/free/nrw/commons/utils/ExecutorUtils.java +++ b/app/src/main/java/fr/free/nrw/commons/utils/ExecutorUtils.java @@ -4,6 +4,7 @@ import android.os.Looper; import java.util.concurrent.Executor; +import java.util.concurrent.ExecutorService; public class ExecutorUtils { @@ -19,4 +20,10 @@ public static Executor uiExecutor() { return uiExecutor; } + private static final ExecutorService executor = java.util.concurrent.Executors.newFixedThreadPool(3); + + public static ExecutorService get() { + return executor; + } + } diff --git a/app/src/test/kotlin/fr/free/nrw/commons/contributions/ContributionsPresenterTest.kt b/app/src/test/kotlin/fr/free/nrw/commons/contributions/ContributionsPresenterTest.kt index 2dee682c81..9b20593452 100644 --- a/app/src/test/kotlin/fr/free/nrw/commons/contributions/ContributionsPresenterTest.kt +++ b/app/src/test/kotlin/fr/free/nrw/commons/contributions/ContributionsPresenterTest.kt @@ -47,7 +47,7 @@ class ContributionsPresenterTest { */ @Test fun testGetContributionFromCursor() { - contributionsPresenter?.getContributionsFromCursor(cursor) + contributionsPresenter?.getContributionsWithTitle(cursor) verify(repository)?.getContributionFromCursor(cursor) } diff --git a/captures/fr.free.nrw.commons.beta_2020.01.13_11.01.li b/captures/fr.free.nrw.commons.beta_2020.01.13_11.01.li new file mode 100644 index 0000000000000000000000000000000000000000..3d87b4a497ceecc39133190a44232e31d66582d3 GIT binary patch literal 722867 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