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