From c959321ab08a8fdff6994d198053090a62b255b6 Mon Sep 17 00:00:00 2001 From: Josephine Lim Date: Wed, 2 May 2018 20:17:32 +1000 Subject: [PATCH 01/53] Update issue_template.md It feels like the template for reporting bugs is a bit redundant - we have summary, steps to reproduce, observed behaviour AND expected behaviour, which all are very similar. I think that by paring it down to the essentials, people will be less likely to skip steps. --- ISSUE_TEMPLATE.md | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/ISSUE_TEMPLATE.md b/ISSUE_TEMPLATE.md index 691562b04..ce33f1a18 100644 --- a/ISSUE_TEMPLATE.md +++ b/ISSUE_TEMPLATE.md @@ -1,9 +1,9 @@ -_Before creating an issue, please search the existing issues to see if a similar one has already been created. You can search issues by specific labels (e.g. `label:nearby `) or just by typing keywords into the search filter._ - **Summary:** Summarize your issue in one sentence (what goes wrong, what did you expect to happen) +_Before creating an issue, please search the existing issues to see if a similar one has already been created. You can search issues by specific labels (e.g. `label:nearby `) or just by typing keywords into the search filter._ + **Steps to reproduce:** How can we reproduce the issue? @@ -12,14 +12,6 @@ How can we reproduce the issue? Add logcat files here (if possible). -**Expected behavior:** - -What did you expect the App to do? - -**Observed behavior:** - -What did you see instead? Describe your issue in detail here. - **Device and Android version:** What make and model device (e.g., Samsung J7) did you encounter this on? What Android @@ -28,7 +20,7 @@ version (e.g., Android 4.0 Ice Cream Sandwich or Android 6.0 Marshmallow) are yo **Commons app version:** -You can find this information by going to the navigation drawer in the app and tapping 'About' +You can find this information by going to the navigation drawer in the app and tapping 'About'. If you are building from our codebase instead of downloading the app, please also mention the branch and build variant (e.g. master and prodDebug). **Screen-shots:** From dcf43e66826877219f16109f3927192e34ce41c4 Mon Sep 17 00:00:00 2001 From: Shridhar Goel Date: Fri, 11 May 2018 18:59:09 +0530 Subject: [PATCH 02/53] Made changes to the error message when user enters wrong login credentials. --- app/src/main/res/values/strings.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index dcea51bcc..7b3fcbc17 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -46,8 +46,8 @@ Please provide a title for this file Description Unable to login - network failure - Unable to login - please check your username - Unable to login - please check your password + Unable to login - please check your username and password + Unable to login - please check your username and password Too many unsuccessful attempts. Please try again in a few minutes. Sorry, this user has been blocked on Commons You must provide your two factor authentication code. From 7adf79c07d9a5f8417615ca07750e3437daf9fff Mon Sep 17 00:00:00 2001 From: Shridhar Goel Date: Fri, 11 May 2018 19:34:04 +0530 Subject: [PATCH 03/53] Used a single string for the error message when user enters wrong login credentials. --- app/src/main/java/fr/free/nrw/commons/auth/LoginActivity.java | 4 ++-- app/src/main/res/values/strings.xml | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/fr/free/nrw/commons/auth/LoginActivity.java b/app/src/main/java/fr/free/nrw/commons/auth/LoginActivity.java index d0fb628e3..b19d70a4e 100644 --- a/app/src/main/java/fr/free/nrw/commons/auth/LoginActivity.java +++ b/app/src/main/java/fr/free/nrw/commons/auth/LoginActivity.java @@ -271,11 +271,11 @@ public class LoginActivity extends AccountAuthenticatorActivity { showMessageAndCancelDialog(R.string.login_failed_network); } else if (result.toLowerCase(Locale.getDefault()).contains("nosuchuser".toLowerCase()) || result.toLowerCase().contains("noname".toLowerCase())) { // Matches nosuchuser, nosuchusershort, noname - showMessageAndCancelDialog(R.string.login_failed_username); + showMessageAndCancelDialog(R.string.login_failed_wrong_credentials); emptySensitiveEditFields(); } else if (result.toLowerCase(Locale.getDefault()).contains("wrongpassword".toLowerCase())) { // Matches wrongpassword, wrongpasswordempty - showMessageAndCancelDialog(R.string.login_failed_password); + showMessageAndCancelDialog(R.string.login_failed_wrong_credentials); emptySensitiveEditFields(); } else if (result.toLowerCase(Locale.getDefault()).contains("throttle".toLowerCase())) { // Matches unknown throttle error codes diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 7b3fcbc17..1562b6302 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -46,8 +46,7 @@ Please provide a title for this file Description Unable to login - network failure - Unable to login - please check your username and password - Unable to login - please check your username and password + Unable to login - please check your username and password Too many unsuccessful attempts. Please try again in a few minutes. Sorry, this user has been blocked on Commons You must provide your two factor authentication code. From 089c2917a4e70233ec0c183073d8b438fe6d2bbc Mon Sep 17 00:00:00 2001 From: Sean Nemann Date: Mon, 28 May 2018 19:18:59 -0400 Subject: [PATCH 04/53] Upon creating AuthenticatedActivity, now checking if the user is blocked via api call and notifying the user if they are blocked via snackbar --- .../commons/auth/AuthenticatedActivity.java | 19 ++++++++++++++++++ .../free/nrw/commons/auth/LoginActivity.java | 1 + .../mwapi/ApacheHttpClientMediaWikiApi.java | 20 +++++++++++++++++++ .../free/nrw/commons/mwapi/MediaWikiApi.java | 2 ++ app/src/main/res/values/strings.xml | 1 + 5 files changed, 43 insertions(+) diff --git a/app/src/main/java/fr/free/nrw/commons/auth/AuthenticatedActivity.java b/app/src/main/java/fr/free/nrw/commons/auth/AuthenticatedActivity.java index e39528252..19fabf7d2 100644 --- a/app/src/main/java/fr/free/nrw/commons/auth/AuthenticatedActivity.java +++ b/app/src/main/java/fr/free/nrw/commons/auth/AuthenticatedActivity.java @@ -4,8 +4,13 @@ import android.os.Bundle; import javax.inject.Inject; +import fr.free.nrw.commons.R; import fr.free.nrw.commons.mwapi.MediaWikiApi; import fr.free.nrw.commons.theme.NavigationBaseActivity; +import fr.free.nrw.commons.utils.ViewUtil; +import io.reactivex.Observable; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.schedulers.Schedulers; import static fr.free.nrw.commons.auth.AccountUtil.AUTH_COOKIE; @@ -34,6 +39,8 @@ public abstract class AuthenticatedActivity extends NavigationBaseActivity { if (savedInstanceState != null) { authCookie = savedInstanceState.getString(AUTH_COOKIE); } + + showBlockStatus(); } @Override @@ -45,4 +52,16 @@ public abstract class AuthenticatedActivity extends NavigationBaseActivity { protected abstract void onAuthCookieAcquired(String authCookie); protected abstract void onAuthFailure(); + + protected void showBlockStatus() + { + Observable.fromCallable(() -> mediaWikiApi.isUserBlocked()) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .filter(result -> result) + .subscribe(result -> { + ViewUtil.showSnackbar(findViewById(android.R.id.content), R.string.block_notification); + } + ); + } } diff --git a/app/src/main/java/fr/free/nrw/commons/auth/LoginActivity.java b/app/src/main/java/fr/free/nrw/commons/auth/LoginActivity.java index d0fb628e3..5c3f86c24 100644 --- a/app/src/main/java/fr/free/nrw/commons/auth/LoginActivity.java +++ b/app/src/main/java/fr/free/nrw/commons/auth/LoginActivity.java @@ -162,6 +162,7 @@ public class LoginActivity extends AccountAuthenticatorActivity { if (sessionManager.getCurrentAccount() != null && sessionManager.isUserLoggedIn() && sessionManager.getCachedAuthCookie() != null) { + sessionManager.revalidateAuthToken(); startMainActivity(); } } diff --git a/app/src/main/java/fr/free/nrw/commons/mwapi/ApacheHttpClientMediaWikiApi.java b/app/src/main/java/fr/free/nrw/commons/mwapi/ApacheHttpClientMediaWikiApi.java index 6629d0933..679a6af20 100644 --- a/app/src/main/java/fr/free/nrw/commons/mwapi/ApacheHttpClientMediaWikiApi.java +++ b/app/src/main/java/fr/free/nrw/commons/mwapi/ApacheHttpClientMediaWikiApi.java @@ -615,6 +615,26 @@ public class ApacheHttpClientMediaWikiApi implements MediaWikiApi { }); } + @Override + public boolean isUserBlocked() { + boolean userBlocked = false; + try { + ApiResult result = api.action("query") + .param("action", "query") + .param("format", "xml") + .param("meta", "userinfo") + .param("uiprop", "blockinfo") + .get(); + if(result != null) { + userBlocked = !result.getString("/api/query/userinfo/@blockexpiry").isEmpty(); + } + } catch (Exception e) { + e.printStackTrace(); + } + + return userBlocked; + } + private Date parseMWDate(String mwDate) { SimpleDateFormat isoFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.ENGLISH); // Assuming MW always gives me UTC try { diff --git a/app/src/main/java/fr/free/nrw/commons/mwapi/MediaWikiApi.java b/app/src/main/java/fr/free/nrw/commons/mwapi/MediaWikiApi.java index c0bd2fd87..6ba1f9158 100644 --- a/app/src/main/java/fr/free/nrw/commons/mwapi/MediaWikiApi.java +++ b/app/src/main/java/fr/free/nrw/commons/mwapi/MediaWikiApi.java @@ -75,6 +75,8 @@ public interface MediaWikiApi { @NonNull Single getUploadCount(String userName); + boolean isUserBlocked(); + interface ProgressListener { void onProgress(long transferred, long total); } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 6e30baa10..bd82e5c4d 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -283,5 +283,6 @@ Share App Coordinates were not specified during image selection Error fetching nearby places. + You are blocked from editing commons From 39bf214c572cfbfb433c88ad5cf493a6498d09da Mon Sep 17 00:00:00 2001 From: Sean Nemann Date: Thu, 31 May 2018 09:44:09 -0400 Subject: [PATCH 05/53] Added comments to isUserBlocked method and tests for the method --- .../mwapi/ApacheHttpClientMediaWikiApi.java | 5 ++ .../mwapi/ApacheHttpClientMediaWikiApiTest.kt | 54 +++++++++++++++++++ 2 files changed, 59 insertions(+) diff --git a/app/src/main/java/fr/free/nrw/commons/mwapi/ApacheHttpClientMediaWikiApi.java b/app/src/main/java/fr/free/nrw/commons/mwapi/ApacheHttpClientMediaWikiApi.java index 679a6af20..d5f9a7fce 100644 --- a/app/src/main/java/fr/free/nrw/commons/mwapi/ApacheHttpClientMediaWikiApi.java +++ b/app/src/main/java/fr/free/nrw/commons/mwapi/ApacheHttpClientMediaWikiApi.java @@ -615,6 +615,10 @@ public class ApacheHttpClientMediaWikiApi implements MediaWikiApi { }); } + /** + * Checks to see if a user is currently blocked + * @return whether or not the user is blocked + */ @Override public boolean isUserBlocked() { boolean userBlocked = false; @@ -626,6 +630,7 @@ public class ApacheHttpClientMediaWikiApi implements MediaWikiApi { .param("uiprop", "blockinfo") .get(); if(result != null) { + // the blockexpiry field will only be present if the user is currently blocked userBlocked = !result.getString("/api/query/userinfo/@blockexpiry").isEmpty(); } } catch (Exception e) { diff --git a/app/src/test/kotlin/fr/free/nrw/commons/mwapi/ApacheHttpClientMediaWikiApiTest.kt b/app/src/test/kotlin/fr/free/nrw/commons/mwapi/ApacheHttpClientMediaWikiApiTest.kt index 686a90ef2..6f630ce1a 100644 --- a/app/src/test/kotlin/fr/free/nrw/commons/mwapi/ApacheHttpClientMediaWikiApiTest.kt +++ b/app/src/test/kotlin/fr/free/nrw/commons/mwapi/ApacheHttpClientMediaWikiApiTest.kt @@ -223,6 +223,60 @@ class ApacheHttpClientMediaWikiApiTest { assertEquals(23, testObserver.values()[0]) } + @Test + fun isUserBlockedForInfinitelyBlockedUser() { + server.enqueue(MockResponse().setBody("")) + + val result = testObject.isUserBlocked(); + + assertBasicRequestParameters(server, "GET").let { userBlockedRequest -> + parseQueryParams(userBlockedRequest).let { body -> + assertEquals("xml", body["format"]) + assertEquals("query", body["action"]) + assertEquals("userinfo", body["meta"]) + assertEquals("blockinfo", body["uiprop"]) + } + } + + assertTrue(result) + } + + @Test + fun isUserBlockedForTimeBlockedUser() { + server.enqueue(MockResponse().setBody("")) + + val result = testObject.isUserBlocked(); + + assertBasicRequestParameters(server, "GET").let { userBlockedRequest -> + parseQueryParams(userBlockedRequest).let { body -> + assertEquals("xml", body["format"]) + assertEquals("query", body["action"]) + assertEquals("userinfo", body["meta"]) + assertEquals("blockinfo", body["uiprop"]) + } + } + + assertTrue(result) + } + + @Test + fun isUserBlockedForNotBlockedUser() { + server.enqueue(MockResponse().setBody("")) + + val result = testObject.isUserBlocked(); + + assertBasicRequestParameters(server, "GET").let { userBlockedRequest -> + parseQueryParams(userBlockedRequest).let { body -> + assertEquals("xml", body["format"]) + assertEquals("query", body["action"]) + assertEquals("userinfo", body["meta"]) + assertEquals("blockinfo", body["uiprop"]) + } + } + + assertFalse(result) + } + private fun assertBasicRequestParameters(server: MockWebServer, method: String): RecordedRequest = server.takeRequest().let { assertEquals("/", it.requestUrl.encodedPath()) assertEquals(method, it.method) From 47bffa1b21c26f4a83e096c2a01be287764e2938 Mon Sep 17 00:00:00 2001 From: Sean Nemann Date: Thu, 31 May 2018 11:28:56 -0400 Subject: [PATCH 06/53] Updated isUserBlocked method to check the expiration time instead of just if an expiration time exists. Updated tests accordingly --- .../mwapi/ApacheHttpClientMediaWikiApi.java | 16 ++++++++-- .../mwapi/ApacheHttpClientMediaWikiApiTest.kt | 29 ++++++++++++++++++- 2 files changed, 42 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/fr/free/nrw/commons/mwapi/ApacheHttpClientMediaWikiApi.java b/app/src/main/java/fr/free/nrw/commons/mwapi/ApacheHttpClientMediaWikiApi.java index d5f9a7fce..6db6a4e5a 100644 --- a/app/src/main/java/fr/free/nrw/commons/mwapi/ApacheHttpClientMediaWikiApi.java +++ b/app/src/main/java/fr/free/nrw/commons/mwapi/ApacheHttpClientMediaWikiApi.java @@ -37,6 +37,7 @@ import java.util.Collections; import java.util.Date; import java.util.List; import java.util.Locale; +import java.util.TimeZone; import java.util.concurrent.Callable; import fr.free.nrw.commons.BuildConfig; @@ -630,8 +631,17 @@ public class ApacheHttpClientMediaWikiApi implements MediaWikiApi { .param("uiprop", "blockinfo") .get(); if(result != null) { - // the blockexpiry field will only be present if the user is currently blocked - userBlocked = !result.getString("/api/query/userinfo/@blockexpiry").isEmpty(); + String blockEnd = result.getString("/api/query/userinfo/@blockexpiry"); + if(blockEnd.equals("infinite")) + { + userBlocked = true; + } + else if (!blockEnd.isEmpty()) { + Date endDate = parseMWDate(blockEnd); + Date current = new Date(); + userBlocked = endDate.after(current); + } + } } catch (Exception e) { e.printStackTrace(); @@ -642,10 +652,12 @@ public class ApacheHttpClientMediaWikiApi implements MediaWikiApi { private Date parseMWDate(String mwDate) { SimpleDateFormat isoFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.ENGLISH); // Assuming MW always gives me UTC + isoFormat.setTimeZone(TimeZone.getTimeZone("UTC")); try { return isoFormat.parse(mwDate); } catch (ParseException e) { throw new RuntimeException(e); } } + } diff --git a/app/src/test/kotlin/fr/free/nrw/commons/mwapi/ApacheHttpClientMediaWikiApiTest.kt b/app/src/test/kotlin/fr/free/nrw/commons/mwapi/ApacheHttpClientMediaWikiApiTest.kt index 6f630ce1a..eea86fd2f 100644 --- a/app/src/test/kotlin/fr/free/nrw/commons/mwapi/ApacheHttpClientMediaWikiApiTest.kt +++ b/app/src/test/kotlin/fr/free/nrw/commons/mwapi/ApacheHttpClientMediaWikiApiTest.kt @@ -18,6 +18,7 @@ import org.robolectric.RobolectricTestRunner import org.robolectric.RuntimeEnvironment import org.robolectric.annotation.Config import java.net.URLDecoder +import java.text.SimpleDateFormat import java.util.* @RunWith(RobolectricTestRunner::class) @@ -243,7 +244,11 @@ class ApacheHttpClientMediaWikiApiTest { @Test fun isUserBlockedForTimeBlockedUser() { - server.enqueue(MockResponse().setBody("")) + val currentDate = Date() + val expiredDate = Date(currentDate.time + 10000) + val dateFormat = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'") + dateFormat.setTimeZone(TimeZone.getTimeZone("UTC")) + server.enqueue(MockResponse().setBody("")) val result = testObject.isUserBlocked(); @@ -259,6 +264,28 @@ class ApacheHttpClientMediaWikiApiTest { assertTrue(result) } + @Test + fun isUserBlockedForExpiredBlockedUser() { + val currentDate = Date() + val expiredDate = Date(currentDate.time - 10000) + val dateFormat = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'") + dateFormat.setTimeZone(TimeZone.getTimeZone("UTC")) + server.enqueue(MockResponse().setBody("")) + + val result = testObject.isUserBlocked(); + + assertBasicRequestParameters(server, "GET").let { userBlockedRequest -> + parseQueryParams(userBlockedRequest).let { body -> + assertEquals("xml", body["format"]) + assertEquals("query", body["action"]) + assertEquals("userinfo", body["meta"]) + assertEquals("blockinfo", body["uiprop"]) + } + } + + assertFalse(result) + } + @Test fun isUserBlockedForNotBlockedUser() { server.enqueue(MockResponse().setBody("")) From db30e03cf2a6b96b598f4b91e7136f64eb46ea02 Mon Sep 17 00:00:00 2001 From: Sean Nemann Date: Thu, 31 May 2018 13:37:55 -0400 Subject: [PATCH 07/53] Added javadoc comments to showBlockStatus method --- .../java/fr/free/nrw/commons/auth/AuthenticatedActivity.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/src/main/java/fr/free/nrw/commons/auth/AuthenticatedActivity.java b/app/src/main/java/fr/free/nrw/commons/auth/AuthenticatedActivity.java index 19fabf7d2..f31f36c51 100644 --- a/app/src/main/java/fr/free/nrw/commons/auth/AuthenticatedActivity.java +++ b/app/src/main/java/fr/free/nrw/commons/auth/AuthenticatedActivity.java @@ -53,6 +53,10 @@ public abstract class AuthenticatedActivity extends NavigationBaseActivity { protected abstract void onAuthFailure(); + /** + * Makes API call to check if user is blocked. If the user is blocked, a snackbar + * is created to notify the user + */ protected void showBlockStatus() { Observable.fromCallable(() -> mediaWikiApi.isUserBlocked()) From 39096cf30baafa78f925f61220bbcedd3ebbd62c Mon Sep 17 00:00:00 2001 From: Sean Nemann Date: Mon, 28 May 2018 19:18:59 -0400 Subject: [PATCH 08/53] Upon creating AuthenticatedActivity, now checking if the user is blocked via api call and notifying the user if they are blocked via snackbar --- .../commons/auth/AuthenticatedActivity.java | 19 ++++++++++++++++++ .../free/nrw/commons/auth/LoginActivity.java | 1 + .../mwapi/ApacheHttpClientMediaWikiApi.java | 20 +++++++++++++++++++ .../free/nrw/commons/mwapi/MediaWikiApi.java | 2 ++ app/src/main/res/values/strings.xml | 1 + 5 files changed, 43 insertions(+) diff --git a/app/src/main/java/fr/free/nrw/commons/auth/AuthenticatedActivity.java b/app/src/main/java/fr/free/nrw/commons/auth/AuthenticatedActivity.java index e39528252..19fabf7d2 100644 --- a/app/src/main/java/fr/free/nrw/commons/auth/AuthenticatedActivity.java +++ b/app/src/main/java/fr/free/nrw/commons/auth/AuthenticatedActivity.java @@ -4,8 +4,13 @@ import android.os.Bundle; import javax.inject.Inject; +import fr.free.nrw.commons.R; import fr.free.nrw.commons.mwapi.MediaWikiApi; import fr.free.nrw.commons.theme.NavigationBaseActivity; +import fr.free.nrw.commons.utils.ViewUtil; +import io.reactivex.Observable; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.schedulers.Schedulers; import static fr.free.nrw.commons.auth.AccountUtil.AUTH_COOKIE; @@ -34,6 +39,8 @@ public abstract class AuthenticatedActivity extends NavigationBaseActivity { if (savedInstanceState != null) { authCookie = savedInstanceState.getString(AUTH_COOKIE); } + + showBlockStatus(); } @Override @@ -45,4 +52,16 @@ public abstract class AuthenticatedActivity extends NavigationBaseActivity { protected abstract void onAuthCookieAcquired(String authCookie); protected abstract void onAuthFailure(); + + protected void showBlockStatus() + { + Observable.fromCallable(() -> mediaWikiApi.isUserBlocked()) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .filter(result -> result) + .subscribe(result -> { + ViewUtil.showSnackbar(findViewById(android.R.id.content), R.string.block_notification); + } + ); + } } diff --git a/app/src/main/java/fr/free/nrw/commons/auth/LoginActivity.java b/app/src/main/java/fr/free/nrw/commons/auth/LoginActivity.java index b19d70a4e..339af96d7 100644 --- a/app/src/main/java/fr/free/nrw/commons/auth/LoginActivity.java +++ b/app/src/main/java/fr/free/nrw/commons/auth/LoginActivity.java @@ -162,6 +162,7 @@ public class LoginActivity extends AccountAuthenticatorActivity { if (sessionManager.getCurrentAccount() != null && sessionManager.isUserLoggedIn() && sessionManager.getCachedAuthCookie() != null) { + sessionManager.revalidateAuthToken(); startMainActivity(); } } diff --git a/app/src/main/java/fr/free/nrw/commons/mwapi/ApacheHttpClientMediaWikiApi.java b/app/src/main/java/fr/free/nrw/commons/mwapi/ApacheHttpClientMediaWikiApi.java index e962bdaf3..13eb77e83 100644 --- a/app/src/main/java/fr/free/nrw/commons/mwapi/ApacheHttpClientMediaWikiApi.java +++ b/app/src/main/java/fr/free/nrw/commons/mwapi/ApacheHttpClientMediaWikiApi.java @@ -615,6 +615,26 @@ public class ApacheHttpClientMediaWikiApi implements MediaWikiApi { }); } + @Override + public boolean isUserBlocked() { + boolean userBlocked = false; + try { + ApiResult result = api.action("query") + .param("action", "query") + .param("format", "xml") + .param("meta", "userinfo") + .param("uiprop", "blockinfo") + .get(); + if(result != null) { + userBlocked = !result.getString("/api/query/userinfo/@blockexpiry").isEmpty(); + } + } catch (Exception e) { + e.printStackTrace(); + } + + return userBlocked; + } + private Date parseMWDate(String mwDate) { SimpleDateFormat isoFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.ENGLISH); // Assuming MW always gives me UTC try { diff --git a/app/src/main/java/fr/free/nrw/commons/mwapi/MediaWikiApi.java b/app/src/main/java/fr/free/nrw/commons/mwapi/MediaWikiApi.java index c0bd2fd87..6ba1f9158 100644 --- a/app/src/main/java/fr/free/nrw/commons/mwapi/MediaWikiApi.java +++ b/app/src/main/java/fr/free/nrw/commons/mwapi/MediaWikiApi.java @@ -75,6 +75,8 @@ public interface MediaWikiApi { @NonNull Single getUploadCount(String userName); + boolean isUserBlocked(); + interface ProgressListener { void onProgress(long transferred, long total); } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index d3e3902e5..6828af2c3 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -282,6 +282,7 @@ Share App Coordinates were not specified during image selection Error fetching nearby places. + You are blocked from editing commons Set wallpaper Wallpaper set successfully! From 01a3a233a90a33e6c74b41c3024852e9f89fbd22 Mon Sep 17 00:00:00 2001 From: Sean Nemann Date: Thu, 31 May 2018 09:44:09 -0400 Subject: [PATCH 09/53] Added comments to isUserBlocked method and tests for the method --- .../mwapi/ApacheHttpClientMediaWikiApi.java | 5 ++ .../mwapi/ApacheHttpClientMediaWikiApiTest.kt | 54 +++++++++++++++++++ 2 files changed, 59 insertions(+) diff --git a/app/src/main/java/fr/free/nrw/commons/mwapi/ApacheHttpClientMediaWikiApi.java b/app/src/main/java/fr/free/nrw/commons/mwapi/ApacheHttpClientMediaWikiApi.java index 13eb77e83..b78ad88ae 100644 --- a/app/src/main/java/fr/free/nrw/commons/mwapi/ApacheHttpClientMediaWikiApi.java +++ b/app/src/main/java/fr/free/nrw/commons/mwapi/ApacheHttpClientMediaWikiApi.java @@ -615,6 +615,10 @@ public class ApacheHttpClientMediaWikiApi implements MediaWikiApi { }); } + /** + * Checks to see if a user is currently blocked + * @return whether or not the user is blocked + */ @Override public boolean isUserBlocked() { boolean userBlocked = false; @@ -626,6 +630,7 @@ public class ApacheHttpClientMediaWikiApi implements MediaWikiApi { .param("uiprop", "blockinfo") .get(); if(result != null) { + // the blockexpiry field will only be present if the user is currently blocked userBlocked = !result.getString("/api/query/userinfo/@blockexpiry").isEmpty(); } } catch (Exception e) { diff --git a/app/src/test/kotlin/fr/free/nrw/commons/mwapi/ApacheHttpClientMediaWikiApiTest.kt b/app/src/test/kotlin/fr/free/nrw/commons/mwapi/ApacheHttpClientMediaWikiApiTest.kt index 686a90ef2..6f630ce1a 100644 --- a/app/src/test/kotlin/fr/free/nrw/commons/mwapi/ApacheHttpClientMediaWikiApiTest.kt +++ b/app/src/test/kotlin/fr/free/nrw/commons/mwapi/ApacheHttpClientMediaWikiApiTest.kt @@ -223,6 +223,60 @@ class ApacheHttpClientMediaWikiApiTest { assertEquals(23, testObserver.values()[0]) } + @Test + fun isUserBlockedForInfinitelyBlockedUser() { + server.enqueue(MockResponse().setBody("")) + + val result = testObject.isUserBlocked(); + + assertBasicRequestParameters(server, "GET").let { userBlockedRequest -> + parseQueryParams(userBlockedRequest).let { body -> + assertEquals("xml", body["format"]) + assertEquals("query", body["action"]) + assertEquals("userinfo", body["meta"]) + assertEquals("blockinfo", body["uiprop"]) + } + } + + assertTrue(result) + } + + @Test + fun isUserBlockedForTimeBlockedUser() { + server.enqueue(MockResponse().setBody("")) + + val result = testObject.isUserBlocked(); + + assertBasicRequestParameters(server, "GET").let { userBlockedRequest -> + parseQueryParams(userBlockedRequest).let { body -> + assertEquals("xml", body["format"]) + assertEquals("query", body["action"]) + assertEquals("userinfo", body["meta"]) + assertEquals("blockinfo", body["uiprop"]) + } + } + + assertTrue(result) + } + + @Test + fun isUserBlockedForNotBlockedUser() { + server.enqueue(MockResponse().setBody("")) + + val result = testObject.isUserBlocked(); + + assertBasicRequestParameters(server, "GET").let { userBlockedRequest -> + parseQueryParams(userBlockedRequest).let { body -> + assertEquals("xml", body["format"]) + assertEquals("query", body["action"]) + assertEquals("userinfo", body["meta"]) + assertEquals("blockinfo", body["uiprop"]) + } + } + + assertFalse(result) + } + private fun assertBasicRequestParameters(server: MockWebServer, method: String): RecordedRequest = server.takeRequest().let { assertEquals("/", it.requestUrl.encodedPath()) assertEquals(method, it.method) From fcfae643c3478dfe2fdf31128af4feb8ef837063 Mon Sep 17 00:00:00 2001 From: Sean Nemann Date: Thu, 31 May 2018 11:28:56 -0400 Subject: [PATCH 10/53] Updated isUserBlocked method to check the expiration time instead of just if an expiration time exists. Updated tests accordingly --- .../mwapi/ApacheHttpClientMediaWikiApi.java | 16 ++++++++-- .../mwapi/ApacheHttpClientMediaWikiApiTest.kt | 29 ++++++++++++++++++- 2 files changed, 42 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/fr/free/nrw/commons/mwapi/ApacheHttpClientMediaWikiApi.java b/app/src/main/java/fr/free/nrw/commons/mwapi/ApacheHttpClientMediaWikiApi.java index b78ad88ae..c24ee2f21 100644 --- a/app/src/main/java/fr/free/nrw/commons/mwapi/ApacheHttpClientMediaWikiApi.java +++ b/app/src/main/java/fr/free/nrw/commons/mwapi/ApacheHttpClientMediaWikiApi.java @@ -37,6 +37,7 @@ import java.util.Collections; import java.util.Date; import java.util.List; import java.util.Locale; +import java.util.TimeZone; import java.util.concurrent.Callable; import fr.free.nrw.commons.BuildConfig; @@ -630,8 +631,17 @@ public class ApacheHttpClientMediaWikiApi implements MediaWikiApi { .param("uiprop", "blockinfo") .get(); if(result != null) { - // the blockexpiry field will only be present if the user is currently blocked - userBlocked = !result.getString("/api/query/userinfo/@blockexpiry").isEmpty(); + String blockEnd = result.getString("/api/query/userinfo/@blockexpiry"); + if(blockEnd.equals("infinite")) + { + userBlocked = true; + } + else if (!blockEnd.isEmpty()) { + Date endDate = parseMWDate(blockEnd); + Date current = new Date(); + userBlocked = endDate.after(current); + } + } } catch (Exception e) { e.printStackTrace(); @@ -642,10 +652,12 @@ public class ApacheHttpClientMediaWikiApi implements MediaWikiApi { private Date parseMWDate(String mwDate) { SimpleDateFormat isoFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.ENGLISH); // Assuming MW always gives me UTC + isoFormat.setTimeZone(TimeZone.getTimeZone("UTC")); try { return isoFormat.parse(mwDate); } catch (ParseException e) { throw new RuntimeException(e); } } + } diff --git a/app/src/test/kotlin/fr/free/nrw/commons/mwapi/ApacheHttpClientMediaWikiApiTest.kt b/app/src/test/kotlin/fr/free/nrw/commons/mwapi/ApacheHttpClientMediaWikiApiTest.kt index 6f630ce1a..eea86fd2f 100644 --- a/app/src/test/kotlin/fr/free/nrw/commons/mwapi/ApacheHttpClientMediaWikiApiTest.kt +++ b/app/src/test/kotlin/fr/free/nrw/commons/mwapi/ApacheHttpClientMediaWikiApiTest.kt @@ -18,6 +18,7 @@ import org.robolectric.RobolectricTestRunner import org.robolectric.RuntimeEnvironment import org.robolectric.annotation.Config import java.net.URLDecoder +import java.text.SimpleDateFormat import java.util.* @RunWith(RobolectricTestRunner::class) @@ -243,7 +244,11 @@ class ApacheHttpClientMediaWikiApiTest { @Test fun isUserBlockedForTimeBlockedUser() { - server.enqueue(MockResponse().setBody("")) + val currentDate = Date() + val expiredDate = Date(currentDate.time + 10000) + val dateFormat = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'") + dateFormat.setTimeZone(TimeZone.getTimeZone("UTC")) + server.enqueue(MockResponse().setBody("")) val result = testObject.isUserBlocked(); @@ -259,6 +264,28 @@ class ApacheHttpClientMediaWikiApiTest { assertTrue(result) } + @Test + fun isUserBlockedForExpiredBlockedUser() { + val currentDate = Date() + val expiredDate = Date(currentDate.time - 10000) + val dateFormat = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'") + dateFormat.setTimeZone(TimeZone.getTimeZone("UTC")) + server.enqueue(MockResponse().setBody("")) + + val result = testObject.isUserBlocked(); + + assertBasicRequestParameters(server, "GET").let { userBlockedRequest -> + parseQueryParams(userBlockedRequest).let { body -> + assertEquals("xml", body["format"]) + assertEquals("query", body["action"]) + assertEquals("userinfo", body["meta"]) + assertEquals("blockinfo", body["uiprop"]) + } + } + + assertFalse(result) + } + @Test fun isUserBlockedForNotBlockedUser() { server.enqueue(MockResponse().setBody("")) From 4aac81d6273182097d0c01e0910982985080dde8 Mon Sep 17 00:00:00 2001 From: Sean Nemann Date: Thu, 31 May 2018 13:37:55 -0400 Subject: [PATCH 11/53] Added javadoc comments to showBlockStatus method --- .../java/fr/free/nrw/commons/auth/AuthenticatedActivity.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/src/main/java/fr/free/nrw/commons/auth/AuthenticatedActivity.java b/app/src/main/java/fr/free/nrw/commons/auth/AuthenticatedActivity.java index 19fabf7d2..f31f36c51 100644 --- a/app/src/main/java/fr/free/nrw/commons/auth/AuthenticatedActivity.java +++ b/app/src/main/java/fr/free/nrw/commons/auth/AuthenticatedActivity.java @@ -53,6 +53,10 @@ public abstract class AuthenticatedActivity extends NavigationBaseActivity { protected abstract void onAuthFailure(); + /** + * Makes API call to check if user is blocked. If the user is blocked, a snackbar + * is created to notify the user + */ protected void showBlockStatus() { Observable.fromCallable(() -> mediaWikiApi.isUserBlocked()) From 3f47d39cdffc9d50244ca2757c92ff8d08b72845 Mon Sep 17 00:00:00 2001 From: "translatewiki.net" Date: Thu, 7 Jun 2018 08:05:24 +0200 Subject: [PATCH 12/53] Localisation updates from https://translatewiki.net. --- app/src/main/res/values-de/strings.xml | 2 ++ app/src/main/res/values-el/strings.xml | 2 ++ app/src/main/res/values-gl/strings.xml | 13 +++++++++++++ app/src/main/res/values-iw/strings.xml | 2 ++ app/src/main/res/values-ko/strings.xml | 2 ++ app/src/main/res/values-mk/strings.xml | 2 ++ app/src/main/res/values-pms/strings.xml | 2 ++ app/src/main/res/values-pt/strings.xml | 2 ++ app/src/main/res/values-ru/strings.xml | 2 ++ app/src/main/res/values-sv/strings.xml | 2 ++ app/src/main/res/values-uk/strings.xml | 2 ++ app/src/main/res/values-zh-rTW/strings.xml | 2 ++ app/src/main/res/values-zh/strings.xml | 2 ++ 13 files changed, 37 insertions(+) diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index f0eab6cb2..8d82fe80f 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -278,6 +278,8 @@ App teilen Während der Bildauswahl wurden keine Koordinaten angegeben Fehler beim Abrufen der Orte in der Nähe. + Bild erfolgreich nach %1$s auf Wikidata hinzugefügt! + Fehler bei der Aktualisierung des dazugehörigen Wikidata-Objekts! Hintergrundbild festlegen Hintergrundbild erfolgreich festgelegt! diff --git a/app/src/main/res/values-el/strings.xml b/app/src/main/res/values-el/strings.xml index 876b76924..1e738cafc 100644 --- a/app/src/main/res/values-el/strings.xml +++ b/app/src/main/res/values-el/strings.xml @@ -282,6 +282,8 @@ Κοινοποίηση εφαρμογής Οι συντεταγμένες δεν ορίστηκαν κατά την διάρκεια της επιλογής εικόνας Σφάλμα κατά την εύρεση κοντινών μερών. + Η εικόνα προστέθηκε επιτυχώς στο %1$s στο Wikidata! + Αποτυχία ενημέρωσης της αντιστοιχούσας οντότητας δεδομένων βίκι! Ρύθμιση ταπετσαρίας Η ταπετσαρία ρυθμίστηκε επιτυχώς! diff --git a/app/src/main/res/values-gl/strings.xml b/app/src/main/res/values-gl/strings.xml index 1dcd7ecca..09e7bb798 100644 --- a/app/src/main/res/values-gl/strings.xml +++ b/app/src/main/res/values-gl/strings.xml @@ -55,6 +55,7 @@ Por favor, proporcione un título para este ficheiro Descrición Erro ao acceder ao sistema: Fallou a rede + Non se pode acceder. Revise o nome de usuario e o contrasinal Demasiados intentos incorrectos. Inténteo de novo nuns minutos. Sentímolo, este usuario está bloqueado en Commons Debe proporcionar o seu código de autenticación de dous factores. @@ -267,4 +268,16 @@ Proceder Cancelar Reintentar + Entendido! + Hai sitios preto de vostede que precisan fotos para ilustrar os seus artigos de Wikipedia + Premendo neste botón aparecerá unha lista destes lugares + Pode cargar unha imaxe de calquera lugar dende a galería ou a cámara + Non se atopou ningunha imaxeǃ + Houbo un erro ó subir as imaxes. + Subida porː %1$s + Compartir a aplicación + Non se indicaron as coordenadas ó seleccionar a imaxe + Erro ó procurar os lugares próximos. + Definir imaxe de fondo + A imaxe de fondo configurouse correctamenteǃ diff --git a/app/src/main/res/values-iw/strings.xml b/app/src/main/res/values-iw/strings.xml index e13626c29..0a92a94fd 100644 --- a/app/src/main/res/values-iw/strings.xml +++ b/app/src/main/res/values-iw/strings.xml @@ -282,6 +282,8 @@ שיתוף היישום לא צוינו קואורדינטות בעת בחירת התמונה שגיאה באחזור המקומות בסביבתך. + התמונה נוספה בהצלחה ל־%1$s בוויקינתונים! + לא ניתן היה לעדכן הישות המתאימה בוויקינתונים! הגדרת רקע הרקע הוגדר בהצלחה! diff --git a/app/src/main/res/values-ko/strings.xml b/app/src/main/res/values-ko/strings.xml index 4cd947699..9959e3ec6 100644 --- a/app/src/main/res/values-ko/strings.xml +++ b/app/src/main/res/values-ko/strings.xml @@ -275,6 +275,8 @@ 앱 공유 그림 선택 중에 좌표가 지정되지 않았습니다 주변 장소를 가져오는데 오류가 있습니다. + 위키데이터의 %1$s에 그림을 성공적으로 추가했습니다! + 일치하는 위키 데이터 엔티티의 업데이트를 실패했습니다! 배경화면 설정 배경화면을 성공적으로 설정했습니다! diff --git a/app/src/main/res/values-mk/strings.xml b/app/src/main/res/values-mk/strings.xml index 66a48e0a0..106b725f4 100644 --- a/app/src/main/res/values-mk/strings.xml +++ b/app/src/main/res/values-mk/strings.xml @@ -272,6 +272,8 @@ Сподели прилог Не беа укажани координати при изборот на сликата Грешка при добивањето на околните места. + Сликата е успешно додадена кон %1$s на Википодатоците! + Не успеав да ја изменам соодветната единица на Википодатоците! Задај позадина Позадината е успешно зададена! diff --git a/app/src/main/res/values-pms/strings.xml b/app/src/main/res/values-pms/strings.xml index c68663306..6b5f984b4 100644 --- a/app/src/main/res/values-pms/strings.xml +++ b/app/src/main/res/values-pms/strings.xml @@ -272,6 +272,8 @@ Partagé j\'aplicassion Le coordinà a son nen ëstàite spessificà durant la selession ëd la plancia Eror durant l\'esplorassion dj\'anviron. + Plancia giontà për da bin a %1$s su Wikidata! + Falì a agiorné l\'entità ëd dàit wiki corëspondent! Definì la tapissarìa La tapissarìa a l\'é stàita definìa për da bin! diff --git a/app/src/main/res/values-pt/strings.xml b/app/src/main/res/values-pt/strings.xml index 22776341f..c24e05a4c 100644 --- a/app/src/main/res/values-pt/strings.xml +++ b/app/src/main/res/values-pt/strings.xml @@ -283,6 +283,8 @@ Partilhar aplicação Não foram especificadas coordenadas durante a seleção da imagem Erro ao localizar locais próximos. + Imagem adicionada a %1$s na wiki Wikidata! + Falha ao atualizar a entidade Wikidata correspondente! Definir imagem de fundo Imagem de fundo definida! diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 754fd228c..8211772ac 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -290,6 +290,8 @@ Поделиться приложением Во время выбора изображения не были указаны координаты Ошибка получения мест поблизости + Изображение успешно добавлено на страницу викиданных! + Не удалось обновить соответствующую страницу викиданных! Сделать фоновой заставкой Фоновая заставка успешно установлена! diff --git a/app/src/main/res/values-sv/strings.xml b/app/src/main/res/values-sv/strings.xml index e57c98b5b..d211946e1 100644 --- a/app/src/main/res/values-sv/strings.xml +++ b/app/src/main/res/values-sv/strings.xml @@ -280,6 +280,8 @@ Dela app Koordinater specificerades inte vid bildvalet Fel uppstod när platser i närheten hämtades. + Bilden lades till i %1$s på Wikidata! + Misslyckades att uppdatera motsvarande wikidataentitet! Ange som bakgrundsbild Bakgrundsbilden ändrades! diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml index 4b0286605..0ebd3ccbf 100644 --- a/app/src/main/res/values-uk/strings.xml +++ b/app/src/main/res/values-uk/strings.xml @@ -289,6 +289,8 @@ Поділитися програмою Під час вибору зображення не були вказані координати Помилка отримання місць поблизу. + Зображення успішно додано до сторінки %1$s у Вікіданих! + Не вдалось оновити відповідну сторінку Вікіданих! Поставити шпалерами екрану Шпалери екрану виставлено успішно! diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index bd1242e12..9b723eb30 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -283,6 +283,8 @@ 分享應用程式 當選擇圖片時未指定座標 索取附近地點時出錯。 + 圖片已成功添加到維基數據上的 %1$s! + 更新所對應的維基數據項目失敗! 設定桌布 桌布設定成功! diff --git a/app/src/main/res/values-zh/strings.xml b/app/src/main/res/values-zh/strings.xml index 445e0f82d..2e4d74ddd 100644 --- a/app/src/main/res/values-zh/strings.xml +++ b/app/src/main/res/values-zh/strings.xml @@ -278,6 +278,8 @@ 分享应用 图片选择时,坐标并未指定 检索附近地点时出错。 + 图片已成功添加到维基数据上的%1$s! + 更新对应wiki的数据实体失败! 设置墙纸 墙纸已成功设置! From a934d24a2d6529d65af8ee5021c6fc6b064f9c1f Mon Sep 17 00:00:00 2001 From: tanvidadu Date: Thu, 7 Jun 2018 15:22:07 +0530 Subject: [PATCH 13/53] Introducing a brief exp of Image License --- .../commons/upload/SingleUploadFragment.java | 16 +++++ .../free/nrw/commons/upload/UrlLicense.java | 72 +++++++++++++++++++ .../res/layout/fragment_single_upload.xml | 20 ++++-- 3 files changed, 104 insertions(+), 4 deletions(-) create mode 100644 app/src/main/java/fr/free/nrw/commons/upload/UrlLicense.java diff --git a/app/src/main/java/fr/free/nrw/commons/upload/SingleUploadFragment.java b/app/src/main/java/fr/free/nrw/commons/upload/SingleUploadFragment.java index a32fb7b42..47c4c7c22 100644 --- a/app/src/main/java/fr/free/nrw/commons/upload/SingleUploadFragment.java +++ b/app/src/main/java/fr/free/nrw/commons/upload/SingleUploadFragment.java @@ -4,6 +4,7 @@ import android.annotation.SuppressLint; import android.content.Intent; import android.content.SharedPreferences; import android.graphics.Color; +import android.net.Uri; import android.os.Bundle; import android.preference.PreferenceManager; import android.support.annotation.NonNull; @@ -13,6 +14,7 @@ import android.text.Editable; import android.text.Html; import android.text.TextWatcher; import android.text.method.LinkMovementMethod; +import android.util.Log; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuInflater; @@ -29,6 +31,7 @@ import android.widget.TextView; import android.widget.Toast; import java.util.ArrayList; +import java.util.Locale; import javax.inject.Inject; import javax.inject.Named; @@ -342,4 +345,17 @@ public class SingleUploadFragment extends CommonsDaggerSupportFragment { .create() .show(); } + + /** + * To launch the Commons:Licensing + * @param view + */ + @OnClick(R.id.licenseInfo) + public void launchLicenseInfo(View view){ + Log.i("Language", Locale.getDefault().getLanguage()); + UrlLicense urlLicense = new UrlLicense(); + urlLicense.initialize(); + String url = urlLicense.getLicenseUrl(Locale.getDefault().getLanguage()); + Utils.handleWebUrl(getActivity() , Uri.parse(url)); + } } diff --git a/app/src/main/java/fr/free/nrw/commons/upload/UrlLicense.java b/app/src/main/java/fr/free/nrw/commons/upload/UrlLicense.java new file mode 100644 index 000000000..875dde26a --- /dev/null +++ b/app/src/main/java/fr/free/nrw/commons/upload/UrlLicense.java @@ -0,0 +1,72 @@ +package fr.free.nrw.commons.upload; + +import java.util.HashMap; +import java.util.Locale; + +/** + * This is a Util class which provides the necessary token to open the Commons License + * info in the user language + */ +public class UrlLicense { + HashMap urlLicense = new HashMap(); + public void initialize(){ + urlLicense.put("en","https://commons.wikimedia.org/wiki/Commons:Licensing"); + urlLicense.put("ar","https://commons.wikimedia.org/wiki/Commons:Licensing/ar"); + urlLicense.put("ast","https://commons.wikimedia.org/wiki/Commons:Licensing/ast"); + urlLicense.put("az","https://commons.wikimedia.org/wiki/Commons:Licensing/az"); + urlLicense.put("be","https://commons.wikimedia.org/wiki/Commons:Licensing/be"); + urlLicense.put("bg","https://commons.wikimedia.org/wiki/Commons:Licensing/bg"); + urlLicense.put("bn","https://commons.wikimedia.org/wiki/Commons:Licensing/bn"); + urlLicense.put("ca","https://commons.wikimedia.org/wiki/Commons:Licensing/ca"); + urlLicense.put("cs","https://commons.wikimedia.org/wiki/Commons:Licensing/cs"); + urlLicense.put("da","https://commons.wikimedia.org/wiki/Commons:Licensing/da"); + urlLicense.put("de","https://commons.wikimedia.org/wiki/Commons:Licensing/de"); + urlLicense.put("el","https://commons.wikimedia.org/wiki/Commons:Licensing/el"); + urlLicense.put("eo","https://commons.wikimedia.org/wiki/Commons:Licensing/eo"); + urlLicense.put("es","https://commons.wikimedia.org/wiki/Commons:Licensing/es"); + urlLicense.put("eu","https://commons.wikimedia.org/wiki/Commons:Licensing/eu"); + urlLicense.put("fa","https://commons.wikimedia.org/wiki/Commons:Licensing/fa"); + urlLicense.put("fi","https://commons.wikimedia.org/wiki/Commons:Licensing/fi"); + urlLicense.put("fr","https://commons.wikimedia.org/wiki/Commons:Licensing/fr"); + urlLicense.put("gl","https://commons.wikimedia.org/wiki/Commons:Licensing/gl"); + urlLicense.put("gsw","https://commons.wikimedia.org/wiki/Commons:Licensing/gsw"); + urlLicense.put("he","https://commons.wikimedia.org/wiki/Commons:Licensing/he"); + urlLicense.put("hi","https://commons.wikimedia.org/wiki/Commons:Licensing/hi"); + urlLicense.put("hu","https://commons.wikimedia.org/wiki/Commons:Licensing/hu"); + urlLicense.put("id","https://commons.wikimedia.org/wiki/Commons:Licensing/id"); + urlLicense.put("is","https://commons.wikimedia.org/wiki/Commons:Licensing/is"); + urlLicense.put("it","https://commons.wikimedia.org/wiki/Commons:Licensing/it"); + urlLicense.put("ja","https://commons.wikimedia.org/wiki/Commons:Licensing/ja"); + urlLicense.put("ka","https://commons.wikimedia.org/wiki/Commons:Licensing/ka"); + urlLicense.put("km","https://commons.wikimedia.org/wiki/Commons:Licensing/km"); + urlLicense.put("ko","https://commons.wikimedia.org/wiki/Commons:Licensing/ko"); + urlLicense.put("ku","https://commons.wikimedia.org/wiki/Commons:Licensing/ku"); + urlLicense.put("mk","https://commons.wikimedia.org/wiki/Commons:Licensing/mk"); + urlLicense.put("mr","https://commons.wikimedia.org/wiki/Commons:Licensing/mr"); + urlLicense.put("ms","https://commons.wikimedia.org/wiki/Commons:Licensing/ms"); + urlLicense.put("my","https://commons.wikimedia.org/wiki/Commons:Licensing/my"); + urlLicense.put("nl","https://commons.wikimedia.org/wiki/Commons:Licensing/nl"); + urlLicense.put("oc","https://commons.wikimedia.org/wiki/Commons:Licensing/oc"); + urlLicense.put("pl","https://commons.wikimedia.org/wiki/Commons:Licensing/pl"); + urlLicense.put("pt","https://commons.wikimedia.org/wiki/Commons:Licensing/pt"); + urlLicense.put("pt-br","https://commons.wikimedia.org/wiki/Commons:Licensing/pt-br"); + urlLicense.put("ro","https://commons.wikimedia.org/wiki/Commons:Licensing/ro"); + urlLicense.put("ru","https://commons.wikimedia.org/wiki/Commons:Licensing/ru"); + urlLicense.put("scn","https://commons.wikimedia.org/wiki/Commons:Licensing/scn"); + urlLicense.put("sk","https://commons.wikimedia.org/wiki/Commons:Licensing/sk"); + urlLicense.put("sl","https://commons.wikimedia.org/wiki/Commons:Licensing/sl"); + urlLicense.put("sv","https://commons.wikimedia.org/wiki/Commons:Licensing/sv"); + urlLicense.put("tr","https://commons.wikimedia.org/wiki/Commons:Licensing/tr"); + urlLicense.put("uk","https://commons.wikimedia.org/wiki/Commons:Licensing/uk"); + urlLicense.put("ur","https://commons.wikimedia.org/wiki/Commons:Licensing/ur"); + urlLicense.put("vi","https://commons.wikimedia.org/wiki/Commons:Licensing/vi"); + urlLicense.put("zh","https://commons.wikimedia.org/wiki/Commons:Licensing/zh"); + } + public String getLicenseUrl ( String language){ + if(urlLicense.containsKey(language)) { + return urlLicense.get(language); + } else { + return urlLicense.get("en"); + } + } +} diff --git a/app/src/main/res/layout/fragment_single_upload.xml b/app/src/main/res/layout/fragment_single_upload.xml index 37e43ee81..00cc1d194 100644 --- a/app/src/main/res/layout/fragment_single_upload.xml +++ b/app/src/main/res/layout/fragment_single_upload.xml @@ -55,11 +55,23 @@ - + android:layout_height="wrap_content"> + + +