From 15107e622b655d865079dc636d54ec55727b8d10 Mon Sep 17 00:00:00 2001 From: Paul Hawke Date: Sun, 3 Sep 2017 17:55:45 -0500 Subject: [PATCH] Codacy suggestions for improvement. --- .../free/nrw/commons/CommonsApplication.java | 6 +- .../java/fr/free/nrw/commons/LicenseList.java | 40 ++---- .../main/java/fr/free/nrw/commons/Media.java | 136 +++++++++--------- .../commons/auth/AuthenticatedActivity.java | 11 +- .../auth/WikiAccountAuthenticator.java | 44 +++--- .../category/CategoryContentProvider.java | 41 +++--- .../contributions/ContributionController.java | 69 +++++---- .../contributions/ContributionsActivity.java | 118 ++++++++------- .../ContributionsContentProvider.java | 75 ++++++---- .../ContributionsListFragment.java | 44 +++--- .../ContributionsSyncAdapter.java | 46 +++--- .../media/MediaDetailPagerFragment.java | 116 +++++++-------- .../nrw/commons/nearby/NearbyInfoDialog.java | 4 +- 13 files changed, 405 insertions(+), 345 deletions(-) diff --git a/app/src/main/java/fr/free/nrw/commons/CommonsApplication.java b/app/src/main/java/fr/free/nrw/commons/CommonsApplication.java index f3494d46f..4c44f00f3 100644 --- a/app/src/main/java/fr/free/nrw/commons/CommonsApplication.java +++ b/app/src/main/java/fr/free/nrw/commons/CommonsApplication.java @@ -220,10 +220,8 @@ public class CommonsApplication extends Application { setIndex(getIndex() + 1); try { - if (accountManagerFuture != null) { - if (accountManagerFuture.getResult()) { - Timber.d("Account removed successfully."); - } + if (accountManagerFuture != null && accountManagerFuture.getResult()) { + Timber.d("Account removed successfully."); } } catch (OperationCanceledException | IOException | AuthenticatorException e) { e.printStackTrace(); diff --git a/app/src/main/java/fr/free/nrw/commons/LicenseList.java b/app/src/main/java/fr/free/nrw/commons/LicenseList.java index 28d5b3f34..382ceee3f 100644 --- a/app/src/main/java/fr/free/nrw/commons/LicenseList.java +++ b/app/src/main/java/fr/free/nrw/commons/LicenseList.java @@ -10,18 +10,16 @@ import java.util.Collection; import java.util.HashMap; import java.util.Locale; import java.util.Map; -import java.util.Set; public class LicenseList { - Map licenses = new HashMap<>(); - Resources res; - - private static String XMLNS_LICENSE = "https://www.mediawiki.org/wiki/Extension:UploadWizard/xmlns/licenses"; + private Map licenses = new HashMap<>(); + private Resources res; public LicenseList(Activity activity) { res = activity.getResources(); XmlPullParser parser = res.getXml(R.xml.wikimedia_licenses); - while (Utils.xmlFastForward(parser, XMLNS_LICENSE, "license")) { + String namespace = "https://www.mediawiki.org/wiki/Extension:UploadWizard/xmlns/licenses"; + while (Utils.xmlFastForward(parser, namespace, "license")) { String id = parser.getAttributeValue(null, "id"); String template = parser.getAttributeValue(null, "template"); String url = parser.getAttributeValue(null, "url"); @@ -31,10 +29,6 @@ public class LicenseList { } } - public Set keySet() { - return licenses.keySet(); - } - public Collection values() { return licenses.values(); } @@ -44,7 +38,7 @@ public class LicenseList { } @Nullable - public License licenseForTemplate(String template) { + License licenseForTemplate(String template) { String ucTemplate = new PageTitle(template).getDisplayText(); for (License license : values()) { if (ucTemplate.equals(new PageTitle(license.getTemplate()).getDisplayText())) { @@ -54,26 +48,16 @@ public class LicenseList { return null; } - public String nameIdForTemplate(String template) { + private String nameIdForTemplate(String template) { // hack :D (converts dashes and periods to underscores) // cc-by-sa-3.0 -> cc_by_sa_3_0 - return "license_name_" + template.toLowerCase(Locale.ENGLISH).replace("-", "_").replace(".", "_"); + return "license_name_" + template.toLowerCase(Locale.ENGLISH).replace("-", + "_").replace(".", "_"); } - private int stringIdByName(String stringId) { - return res.getIdentifier("fr.free.nrw.commons:string/" + stringId, null, null); - } - - public String nameForTemplate(String template) { - //Log.d("Commons", "LicenseList.nameForTemplate: template: " + template); - String stringId = nameIdForTemplate(template); - //Log.d("Commons", "LicenseList.nameForTemplate: stringId: " + stringId); - int nameId = stringIdByName(stringId); - //Log.d("Commons", "LicenseList.nameForTemplate: nameId: " + nameId); - if(nameId != 0) { - //Log.d("Commons", "LicenseList.nameForTemplate: name: " + name); - return res.getString(nameId); - } - return template; + private String nameForTemplate(String template) { + int nameId = res.getIdentifier("fr.free.nrw.commons:string/" + + nameIdForTemplate(template), null, null); + return (nameId != 0) ? res.getString(nameId) : template; } } \ No newline at end of file diff --git a/app/src/main/java/fr/free/nrw/commons/Media.java b/app/src/main/java/fr/free/nrw/commons/Media.java index 1d07e9c16..26a1d038b 100644 --- a/app/src/main/java/fr/free/nrw/commons/Media.java +++ b/app/src/main/java/fr/free/nrw/commons/Media.java @@ -29,12 +29,66 @@ public class Media implements Parcelable { } }; + private static Pattern displayTitlePattern = Pattern.compile("(.*)(\\.\\w+)", Pattern.CASE_INSENSITIVE); + // Primary metadata fields + protected Uri localUri; + protected String imageUrl; + protected String filename; + protected String description; // monolingual description on input... + protected long dataLength; + protected Date dateCreated; + protected @Nullable Date dateUploaded; + protected int width; + protected int height; + protected String license; + protected String creator; + protected ArrayList categories; // as loaded at runtime? + private Map descriptions; // multilingual descriptions as loaded + private HashMap tags = new HashMap<>(); + private @Nullable LatLng coordinates; + protected Media() { this.categories = new ArrayList<>(); this.descriptions = new HashMap<>(); } - private HashMap tags = new HashMap<>(); + public Media(String filename) { + this(); + this.filename = filename; + } + + public Media(Uri localUri, String imageUrl, String filename, String description, + long dataLength, Date dateCreated, @Nullable Date dateUploaded, String creator) { + this(); + this.localUri = localUri; + this.imageUrl = imageUrl; + this.filename = filename; + this.description = description; + this.dataLength = dataLength; + this.dateCreated = dateCreated; + this.dateUploaded = dateUploaded; + this.creator = creator; + } + + @SuppressWarnings("unchecked") + public Media(Parcel in) { + localUri = in.readParcelable(Uri.class.getClassLoader()); + imageUrl = in.readString(); + filename = in.readString(); + description = in.readString(); + dataLength = in.readLong(); + dateCreated = (Date) in.readSerializable(); + dateUploaded = (Date) in.readSerializable(); + creator = in.readString(); + tags = (HashMap) in.readSerializable(); + width = in.readInt(); + height = in.readInt(); + license = in.readString(); + if (categories != null) { + in.readStringList(categories); + } + descriptions = in.readHashMap(ClassLoader.getSystemClassLoader()); + } public Object getTag(String key) { return tags.get(key); @@ -44,15 +98,14 @@ public class Media implements Parcelable { tags.put(key, value); } - public static Pattern displayTitlePattern = Pattern.compile("(.*)(\\.\\w+)", Pattern.CASE_INSENSITIVE); - public String getDisplayTitle() { - if(filename == null) { + public String getDisplayTitle() { + if (filename == null) { return ""; } // FIXME: Gross hack bercause my regex skills suck maybe or I am too lazy who knows String title = getFilePageTitle().getDisplayText().replaceFirst("^File:", ""); Matcher matcher = displayTitlePattern.matcher(title); - if(matcher.matches()) { + if (matcher.matches()) { return matcher.group(1); } else { return title; @@ -68,7 +121,7 @@ public class Media implements Parcelable { } public String getImageUrl() { - if(imageUrl == null) { + if (imageUrl == null) { imageUrl = Utils.makeThumbBaseUrl(this.getFilename()); } return imageUrl; @@ -86,6 +139,10 @@ public class Media implements Parcelable { return description; } + public void setDescription(String description) { + this.description = description; + } + public long getDataLength() { return dataLength; } @@ -102,7 +159,8 @@ public class Media implements Parcelable { this.dateCreated = date; } - public @Nullable Date getDateUploaded() { + public @Nullable + Date getDateUploaded() { return dateUploaded; } @@ -138,7 +196,8 @@ public class Media implements Parcelable { this.license = license; } - public @Nullable LatLng getCoordinates() { + public @Nullable + LatLng getCoordinates() { return coordinates; } @@ -146,24 +205,9 @@ public class Media implements Parcelable { this.coordinates = coordinates; } - // Primary metadata fields - protected Uri localUri; - protected String imageUrl; - protected String filename; - protected String description; // monolingual description on input... - protected long dataLength; - protected Date dateCreated; - protected @Nullable Date dateUploaded; - protected int width; - protected int height; - protected String license; - private @Nullable LatLng coordinates; - protected String creator; - protected ArrayList categories; // as loaded at runtime? - protected Map descriptions; // multilingual descriptions as loaded - + @SuppressWarnings("unchecked") public ArrayList getCategories() { - return (ArrayList)categories.clone(); // feels dirty + return (ArrayList) categories.clone(); // feels dirty } public void setCategories(List categories) { @@ -171,7 +215,7 @@ public class Media implements Parcelable { this.categories.addAll(categories); } - public void setDescriptions(Map descriptions) { + void setDescriptions(Map descriptions) { for (String key : this.descriptions.keySet()) { this.descriptions.remove(key); } @@ -196,23 +240,6 @@ public class Media implements Parcelable { } } - public Media(String filename) { - this(); - this.filename = filename; - } - - public Media(Uri localUri, String imageUrl, String filename, String description, long dataLength, Date dateCreated, @Nullable Date dateUploaded, String creator) { - this(); - this.localUri = localUri; - this.imageUrl = imageUrl; - this.filename = filename; - this.description = description; - this.dataLength = dataLength; - this.dateCreated = dateCreated; - this.dateUploaded = dateUploaded; - this.creator = creator; - } - @Override public int describeContents() { return 0; @@ -235,27 +262,4 @@ public class Media implements Parcelable { parcel.writeStringList(categories); parcel.writeMap(descriptions); } - - public Media(Parcel in) { - localUri = in.readParcelable(Uri.class.getClassLoader()); - imageUrl = in.readString(); - filename = in.readString(); - description = in.readString(); - dataLength = in.readLong(); - dateCreated = (Date) in.readSerializable(); - dateUploaded = (Date) in.readSerializable(); - creator = in.readString(); - tags = (HashMap)in.readSerializable(); - width = in.readInt(); - height = in.readInt(); - license = in.readString(); - if (categories != null) { - in.readStringList(categories); - } - descriptions = in.readHashMap(ClassLoader.getSystemClassLoader()); - } - - public void setDescription(String description) { - this.description = description; - } } diff --git a/app/src/main/java/fr/free/nrw/commons/auth/AuthenticatedActivity.java b/app/src/main/java/fr/free/nrw/commons/auth/AuthenticatedActivity.java index 1fcec5389..4bd608917 100644 --- a/app/src/main/java/fr/free/nrw/commons/auth/AuthenticatedActivity.java +++ b/app/src/main/java/fr/free/nrw/commons/auth/AuthenticatedActivity.java @@ -18,7 +18,7 @@ public abstract class AuthenticatedActivity extends NavigationBaseActivity { CommonsApplication app; private String authCookie; - + public AuthenticatedActivity() { this.accountType = AccountUtil.accountType(); } @@ -53,24 +53,24 @@ public abstract class AuthenticatedActivity extends NavigationBaseActivity { } protected void requestAuthToken() { - if(authCookie != null) { + if (authCookie != null) { onAuthCookieAcquired(authCookie); return; } AccountManager accountManager = AccountManager.get(this); Account curAccount = app.getCurrentAccount(); - if(curAccount == null) { + if (curAccount == null) { addAccount(accountManager); } else { getAuthCookie(curAccount, accountManager); } } - + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); app = CommonsApplication.getInstance(); - if(savedInstanceState != null) { + if (savedInstanceState != null) { authCookie = savedInstanceState.getString("authCookie"); } } @@ -82,5 +82,6 @@ public abstract class AuthenticatedActivity extends NavigationBaseActivity { } protected abstract void onAuthCookieAcquired(String authCookie); + protected abstract void onAuthFailure(); } diff --git a/app/src/main/java/fr/free/nrw/commons/auth/WikiAccountAuthenticator.java b/app/src/main/java/fr/free/nrw/commons/auth/WikiAccountAuthenticator.java index 8ecfc67cb..ea574d432 100644 --- a/app/src/main/java/fr/free/nrw/commons/auth/WikiAccountAuthenticator.java +++ b/app/src/main/java/fr/free/nrw/commons/auth/WikiAccountAuthenticator.java @@ -16,21 +16,32 @@ import java.io.IOException; import fr.free.nrw.commons.CommonsApplication; import fr.free.nrw.commons.mwapi.MediaWikiApi; +import static android.accounts.AccountManager.ERROR_CODE_UNSUPPORTED_OPERATION; +import static android.accounts.AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE; +import static android.accounts.AccountManager.KEY_ACCOUNT_NAME; +import static android.accounts.AccountManager.KEY_ACCOUNT_TYPE; +import static android.accounts.AccountManager.KEY_AUTHTOKEN; +import static android.accounts.AccountManager.KEY_BOOLEAN_RESULT; +import static android.accounts.AccountManager.KEY_ERROR_CODE; +import static android.accounts.AccountManager.KEY_ERROR_MESSAGE; +import static android.accounts.AccountManager.KEY_INTENT; +import static fr.free.nrw.commons.auth.LoginActivity.PARAM_USERNAME; + public class WikiAccountAuthenticator extends AbstractAccountAuthenticator { private Context context; - public WikiAccountAuthenticator(Context context) { + WikiAccountAuthenticator(Context context) { super(context); this.context = context; } private Bundle unsupportedOperation() { Bundle bundle = new Bundle(); - bundle.putInt(AccountManager.KEY_ERROR_CODE, AccountManager.ERROR_CODE_UNSUPPORTED_OPERATION); + bundle.putInt(KEY_ERROR_CODE, ERROR_CODE_UNSUPPORTED_OPERATION); // HACK: the docs indicate that this is a required key bit it's not displayed to the user. - bundle.putString(AccountManager.KEY_ERROR_MESSAGE, ""); + bundle.putString(KEY_ERROR_MESSAGE, ""); return bundle; } @@ -54,10 +65,10 @@ public class WikiAccountAuthenticator extends AbstractAccountAuthenticator { private Bundle addAccount(AccountAuthenticatorResponse response) { Intent Intent = new Intent(context, LoginActivity.class); - Intent.putExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE, response); + Intent.putExtra(KEY_ACCOUNT_AUTHENTICATOR_RESPONSE, response); Bundle bundle = new Bundle(); - bundle.putParcelable(AccountManager.KEY_INTENT, Intent); + bundle.putParcelable(KEY_INTENT, Intent); return bundle; } @@ -78,14 +89,16 @@ public class WikiAccountAuthenticator extends AbstractAccountAuthenticator { MediaWikiApi api = CommonsApplication.getInstance().getMWApi(); //TODO add 2fa support here String result = api.login(username, password); - if(result.equals("PASS")) { + if (result.equals("PASS")) { return api.getAuthCookie(); } else { return null; } } + @Override - public Bundle getAuthToken(AccountAuthenticatorResponse response, Account account, String authTokenType, Bundle options) throws NetworkErrorException { + public Bundle getAuthToken(AccountAuthenticatorResponse response, Account account, + String authTokenType, Bundle options) throws NetworkErrorException { // Extract the username and password from the Account Manager, and ask // the server for an appropriate AuthToken. final AccountManager am = AccountManager.get(context); @@ -101,9 +114,9 @@ public class WikiAccountAuthenticator extends AbstractAccountAuthenticator { } if (authCookie != null) { final Bundle result = new Bundle(); - result.putString(AccountManager.KEY_ACCOUNT_NAME, account.name); - result.putString(AccountManager.KEY_ACCOUNT_TYPE, AccountUtil.accountType()); - result.putString(AccountManager.KEY_AUTHTOKEN, authCookie); + result.putString(KEY_ACCOUNT_NAME, account.name); + result.putString(KEY_ACCOUNT_TYPE, AccountUtil.accountType()); + result.putString(KEY_AUTHTOKEN, authCookie); return result; } } @@ -112,10 +125,10 @@ public class WikiAccountAuthenticator extends AbstractAccountAuthenticator { // need to re-prompt them for their credentials. We do that by creating // an intent to display our AuthenticatorActivity panel. final Intent intent = new Intent(context, LoginActivity.class); - intent.putExtra(LoginActivity.PARAM_USERNAME, account.name); - intent.putExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE, response); + intent.putExtra(PARAM_USERNAME, account.name); + intent.putExtra(KEY_ACCOUNT_AUTHENTICATOR_RESPONSE, response); final Bundle bundle = new Bundle(); - bundle.putParcelable(AccountManager.KEY_INTENT, intent); + bundle.putParcelable(KEY_INTENT, intent); return bundle; } @@ -133,7 +146,7 @@ public class WikiAccountAuthenticator extends AbstractAccountAuthenticator { @NonNull Account account, @NonNull String[] features) throws NetworkErrorException { Bundle bundle = new Bundle(); - bundle.putBoolean(AccountManager.KEY_BOOLEAN_RESULT, false); + bundle.putBoolean(KEY_BOOLEAN_RESULT, false); return bundle; } @@ -141,8 +154,7 @@ public class WikiAccountAuthenticator extends AbstractAccountAuthenticator { @Override public Bundle updateCredentials(@NonNull AccountAuthenticatorResponse response, @NonNull Account account, @Nullable String authTokenType, - @Nullable Bundle options) - throws NetworkErrorException { + @Nullable Bundle options) throws NetworkErrorException { return unsupportedOperation(); } diff --git a/app/src/main/java/fr/free/nrw/commons/category/CategoryContentProvider.java b/app/src/main/java/fr/free/nrw/commons/category/CategoryContentProvider.java index e75f1adcf..59db22230 100644 --- a/app/src/main/java/fr/free/nrw/commons/category/CategoryContentProvider.java +++ b/app/src/main/java/fr/free/nrw/commons/category/CategoryContentProvider.java @@ -15,31 +15,39 @@ import fr.free.nrw.commons.data.Category; import fr.free.nrw.commons.data.DBOpenHelper; import timber.log.Timber; +import static android.content.UriMatcher.NO_MATCH; +import static fr.free.nrw.commons.data.Category.Table.ALL_FIELDS; +import static fr.free.nrw.commons.data.Category.Table.COLUMN_ID; +import static fr.free.nrw.commons.data.Category.Table.TABLE_NAME; + public class CategoryContentProvider extends ContentProvider { + public static final String AUTHORITY = "fr.free.nrw.commons.categories.contentprovider"; // For URI matcher private static final int CATEGORIES = 1; private static final int CATEGORIES_ID = 2; - - public static final String AUTHORITY = "fr.free.nrw.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); + private static final UriMatcher uriMatcher = new UriMatcher(NO_MATCH); + static { uriMatcher.addURI(AUTHORITY, BASE_PATH, CATEGORIES); uriMatcher.addURI(AUTHORITY, BASE_PATH + "/#", CATEGORIES_ID); } + private DBOpenHelper dbOpenHelper; + public static Uri uriForId(int id) { return Uri.parse(BASE_URI.toString() + "/" + id); } - private DBOpenHelper dbOpenHelper; + @SuppressWarnings("ConstantConditions") @Override public boolean onCreate() { - dbOpenHelper = CommonsApplication.getInstance().getDBOpenHelper(); + CommonsApplication app = ((CommonsApplication) getContext().getApplicationContext()); + dbOpenHelper = app.getDBOpenHelper(); return false; } @@ -48,23 +56,23 @@ public class CategoryContentProvider extends ContentProvider { public Cursor query(@NonNull Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder(); - queryBuilder.setTables(Category.Table.TABLE_NAME); + queryBuilder.setTables(TABLE_NAME); int uriType = uriMatcher.match(uri); SQLiteDatabase db = dbOpenHelper.getReadableDatabase(); Cursor cursor; - switch(uriType) { + 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, + ALL_FIELDS, "_id = ?", - new String[] { uri.getLastPathSegment() }, + new String[]{uri.getLastPathSegment()}, null, null, sortOrder @@ -92,7 +100,7 @@ public class CategoryContentProvider extends ContentProvider { long id; switch (uriType) { case CATEGORIES: - id = sqlDB.insert(Category.Table.TABLE_NAME, null, contentValues); + id = sqlDB.insert(TABLE_NAME, null, contentValues); break; default: throw new IllegalArgumentException("Unknown URI: " + uri); @@ -115,9 +123,9 @@ public class CategoryContentProvider extends ContentProvider { sqlDB.beginTransaction(); switch (uriType) { case CATEGORIES: - for(ContentValues value: values) { + for (ContentValues value : values) { Timber.d("Inserting! %s", value); - sqlDB.insert(Category.Table.TABLE_NAME, null, value); + sqlDB.insert(TABLE_NAME, null, value); } break; default: @@ -145,13 +153,12 @@ public class CategoryContentProvider extends ContentProvider { int rowsUpdated; switch (uriType) { case CATEGORIES_ID: - int id = Integer.valueOf(uri.getLastPathSegment()); - if (TextUtils.isEmpty(selection)) { - rowsUpdated = sqlDB.update(Category.Table.TABLE_NAME, + int id = Integer.valueOf(uri.getLastPathSegment()); + rowsUpdated = sqlDB.update(TABLE_NAME, contentValues, - Category.Table.COLUMN_ID + " = ?", - new String[] { String.valueOf(id) } ); + COLUMN_ID + " = ?", + new String[]{String.valueOf(id)}); } else { throw new IllegalArgumentException( "Parameter `selection` should be empty when updating an ID"); diff --git a/app/src/main/java/fr/free/nrw/commons/contributions/ContributionController.java b/app/src/main/java/fr/free/nrw/commons/contributions/ContributionController.java index 481b4cc7f..dd867a186 100644 --- a/app/src/main/java/fr/free/nrw/commons/contributions/ContributionController.java +++ b/app/src/main/java/fr/free/nrw/commons/contributions/ContributionController.java @@ -1,11 +1,12 @@ package fr.free.nrw.commons.contributions; -import android.app.Activity; +import android.content.Context; import android.content.Intent; import android.net.Uri; import android.os.Bundle; import android.provider.MediaStore; import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentActivity; import android.support.v4.content.FileProvider; import java.io.File; @@ -15,16 +16,25 @@ import fr.free.nrw.commons.upload.ShareActivity; import fr.free.nrw.commons.upload.UploadService; import timber.log.Timber; -public class ContributionController { +import static android.content.Intent.ACTION_GET_CONTENT; +import static android.content.Intent.ACTION_SEND; +import static android.content.Intent.EXTRA_STREAM; +import static android.content.Intent.FLAG_GRANT_READ_URI_PERMISSION; +import static android.content.Intent.FLAG_GRANT_WRITE_URI_PERMISSION; +import static android.provider.MediaStore.EXTRA_OUTPUT; +import static fr.free.nrw.commons.contributions.Contribution.SOURCE_CAMERA; +import static fr.free.nrw.commons.contributions.Contribution.SOURCE_GALLERY; +import static fr.free.nrw.commons.upload.UploadService.EXTRA_SOURCE; + +class ContributionController { + + private static final int SELECT_FROM_GALLERY = 1; + private static final int SELECT_FROM_CAMERA = 2; + private Fragment fragment; - private Activity activity; - private final static int SELECT_FROM_GALLERY = 1; - private final static int SELECT_FROM_CAMERA = 2; - - public ContributionController(Fragment fragment) { + ContributionController(Fragment fragment) { this.fragment = fragment; - this.activity = fragment.getActivity(); } // See http://stackoverflow.com/a/5054673/17865 for why this is done @@ -34,43 +44,44 @@ public class ContributionController { File photoFile = new File(fragment.getContext().getCacheDir() + "/images", new Date().getTime() + ".jpg"); photoFile.getParentFile().mkdirs(); + Context applicationContext = fragment.getActivity().getApplicationContext(); return FileProvider.getUriForFile( fragment.getContext(), - fragment.getActivity().getApplicationContext().getPackageName() + ".provider", + applicationContext.getPackageName() + ".provider", photoFile); } - public void startCameraCapture() { - Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); + void startCameraCapture() { + Intent pictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); lastGeneratedCaptureUri = reGenerateImageCaptureUriInCache(); - takePictureIntent.setFlags( - Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION); - takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, lastGeneratedCaptureUri); - fragment.startActivityForResult(takePictureIntent, SELECT_FROM_CAMERA); + pictureIntent.setFlags(FLAG_GRANT_READ_URI_PERMISSION | FLAG_GRANT_WRITE_URI_PERMISSION); + pictureIntent.putExtra(EXTRA_OUTPUT, lastGeneratedCaptureUri); + fragment.startActivityForResult(pictureIntent, SELECT_FROM_CAMERA); } - public void startGalleryPick() { + void startGalleryPick() { //FIXME: Starts gallery (opens Google Photos) - Intent pickImageIntent = new Intent(Intent.ACTION_GET_CONTENT); + Intent pickImageIntent = new Intent(ACTION_GET_CONTENT); pickImageIntent.setType("image/*"); fragment.startActivityForResult(pickImageIntent, SELECT_FROM_GALLERY); } - public void handleImagePicked(int requestCode, Intent data) { + void handleImagePicked(int requestCode, Intent data) { + FragmentActivity activity = fragment.getActivity(); Intent shareIntent = new Intent(activity, ShareActivity.class); - shareIntent.setAction(Intent.ACTION_SEND); - switch(requestCode) { + shareIntent.setAction(ACTION_SEND); + switch (requestCode) { case SELECT_FROM_GALLERY: //Handles image picked from gallery Uri imageData = data.getData(); shareIntent.setType(activity.getContentResolver().getType(imageData)); - shareIntent.putExtra(Intent.EXTRA_STREAM, imageData); - shareIntent.putExtra(UploadService.EXTRA_SOURCE, Contribution.SOURCE_GALLERY); + shareIntent.putExtra(EXTRA_STREAM, imageData); + shareIntent.putExtra(EXTRA_SOURCE, SOURCE_GALLERY); break; case SELECT_FROM_CAMERA: shareIntent.setType("image/jpeg"); //FIXME: Find out appropriate mime type - shareIntent.putExtra(Intent.EXTRA_STREAM, lastGeneratedCaptureUri); - shareIntent.putExtra(UploadService.EXTRA_SOURCE, Contribution.SOURCE_CAMERA); + shareIntent.putExtra(EXTRA_STREAM, lastGeneratedCaptureUri); + shareIntent.putExtra(EXTRA_SOURCE, SOURCE_CAMERA); break; } Timber.i("Image selected"); @@ -81,12 +92,14 @@ public class ContributionController { } } - public void saveState(Bundle outState) { - outState.putParcelable("lastGeneratedCaptureURI", lastGeneratedCaptureUri); + void saveState(Bundle outState) { + if (outState != null) { + outState.putParcelable("lastGeneratedCaptureURI", lastGeneratedCaptureUri); + } } - public void loadState(Bundle savedInstanceState) { - if(savedInstanceState != null) { + void loadState(Bundle savedInstanceState) { + if (savedInstanceState != null) { lastGeneratedCaptureUri = savedInstanceState.getParcelable("lastGeneratedCaptureURI"); } } diff --git a/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsActivity.java b/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsActivity.java index fa1d2d96f..f27bfe210 100644 --- a/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsActivity.java +++ b/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsActivity.java @@ -1,7 +1,6 @@ package fr.free.nrw.commons.contributions; import android.content.ComponentName; -import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; @@ -38,13 +37,17 @@ import io.reactivex.disposables.CompositeDisposable; import io.reactivex.schedulers.Schedulers; import timber.log.Timber; -public class ContributionsActivity - extends AuthenticatedActivity - implements LoaderManager.LoaderCallbacks, - AdapterView.OnItemClickListener, - MediaDetailPagerFragment.MediaDetailProvider, - FragmentManager.OnBackStackChangedListener, - ContributionsListFragment.SourceRefresher { +import static android.content.ContentResolver.requestSync; +import static fr.free.nrw.commons.contributions.Contribution.STATE_FAILED; +import static fr.free.nrw.commons.contributions.Contribution.Table.ALL_FIELDS; +import static fr.free.nrw.commons.contributions.ContributionsContentProvider.AUTHORITY; +import static fr.free.nrw.commons.contributions.ContributionsContentProvider.BASE_URI; +import static fr.free.nrw.commons.settings.Prefs.UPLOADS_SHOWING; + +public class ContributionsActivity extends AuthenticatedActivity + implements LoaderManager.LoaderCallbacks, AdapterView.OnItemClickListener, + MediaDetailPagerFragment.MediaDetailProvider, FragmentManager.OnBackStackChangedListener, + ContributionsListFragment.SourceRefresher { private Cursor allContributions; private ContributionsListFragment contributionsList; @@ -63,14 +66,18 @@ public class ContributionsActivity This is why Contribution.STATE_COMPLETED is -1. */ - private String CONTRIBUTION_SORT = Contribution.Table.COLUMN_STATE + " DESC, " + Contribution.Table.COLUMN_UPLOADED + " DESC , (" + Contribution.Table.COLUMN_TIMESTAMP + " * " + Contribution.Table.COLUMN_STATE + ")"; + private String CONTRIBUTION_SORT = Contribution.Table.COLUMN_STATE + " DESC, " + + Contribution.Table.COLUMN_UPLOADED + " DESC , (" + + Contribution.Table.COLUMN_TIMESTAMP + " * " + + Contribution.Table.COLUMN_STATE + ")"; private CompositeDisposable compositeDisposable = new CompositeDisposable(); private ServiceConnection uploadServiceConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName componentName, IBinder binder) { - uploadService = (UploadService) ((HandlerService.HandlerServiceLocalBinder)binder).getService(); + uploadService = (UploadService) ((HandlerService.HandlerServiceLocalBinder) binder) + .getService(); isUploadServiceConnected = true; } @@ -86,7 +93,7 @@ public class ContributionsActivity compositeDisposable.clear(); getSupportFragmentManager().removeOnBackStackChangedListener(this); super.onDestroy(); - if(isUploadServiceConnected) { + if (isUploadServiceConnected) { unbindService(uploadServiceConnection); } } @@ -96,9 +103,9 @@ public class ContributionsActivity super.onResume(); SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this); boolean isSettingsChanged = - sharedPreferences.getBoolean(Prefs.IS_CONTRIBUTION_COUNT_CHANGED,false); + sharedPreferences.getBoolean(Prefs.IS_CONTRIBUTION_COUNT_CHANGED, false); SharedPreferences.Editor editor = sharedPreferences.edit(); - editor.putBoolean(Prefs.IS_CONTRIBUTION_COUNT_CHANGED,false); + editor.putBoolean(Prefs.IS_CONTRIBUTION_COUNT_CHANGED, false); editor.apply(); if (isSettingsChanged) { refreshSource(); @@ -107,14 +114,16 @@ public class ContributionsActivity @Override protected void onAuthCookieAcquired(String authCookie) { - // Do a sync everytime we get here! - ContentResolver.requestSync(CommonsApplication.getInstance().getCurrentAccount(), ContributionsContentProvider.AUTHORITY, new Bundle()); + // Do a sync every time we get here! + CommonsApplication app = ((CommonsApplication) getApplication()); + requestSync(app.getCurrentAccount(), AUTHORITY, new Bundle()); Intent uploadServiceIntent = new Intent(this, UploadService.class); uploadServiceIntent.setAction(UploadService.ACTION_START_SERVICE); startService(uploadServiceIntent); bindService(uploadServiceIntent, uploadServiceConnection, Context.BIND_AUTO_CREATE); - allContributions = getContentResolver().query(ContributionsContentProvider.BASE_URI, Contribution.Table.ALL_FIELDS, CONTRIBUTION_SELECTION, null, CONTRIBUTION_SORT); + allContributions = getContentResolver().query(BASE_URI, ALL_FIELDS, + CONTRIBUTION_SELECTION, null, CONTRIBUTION_SORT); getSupportLoaderManager().initLoader(0, null, this); } @@ -127,12 +136,13 @@ public class ContributionsActivity // Activity can call methods in the fragment by acquiring a // reference to the Fragment from FragmentManager, using findFragmentById() - contributionsList = (ContributionsListFragment)getSupportFragmentManager() + FragmentManager supportFragmentManager = getSupportFragmentManager(); + contributionsList = (ContributionsListFragment) supportFragmentManager .findFragmentById(R.id.contributionsListFragment); - getSupportFragmentManager().addOnBackStackChangedListener(this); + supportFragmentManager.addOnBackStackChangedListener(this); if (savedInstanceState != null) { - mediaDetails = (MediaDetailPagerFragment)getSupportFragmentManager() + mediaDetails = (MediaDetailPagerFragment) supportFragmentManager .findFragmentById(R.id.contributionsFragmentContainer); } requestAuthToken(); @@ -143,21 +153,25 @@ public class ContributionsActivity @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); - outState.putBoolean("mediaDetailsVisible", (mediaDetails != null && mediaDetails.isVisible())); + boolean mediaDetailsVisible = mediaDetails != null && mediaDetails.isVisible(); + outState.putBoolean("mediaDetailsVisible", mediaDetailsVisible); } - /** Replace whatever is in the current contributionsFragmentContainer view with mediaDetailPagerFragment, - / and preserve previous state in back stack. - / Called when user selects a contribution. */ + /** + * Replace whatever is in the current contributionsFragmentContainer view with + * mediaDetailPagerFragment, and preserve previous state in back stack. + * Called when user selects a contribution. + */ private void showDetail(int i) { - if(mediaDetails == null ||!mediaDetails.isVisible()) { + if (mediaDetails == null || !mediaDetails.isVisible()) { mediaDetails = new MediaDetailPagerFragment(); - this.getSupportFragmentManager() + FragmentManager supportFragmentManager = getSupportFragmentManager(); + supportFragmentManager .beginTransaction() .replace(R.id.contributionsFragmentContainer, mediaDetails) .addToBackStack(null) .commit(); - this.getSupportFragmentManager().executePendingTransactions(); + supportFragmentManager.executePendingTransactions(); } mediaDetails.showImage(i); } @@ -165,7 +179,7 @@ public class ContributionsActivity public void retryUpload(int i) { allContributions.moveToPosition(i); Contribution c = Contribution.fromCursor(allContributions); - if(c.getState() == Contribution.STATE_FAILED) { + if (c.getState() == STATE_FAILED) { uploadService.queue(UploadService.ACTION_UPLOAD_FILE, c); Timber.d("Restarting for %s", c.toContentValues()); } else { @@ -176,9 +190,9 @@ public class ContributionsActivity public void deleteUpload(int i) { allContributions.moveToPosition(i); Contribution c = Contribution.fromCursor(allContributions); - if(c.getState() == Contribution.STATE_FAILED) { + if (c.getState() == STATE_FAILED) { Timber.d("Deleting failed contrib %s", c.toContentValues()); - c.setContentProviderClient(getContentResolver().acquireContentProviderClient(ContributionsContentProvider.AUTHORITY)); + c.setContentProviderClient(getContentResolver().acquireContentProviderClient(AUTHORITY)); c.delete(); } else { Timber.d("Skipping deletion for non-failed contrib %s", c.toContentValues()); @@ -187,9 +201,9 @@ public class ContributionsActivity @Override public boolean onOptionsItemSelected(MenuItem item) { - switch(item.getItemId()) { + switch (item.getItemId()) { case android.R.id.home: - if(mediaDetails.isVisible()) { + if (mediaDetails.isVisible()) { getSupportFragmentManager().popBackStack(); } return true; @@ -215,21 +229,20 @@ public class ContributionsActivity @Override public Loader onCreateLoader(int i, Bundle bundle) { - SharedPreferences sharedPref = - PreferenceManager.getDefaultSharedPreferences(this); - int uploads = sharedPref.getInt(Prefs.UPLOADS_SHOWING, 100); - return new CursorLoader(this, ContributionsContentProvider.BASE_URI, - Contribution.Table.ALL_FIELDS, CONTRIBUTION_SELECTION, null, + SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this); + int uploads = sharedPref.getInt(UPLOADS_SHOWING, 100); + return new CursorLoader(this, BASE_URI, + ALL_FIELDS, CONTRIBUTION_SELECTION, null, CONTRIBUTION_SORT + "LIMIT " + uploads); } @Override public void onLoadFinished(Loader cursorLoader, Cursor cursor) { - if(contributionsList.getAdapter() == null) { - contributionsList - .setAdapter(new ContributionsListAdapter(getApplicationContext(), cursor, 0)); + if (contributionsList.getAdapter() == null) { + contributionsList.setAdapter(new ContributionsListAdapter(getApplicationContext(), + cursor, 0)); } else { - ((CursorAdapter)contributionsList.getAdapter()).swapCursor(cursor); + ((CursorAdapter) contributionsList.getAdapter()).swapCursor(cursor); } setUploadCount(); @@ -249,34 +262,32 @@ public class ContributionsActivity if (contributionsList.getAdapter() == null) { // not yet ready to return data return null; - } else { + } else { return Contribution.fromCursor((Cursor) contributionsList.getAdapter().getItem(i)); } } @Override public int getTotalMediaCount() { - if(contributionsList.getAdapter() == null) { + if (contributionsList.getAdapter() == null) { return 0; } return contributionsList.getAdapter().getCount(); } + @SuppressWarnings("ConstantConditions") private void setUploadCount() { - CommonsApplication application = CommonsApplication.getInstance(); - + CommonsApplication app = ((CommonsApplication) getApplication()); compositeDisposable.add( - CommonsApplication.getInstance().getMWApi() - .getUploadCount(application.getCurrentAccount().name) + app.getMWApi() + .getUploadCount(app.getCurrentAccount().name) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe( - uploadCount -> - getSupportActionBar().setSubtitle(getResources() - .getQuantityString(R.plurals.contributions_subtitle, - uploadCount, - uploadCount)), - throwable -> Timber.e(throwable, "Fetching upload count failed") + uploadCount -> getSupportActionBar().setSubtitle(getResources() + .getQuantityString(R.plurals.contributions_subtitle, + uploadCount, uploadCount)), + t -> Timber.e(t, "Fetching upload count failed") ) ); } @@ -332,8 +343,7 @@ public class ContributionsActivity } public static void startYourself(Context context) { - Intent contributionsIntent = new Intent(context, ContributionsActivity.class); - context.startActivity(contributionsIntent); + context.startActivity(new Intent(context, ContributionsActivity.class)); } } 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 index 6e84065f2..ec1f02028 100644 --- a/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsContentProvider.java +++ b/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsContentProvider.java @@ -13,17 +13,20 @@ import android.text.TextUtils; import fr.free.nrw.commons.CommonsApplication; import timber.log.Timber; -public class ContributionsContentProvider extends ContentProvider{ +import static android.content.UriMatcher.NO_MATCH; +import static fr.free.nrw.commons.contributions.Contribution.Table.ALL_FIELDS; +import static fr.free.nrw.commons.contributions.Contribution.Table.TABLE_NAME; + +public class ContributionsContentProvider extends ContentProvider { private static final int CONTRIBUTIONS = 1; private static final int CONTRIBUTIONS_ID = 2; - - public static final String AUTHORITY = "fr.free.nrw.commons.contributions.contentprovider"; private static final String BASE_PATH = "contributions"; + private static final UriMatcher uriMatcher = new UriMatcher(NO_MATCH); + public static final String AUTHORITY = "fr.free.nrw.commons.contributions.contentprovider"; 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, CONTRIBUTIONS); uriMatcher.addURI(AUTHORITY, BASE_PATH + "/#", CONTRIBUTIONS_ID); @@ -38,25 +41,29 @@ public class ContributionsContentProvider extends ContentProvider{ return false; } + @SuppressWarnings("ConstantConditions") @Override - public Cursor query(@NonNull Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { + public Cursor query(@NonNull Uri uri, String[] projection, String selection, + String[] selectionArgs, String sortOrder) { SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder(); - queryBuilder.setTables(Contribution.Table.TABLE_NAME); + queryBuilder.setTables(TABLE_NAME); int uriType = uriMatcher.match(uri); - SQLiteDatabase db = CommonsApplication.getInstance().getDBOpenHelper().getReadableDatabase(); + CommonsApplication app = (CommonsApplication) getContext().getApplicationContext(); + SQLiteDatabase db = app.getDBOpenHelper().getReadableDatabase(); Cursor cursor; - switch(uriType) { + switch (uriType) { case CONTRIBUTIONS: - cursor = queryBuilder.query(db, projection, selection, selectionArgs, null, null, sortOrder); + cursor = queryBuilder.query(db, projection, selection, selectionArgs, + null, null, sortOrder); break; case CONTRIBUTIONS_ID: cursor = queryBuilder.query(db, - Contribution.Table.ALL_FIELDS, + ALL_FIELDS, "_id = ?", - new String[] { uri.getLastPathSegment() }, + new String[]{uri.getLastPathSegment()}, null, null, sortOrder @@ -76,14 +83,16 @@ public class ContributionsContentProvider extends ContentProvider{ return null; } + @SuppressWarnings("ConstantConditions") @Override public Uri insert(@NonNull Uri uri, ContentValues contentValues) { int uriType = uriMatcher.match(uri); - SQLiteDatabase sqlDB = CommonsApplication.getInstance().getDBOpenHelper().getWritableDatabase(); - long id = 0; + CommonsApplication app = (CommonsApplication) getContext().getApplicationContext(); + SQLiteDatabase sqlDB = app.getDBOpenHelper().getWritableDatabase(); + long id; switch (uriType) { case CONTRIBUTIONS: - id = sqlDB.insert(Contribution.Table.TABLE_NAME, null, contentValues); + id = sqlDB.insert(TABLE_NAME, null, contentValues); break; default: throw new IllegalArgumentException("Unknown URI: " + uri); @@ -92,19 +101,21 @@ public class ContributionsContentProvider extends ContentProvider{ return Uri.parse(BASE_URI + "/" + id); } + @SuppressWarnings("ConstantConditions") @Override public int delete(@NonNull Uri uri, String s, String[] strings) { - int rows = 0; + int rows; int uriType = uriMatcher.match(uri); - SQLiteDatabase db = CommonsApplication.getInstance().getDBOpenHelper().getReadableDatabase(); + CommonsApplication app = (CommonsApplication) getContext().getApplicationContext(); + SQLiteDatabase sqlDB = app.getDBOpenHelper().getWritableDatabase(); - switch(uriType) { + switch (uriType) { case CONTRIBUTIONS_ID: Timber.d("Deleting contribution id %s", uri.getLastPathSegment()); - rows = db.delete(Contribution.Table.TABLE_NAME, + rows = sqlDB.delete(TABLE_NAME, "_id = ?", - new String[] { uri.getLastPathSegment() } + new String[]{uri.getLastPathSegment()} ); break; default: @@ -114,17 +125,19 @@ public class ContributionsContentProvider extends ContentProvider{ 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 = CommonsApplication.getInstance().getDBOpenHelper().getWritableDatabase(); + CommonsApplication app = (CommonsApplication) getContext().getApplicationContext(); + SQLiteDatabase sqlDB = app.getDBOpenHelper().getWritableDatabase(); sqlDB.beginTransaction(); switch (uriType) { case CONTRIBUTIONS: - for(ContentValues value: values) { + for (ContentValues value : values) { Timber.d("Inserting! %s", value); - sqlDB.insert(Contribution.Table.TABLE_NAME, null, value); + sqlDB.insert(TABLE_NAME, null, value); } break; default: @@ -136,6 +149,7 @@ public class ContributionsContentProvider extends ContentProvider{ return values.length; } + @SuppressWarnings("ConstantConditions") @Override public int update(@NonNull Uri uri, ContentValues contentValues, String selection, String[] selectionArgs) { /* @@ -146,25 +160,24 @@ public class ContributionsContentProvider extends ContentProvider{ 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 = CommonsApplication.getInstance().getDBOpenHelper().getWritableDatabase(); - int rowsUpdated = 0; + CommonsApplication app = (CommonsApplication) getContext().getApplicationContext(); + SQLiteDatabase sqlDB = app.getDBOpenHelper().getWritableDatabase(); + int rowsUpdated; switch (uriType) { case CONTRIBUTIONS: - rowsUpdated = sqlDB.update(Contribution.Table.TABLE_NAME, - contentValues, - selection, - selectionArgs); + 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(Contribution.Table.TABLE_NAME, + rowsUpdated = sqlDB.update(TABLE_NAME, contentValues, Contribution.Table.COLUMN_ID + " = ?", - new String[] { String.valueOf(id) } ); + new String[]{String.valueOf(id)}); } else { - throw new IllegalArgumentException("Parameter `selection` should be empty when updating an ID"); + throw new IllegalArgumentException( + "Parameter `selection` should be empty when updating an ID"); } break; default: 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 3ead40bcf..b93a21fde 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 @@ -1,9 +1,7 @@ package fr.free.nrw.commons.contributions; -import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; -import android.content.pm.PackageManager; import android.os.Build; import android.os.Bundle; import android.support.annotation.NonNull; @@ -30,17 +28,15 @@ import timber.log.Timber; import static android.Manifest.permission.READ_EXTERNAL_STORAGE; import static android.app.Activity.RESULT_OK; +import static android.content.Context.MODE_PRIVATE; +import static android.content.pm.PackageManager.PERMISSION_GRANTED; +import static android.view.View.GONE; public class ContributionsListFragment extends Fragment { - public interface SourceRefresher { - void refreshSource(); - } - @BindView(R.id.contributionsList) GridView contributionsList; @BindView(R.id.waitingMessage) TextView waitingMessage; @BindView(R.id.emptyMessage) TextView emptyMessage; - private ContributionController controller; @Override @@ -48,21 +44,21 @@ public class ContributionsListFragment extends Fragment { View v = inflater.inflate(R.layout.fragment_contributions, container, false); ButterKnife.bind(this, v); - contributionsList.setOnItemClickListener((AdapterView.OnItemClickListener)getActivity()); - if(savedInstanceState != null) { + contributionsList.setOnItemClickListener((AdapterView.OnItemClickListener) getActivity()); + if (savedInstanceState != null) { Timber.d("Scrolling to %d", savedInstanceState.getInt("grid-position")); contributionsList.setSelection(savedInstanceState.getInt("grid-position")); } //TODO: Should this be in onResume? - SharedPreferences prefs = this.getActivity().getSharedPreferences("prefs", Context.MODE_PRIVATE); + SharedPreferences prefs = getActivity().getSharedPreferences("prefs", MODE_PRIVATE); String lastModified = prefs.getString("lastSyncTimestamp", ""); Timber.d("Last Sync Timestamp: %s", lastModified); if (lastModified.equals("")) { waitingMessage.setVisibility(View.VISIBLE); } else { - waitingMessage.setVisibility(View.GONE); + waitingMessage.setVisibility(GONE); } return v; @@ -91,7 +87,7 @@ public class ContributionsListFragment extends Fragment { //FIXME: must get the file data for Google Photos when receive the intent answer, in the onActivityResult method super.onActivityResult(requestCode, resultCode, data); - if ( resultCode == RESULT_OK ) { + if (resultCode == RESULT_OK) { Timber.d("OnActivityResult() parameters: Req code: %d Result code: %d Data: %s", requestCode, resultCode, data); controller.handleImagePicked(requestCode, data); @@ -103,7 +99,7 @@ public class ContributionsListFragment extends Fragment { @Override public boolean onOptionsItemSelected(MenuItem item) { - switch(item.getItemId()) { + switch (item.getItemId()) { case R.id.menu_from_gallery: //Gallery crashes before reach ShareActivity screen so must implement permissions check here if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { @@ -111,7 +107,7 @@ public class ContributionsListFragment extends Fragment { // Here, thisActivity is the current activity if (ContextCompat.checkSelfPermission(getActivity(), READ_EXTERNAL_STORAGE) - != PackageManager.PERMISSION_GRANTED) { + != PERMISSION_GRANTED) { // Should we show an explanation? if (shouldShowRequestPermissionRationale(READ_EXTERNAL_STORAGE)) { @@ -161,14 +157,15 @@ public class ContributionsListFragment extends Fragment { } @Override - public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { - - Timber.d("onRequestPermissionsResult: req code = " + " perm = " + permissions + " grant =" + grantResults); + public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, + @NonNull int[] grantResults) { + Timber.d("onRequestPermissionsResult: req code = " + " perm = " + + permissions + " grant =" + grantResults); switch (requestCode) { // 1 = Storage allowed when gallery selected case 1: { - if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { + if (grantResults.length > 0 && grantResults[0] == PERMISSION_GRANTED) { Timber.d("Call controller.startGalleryPick()"); controller.startGalleryPick(); } @@ -176,7 +173,7 @@ public class ContributionsListFragment extends Fragment { break; // 2 = Location allowed when 'nearby places' selected case 2: { - if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { + if (grantResults.length > 0 && grantResults[0] == PERMISSION_GRANTED) { Timber.d("Location permission granted"); Intent nearbyIntent = new Intent(getActivity(), NearbyActivity.class); startActivity(nearbyIntent); @@ -191,7 +188,8 @@ public class ContributionsListFragment extends Fragment { menu.clear(); // See http://stackoverflow.com/a/8495697/17865 inflater.inflate(R.menu.fragment_contributions_list, menu); - if (!CommonsApplication.getInstance().deviceHasCamera()) { + CommonsApplication app = (CommonsApplication) getContext().getApplicationContext(); + if (!app.deviceHasCamera()) { menu.findItem(R.id.menu_from_camera).setEnabled(false); } } @@ -215,6 +213,10 @@ public class ContributionsListFragment extends Fragment { } protected void clearSyncMessage() { - waitingMessage.setVisibility(View.GONE); + waitingMessage.setVisibility(GONE); + } + + public interface SourceRefresher { + void refreshSource(); } } 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 index 6d769e94c..fdcc52380 100644 --- a/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsSyncAdapter.java +++ b/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsSyncAdapter.java @@ -23,8 +23,18 @@ import fr.free.nrw.commons.mwapi.LogEventResult; import fr.free.nrw.commons.mwapi.MediaWikiApi; import timber.log.Timber; +import static android.content.Context.MODE_PRIVATE; +import static fr.free.nrw.commons.contributions.Contribution.STATE_COMPLETED; +import static fr.free.nrw.commons.contributions.Contribution.Table.COLUMN_FILENAME; +import static fr.free.nrw.commons.contributions.ContributionsContentProvider.BASE_URI; + public class ContributionsSyncAdapter extends AbstractThreadedSyncAdapter { + + private static final String[] existsQuery = {COLUMN_FILENAME}; + private static final String existsSelection = COLUMN_FILENAME + " = ?"; + private static final ContentValues[] EMPTY = {}; private static int COMMIT_THRESHOLD = 10; + public ContributionsSyncAdapter(Context context, boolean autoInitialize) { super(context, autoInitialize); } @@ -36,39 +46,38 @@ public class ContributionsSyncAdapter extends AbstractThreadedSyncAdapter { return limit; // FIXME: Parameterize! } - private static final String[] existsQuery = { Contribution.Table.COLUMN_FILENAME }; - private static final String existsSelection = Contribution.Table.COLUMN_FILENAME + " = ?"; private boolean fileExists(ContentProviderClient client, String filename) { Cursor cursor = null; try { - cursor = client.query(ContributionsContentProvider.BASE_URI, + cursor = client.query(BASE_URI, existsQuery, existsSelection, - new String[] { filename }, + new String[]{filename}, "" ); - return cursor.getCount() != 0; + return cursor != null && cursor.getCount() != 0; } catch (RemoteException e) { throw new RuntimeException(e); } finally { - if ( cursor != null ) { + if (cursor != null) { cursor.close(); } } } @Override - public void onPerformSync(Account account, Bundle bundle, String s, ContentProviderClient contentProviderClient, SyncResult syncResult) { + public void onPerformSync(Account account, Bundle bundle, String authority, + ContentProviderClient contentProviderClient, SyncResult syncResult) { // This code is fraught with possibilities of race conditions, but lalalalala I can't hear you! String user = account.name; MediaWikiApi api = CommonsApplication.getInstance().getMWApi(); - SharedPreferences prefs = this.getContext().getSharedPreferences("prefs", Context.MODE_PRIVATE); + SharedPreferences prefs = getContext().getSharedPreferences("prefs", MODE_PRIVATE); String lastModified = prefs.getString("lastSyncTimestamp", ""); Date curTime = new Date(); LogEventResult result; Boolean done = false; String queryContinue = null; - while(!done) { + while (!done) { try { result = api.logEvents(user, lastModified, queryContinue, getLimit()); @@ -90,19 +99,21 @@ public class ContributionsSyncAdapter extends AbstractThreadedSyncAdapter { continue; } String filename = image.getFilename(); - if(fileExists(contentProviderClient, filename)) { + if (fileExists(contentProviderClient, filename)) { Timber.d("Skipping %s", filename); continue; } String thumbUrl = Utils.makeThumbBaseUrl(filename); Date dateUpdated = image.getDateUpdated(); - Contribution contrib = new Contribution(null, thumbUrl, filename, "", -1, dateUpdated, dateUpdated, user, "", ""); - contrib.setState(Contribution.STATE_COMPLETED); + Contribution contrib = new Contribution(null, thumbUrl, filename, + "", -1, dateUpdated, dateUpdated, user, + "", ""); + contrib.setState(STATE_COMPLETED); imageValues.add(contrib.toContentValues()); - if(imageValues.size() % COMMIT_THRESHOLD == 0) { + if (imageValues.size() % COMMIT_THRESHOLD == 0) { try { - contentProviderClient.bulkInsert(ContributionsContentProvider.BASE_URI, imageValues.toArray(new ContentValues[]{})); + contentProviderClient.bulkInsert(BASE_URI, imageValues.toArray(EMPTY)); } catch (RemoteException e) { throw new RuntimeException(e); } @@ -110,20 +121,21 @@ public class ContributionsSyncAdapter extends AbstractThreadedSyncAdapter { } } - if(imageValues.size() != 0) { + if (imageValues.size() != 0) { try { - contentProviderClient.bulkInsert(ContributionsContentProvider.BASE_URI, imageValues.toArray(new ContentValues[]{})); + contentProviderClient.bulkInsert(BASE_URI, imageValues.toArray(EMPTY)); } catch (RemoteException e) { throw new RuntimeException(e); } } queryContinue = result.getQueryContinue(); - if(TextUtils.isEmpty(queryContinue)) { + if (TextUtils.isEmpty(queryContinue)) { done = true; } } prefs.edit().putString("lastSyncTimestamp", Utils.toMWDate(curTime)).apply(); Timber.d("Oh hai, everyone! Look, a kitty!"); } + } diff --git a/app/src/main/java/fr/free/nrw/commons/media/MediaDetailPagerFragment.java b/app/src/main/java/fr/free/nrw/commons/media/MediaDetailPagerFragment.java index 271ac5c92..42c463dca 100644 --- a/app/src/main/java/fr/free/nrw/commons/media/MediaDetailPagerFragment.java +++ b/app/src/main/java/fr/free/nrw/commons/media/MediaDetailPagerFragment.java @@ -1,11 +1,8 @@ package fr.free.nrw.commons.media; -import android.Manifest; import android.annotation.SuppressLint; import android.app.DownloadManager; -import android.content.Context; import android.content.Intent; -import android.content.pm.PackageManager; import android.database.DataSetObserver; import android.net.Uri; import android.os.Build; @@ -34,23 +31,16 @@ import fr.free.nrw.commons.contributions.Contribution; import fr.free.nrw.commons.contributions.ContributionsActivity; import fr.free.nrw.commons.mwapi.EventLog; +import static android.Manifest.permission.READ_EXTERNAL_STORAGE; +import static android.content.Context.DOWNLOAD_SERVICE; +import static android.content.Intent.ACTION_VIEW; +import static android.content.pm.PackageManager.PERMISSION_GRANTED; +import static fr.free.nrw.commons.CommonsApplication.EVENT_SHARE_ATTEMPT; + public class MediaDetailPagerFragment extends Fragment implements ViewPager.OnPageChangeListener { - public interface MediaDetailProvider { - Media getMediaAtPosition(int i); - - int getTotalMediaCount(); - - void notifyDatasetChanged(); - - void registerDataSetObserver(DataSetObserver observer); - - void unregisterDataSetObserver(DataSetObserver observer); - } - private ViewPager pager; private Boolean editable; - private CommonsApplication app; public MediaDetailPagerFragment() { this(false); @@ -61,30 +51,10 @@ public class MediaDetailPagerFragment extends Fragment implements ViewPager.OnPa this.editable = editable; } - //FragmentStatePagerAdapter allows user to swipe across collection of images (no. of images undetermined) - private class MediaDetailAdapter extends FragmentStatePagerAdapter { - - public MediaDetailAdapter(FragmentManager fm) { - super(fm); - } - - @Override - public Fragment getItem(int i) { - if (i == 0) { - // See bug https://code.google.com/p/android/issues/detail?id=27526 - pager.postDelayed(() -> getActivity().supportInvalidateOptionsMenu(), 5); - } - return MediaDetailFragment.forMedia(i, editable); - } - - @Override - public int getCount() { - return ((MediaDetailProvider)getActivity()).getTotalMediaCount(); - } - } - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + public View onCreateView(LayoutInflater inflater, + ViewGroup container, + Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_media_detail_pager, container, false); pager = (ViewPager) view.findViewById(R.id.mediaDetailsPager); pager.addOnPageChangeListener(this); @@ -120,18 +90,18 @@ public class MediaDetailPagerFragment extends Fragment implements ViewPager.OnPa if (savedInstanceState != null) { editable = savedInstanceState.getBoolean("editable"); } - app = CommonsApplication.getInstance(); setHasOptionsMenu(true); } @Override public boolean onOptionsItemSelected(MenuItem item) { - MediaDetailProvider provider = (MediaDetailProvider)getActivity(); + MediaDetailProvider provider = (MediaDetailProvider) getActivity(); Media m = provider.getMediaAtPosition(pager.getCurrentItem()); - switch(item.getItemId()) { + switch (item.getItemId()) { case R.id.menu_share_current_image: // Share - this is just logs it, intent set in onCreateOptionsMenu, around line 252 - EventLog.schema(CommonsApplication.EVENT_SHARE_ATTEMPT) + CommonsApplication app = (CommonsApplication) getActivity().getApplication(); + EventLog.schema(EVENT_SHARE_ATTEMPT) .param("username", app.getCurrentAccount().name) .param("filename", m.getFilename()) .log(); @@ -139,7 +109,7 @@ public class MediaDetailPagerFragment extends Fragment implements ViewPager.OnPa case R.id.menu_browser_current_image: // View in browser Intent viewIntent = new Intent(); - viewIntent.setAction(Intent.ACTION_VIEW); + viewIntent.setAction(ACTION_VIEW); viewIntent.setData(m.getFilePageTitle().getMobileUri()); startActivity(viewIntent); return true; @@ -149,12 +119,12 @@ public class MediaDetailPagerFragment extends Fragment implements ViewPager.OnPa return true; case R.id.menu_retry_current_image: // Retry - ((ContributionsActivity)getActivity()).retryUpload(pager.getCurrentItem()); + ((ContributionsActivity) getActivity()).retryUpload(pager.getCurrentItem()); getActivity().getSupportFragmentManager().popBackStack(); return true; case R.id.menu_cancel_current_image: // todo: delete image - ((ContributionsActivity)getActivity()).deleteUpload(pager.getCurrentItem()); + ((ContributionsActivity) getActivity()).deleteUpload(pager.getCurrentItem()); getActivity().getSupportFragmentManager().popBackStack(); return true; default: @@ -170,7 +140,7 @@ public class MediaDetailPagerFragment extends Fragment implements ViewPager.OnPa */ private void downloadMedia(Media m) { String imageUrl = m.getImageUrl(), - fileName = m.getFilename(); + fileName = m.getFilename(); // Strip 'File:' from beginning of filename, we really shouldn't store it fileName = fileName.replaceFirst("^File:", ""); Uri imageUri = Uri.parse(imageUrl); @@ -185,14 +155,15 @@ public class MediaDetailPagerFragment extends Fragment implements ViewPager.OnPa req.allowScanningByMediaScanner(); req.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !(ContextCompat.checkSelfPermission(getContext(), Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED)) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M + && !(ContextCompat.checkSelfPermission(getContext(), + READ_EXTERNAL_STORAGE) == PERMISSION_GRANTED)) { Snackbar.make(getView(), R.string.storage_permission_rationale, - Snackbar.LENGTH_INDEFINITE) - .setAction(R.string.ok, view -> ActivityCompat.requestPermissions(getActivity(), - new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, 1)).show(); + Snackbar.LENGTH_INDEFINITE).setAction(R.string.ok, + view -> ActivityCompat.requestPermissions(getActivity(), + new String[]{READ_EXTERNAL_STORAGE}, 1)).show(); } else { - final DownloadManager manager = (DownloadManager)getActivity().getSystemService(Context.DOWNLOAD_SERVICE); - manager.enqueue(req); + ((DownloadManager) getActivity().getSystemService(DOWNLOAD_SERVICE)).enqueue(req); } } @@ -202,7 +173,7 @@ public class MediaDetailPagerFragment extends Fragment implements ViewPager.OnPa menu.clear(); // see http://stackoverflow.com/a/8495697/17865 inflater.inflate(R.menu.fragment_image_detail, menu); if (pager != null) { - MediaDetailProvider provider = (MediaDetailProvider)getActivity(); + MediaDetailProvider provider = (MediaDetailProvider) getActivity(); Media m = provider.getMediaAtPosition(pager.getCurrentItem()); if (m != null) { // Enable default set of actions, then re-enable different set of actions only if it is a failed contrib @@ -225,8 +196,8 @@ public class MediaDetailPagerFragment extends Fragment implements ViewPager.OnPa } if (m instanceof Contribution) { - Contribution c = (Contribution)m; - switch(c.getState()) { + Contribution c = (Contribution) m; + switch (c.getState()) { case Contribution.STATE_FAILED: menu.findItem(R.id.menu_retry_current_image).setEnabled(true).setVisible(true); menu.findItem(R.id.menu_cancel_current_image).setEnabled(true).setVisible(true); @@ -267,6 +238,39 @@ public class MediaDetailPagerFragment extends Fragment implements ViewPager.OnPa @Override public void onPageScrollStateChanged(int i) { + } + public interface MediaDetailProvider { + Media getMediaAtPosition(int i); + + int getTotalMediaCount(); + + void notifyDatasetChanged(); + + void registerDataSetObserver(DataSetObserver observer); + + void unregisterDataSetObserver(DataSetObserver observer); + } + + //FragmentStatePagerAdapter allows user to swipe across collection of images (no. of images undetermined) + private class MediaDetailAdapter extends FragmentStatePagerAdapter { + + public MediaDetailAdapter(FragmentManager fm) { + super(fm); + } + + @Override + public Fragment getItem(int i) { + if (i == 0) { + // See bug https://code.google.com/p/android/issues/detail?id=27526 + pager.postDelayed(() -> getActivity().supportInvalidateOptionsMenu(), 5); + } + return MediaDetailFragment.forMedia(i, editable); + } + + @Override + public int getCount() { + return ((MediaDetailProvider) getActivity()).getTotalMediaCount(); + } } } \ No newline at end of file diff --git a/app/src/main/java/fr/free/nrw/commons/nearby/NearbyInfoDialog.java b/app/src/main/java/fr/free/nrw/commons/nearby/NearbyInfoDialog.java index 1203d5a0d..2e677f33d 100644 --- a/app/src/main/java/fr/free/nrw/commons/nearby/NearbyInfoDialog.java +++ b/app/src/main/java/fr/free/nrw/commons/nearby/NearbyInfoDialog.java @@ -63,10 +63,10 @@ public class NearbyInfoDialog extends OverlayDialog { overflowButton.setVisibility(showMenu() ? View.VISIBLE : View.GONE); - overflowButton.setOnClickListener(this::popupMenuListener); + overflowButton.setOnClickListener(v -> popupMenuListener()); } - private void popupMenuListener(View v) { + private void popupMenuListener() { PopupMenu popupMenu = new PopupMenu(getActivity(), overflowButton); popupMenu.inflate(R.menu.nearby_info_dialog_options);