diff --git a/.travis.yml b/.travis.yml index 898b0a8cf..fc6f81ad7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -33,8 +33,6 @@ after_success: after_failure: - echo '*** Connected Test Rsults ***' - w3m -dump ${TRAVIS_BUILD_DIR}/app/build/reports/androidTests/connected/*Test.html - - echo '*** Lint Results ***' - - cat ${TRAVIS_BUILD_DIR}/app/build/reports/lint-results.xml jdk: # - openjdk8 # not yet available - oraclejdk8 diff --git a/CHANGELOG.md b/CHANGELOG.md index 0b41ff0e2..1de06a4e3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,19 @@ # Wikimedia Commons for Android +## v2.5.0 beta +- Added one-time popup for beta users to provide feedback on IEG renewal proposal +- Added link to Commons policies in ShareActivity +- Various string fixes +- Switched to using vector icons for map markers +- Added filter for irrelevant categories +- Fixed various crashes +- Incremented target SDK to 25 +- Improved appearance of navigation drawer +- Replaced proprietary app image in tutorial with one that isn't Telegram +- Fixed camera issue with FileProvider +- Added RxJava library, migrated to Java 8 +- Various code and continuous integration optimizations + ## v2.4.2 beta - Added option to launch tutorial again from nav drawer - Added marker for current location in Nearby map diff --git a/CREDITS b/CREDITS index a0e1fcec4..7f2ab0893 100644 --- a/CREDITS +++ b/CREDITS @@ -24,6 +24,8 @@ their contribution to the product. * Dmitry Brant * Adam Shorland * John Lubbock +* Mikel Pascual +* Jan Piotrowski 3rd party open source libraries used: * Butterknife diff --git a/README.md b/README.md index 687b53ebb..6c2c9c0ee 100644 --- a/README.md +++ b/README.md @@ -4,11 +4,14 @@ The Wikimedia Commons Android app allows users to upload pictures from their And Initially started by the Wikimedia Foundation, this app is now maintained by volunteers. Anyone is welcome to improve it, just choose among the [open issues](https://github.com/commons-app/apps-android-commons/issues) and send us a pull request :-) +We are currently applying for an [IEG renewal][15] to work on the app for the next 6 months. Feedback is very much welcomed. + Get it on F-Droid Get it on Google Play + ## Develop with Android Studio or IntelliJ ## [Download Android Studio][1] (recommended) or [IntelliJ][2]. @@ -80,6 +83,32 @@ Captured files are not currently stored within the app, but are passed by conten Thumbnail images are not currently cached. +## Volunteers welcome! ## + +We are always looking for volunteers, feel free to step in! It is very easy: + +1. Fork the repository and clone it to your computer, then follow the build instructions above. +2. Choose an [unassigned issue](https://github.com/commons-app/apps-android-commons/issues?q=is%3Aopen+is%3Aissue+no%3Aassignee) that sounds interesting to you. +3. Read the issue's comments to make sure you understand what is the bug, or what feature is being proposed. +4. Write a "I start working on this" comment on the issue +5. Write the code :-) +6. Commit and push +7. Go to your fork's Github webpage, select the "Pull Requests" tab and click "create a pull request", as a comment, write something like "Fix for issue #12345 crash when rotating screen", then submit the pull request. +8. Within a few hours or days, a core developer will review your patch, and either merge it or suggest a few corrections. +9. If you change your mind, or if it is too difficult, no problem, just write "Sorry I don't work on this anymore" on the issue, if possible including feedback (for instance what approaches failed) and ideas. + +Thanks a lot! + +## Translating the app ## + +Thanks to the translation work of many volunteers this app is available in a multitude of languages. + +Translation of the text content of the Wikimedia Commons Android app happens on the [Commons Android App project][10] on [translatewiki.net][11]. If you want to help translate the app please create an account there (to get "translate rights" edit 20 [random keys][13] or ask in their [chat][14]). + +The translations from the translatewiki project are [periodically committed directly to this project][12] by the translatewiki team and later released with the normal updates to the Play Store. + + + [1]: https://developer.android.com/studio/index.html [2]: http://www.jetbrains.com/idea/download/index.html @@ -90,3 +119,9 @@ Thumbnail images are not currently cached. [7]: https://github.com/commons-app/apps-android-commons/issues [8]: https://play.google.com/store/apps/details?id=fr.free.nrw.commons [9]: https://commons-app.github.io/ +[10]: https://translatewiki.net/w/i.php?title=Special:Translate&group=commons-android +[11]: https://translatewiki.net +[12]: https://github.com/commons-app/apps-android-commons/commits/master?author=translatewiki +[13]: https://translatewiki.net/wiki/Special:TranslationStash? +[14]: https://translatewiki.net/wiki/Special:WebChat +[15]: https://meta.wikimedia.org/wiki/Grants:Project/Improve_%27Upload_to_Commons%27_Android_App/Renewal diff --git a/app/build.gradle b/app/build.gradle index 197e6b4d9..3177b672c 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,4 +1,5 @@ apply plugin: 'com.android.application' +apply plugin: 'me.tatarka.retrolambda' apply plugin: 'jacoco-android' apply from: 'quality.gradle' apply plugin: 'com.getkeepsafe.dexcount' @@ -51,8 +52,8 @@ android { defaultConfig { applicationId 'fr.free.nrw.commons' - versionCode 73 - versionName '2.4.2' + versionCode 74 + versionName '2.5.0' minSdkVersion project.minSdkVersion targetSdkVersion project.targetSdkVersion testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" @@ -75,6 +76,11 @@ android { abortOnError false } + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + //FIXME: Temporary fix for https://github.com/commons-app/apps-android-commons/issues/709 configurations.all { resolutionStrategy.force 'com.android.support:support-annotations:25.2.0' diff --git a/app/src/androidTest/java/fr/free/nrw/commons/NearbyControllerTest.java b/app/src/androidTest/java/fr/free/nrw/commons/NearbyControllerTest.java index ab528c2ab..aa32d2637 100644 --- a/app/src/androidTest/java/fr/free/nrw/commons/NearbyControllerTest.java +++ b/app/src/androidTest/java/fr/free/nrw/commons/NearbyControllerTest.java @@ -25,7 +25,7 @@ public class NearbyControllerTest { @Before public void setup() { - instrumentationContext = InstrumentationRegistry.getContext(); + instrumentationContext = InstrumentationRegistry.getTargetContext(); } @Test public void testNullAttractions() { diff --git a/app/src/androidTest/java/fr/free/nrw/commons/SettingsActivityTest.java b/app/src/androidTest/java/fr/free/nrw/commons/SettingsActivityTest.java index 533498a47..5be309252 100644 --- a/app/src/androidTest/java/fr/free/nrw/commons/SettingsActivityTest.java +++ b/app/src/androidTest/java/fr/free/nrw/commons/SettingsActivityTest.java @@ -9,9 +9,8 @@ import android.support.test.espresso.matcher.ViewMatchers; import android.support.test.filters.LargeTest; import android.support.test.rule.ActivityTestRule; import android.support.test.runner.AndroidJUnit4; -import android.view.View; -import org.hamcrest.Matcher; +import org.hamcrest.Matchers; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; @@ -20,9 +19,6 @@ import java.util.Map; import fr.free.nrw.commons.settings.SettingsActivity; -import static org.hamcrest.Matchers.allOf; -import static org.hamcrest.Matchers.anything; - @LargeTest @RunWith(AndroidJUnit4.class) public class SettingsActivityTest { @@ -65,8 +61,8 @@ public class SettingsActivityTest { @Test public void oneLicenseIsChecked() { // click "License" (the first item) - Espresso.onData(anything()) - .inAdapterView(findPreferenceList()) + Espresso.onData(Matchers.anything()) + .inAdapterView(ViewMatchers.withId(android.R.id.list)) .atPosition(0) .perform(ViewActions.click()); @@ -78,8 +74,8 @@ public class SettingsActivityTest { @Test public void afterClickingCcby4ItWillStay() { // click "License" (the first item) - Espresso.onData(anything()) - .inAdapterView(findPreferenceList()) + Espresso.onData(Matchers.anything()) + .inAdapterView(ViewMatchers.withId(android.R.id.list)) .atPosition(0) .perform(ViewActions.click()); @@ -89,8 +85,8 @@ public class SettingsActivityTest { ).perform(ViewActions.click()); // click "License" (the first item) - Espresso.onData(anything()) - .inAdapterView(findPreferenceList()) + Espresso.onData(Matchers.anything()) + .inAdapterView(ViewMatchers.withId(android.R.id.list)) .atPosition(0) .perform(ViewActions.click()); @@ -100,12 +96,4 @@ public class SettingsActivityTest { ViewMatchers.withText(R.string.license_name_cc_by_four) )); } - - private static Matcher findPreferenceList() { - return allOf( - ViewMatchers.isDescendantOfA(ViewMatchers.withId(R.id.settingsFragment)), - ViewMatchers.withResourceName("list"), - ViewMatchers.hasFocus() - ); - } -} +} \ No newline at end of file diff --git a/app/src/main/java/fr/free/nrw/commons/AboutActivity.java b/app/src/main/java/fr/free/nrw/commons/AboutActivity.java index 1f11be2dc..96c1cf200 100644 --- a/app/src/main/java/fr/free/nrw/commons/AboutActivity.java +++ b/app/src/main/java/fr/free/nrw/commons/AboutActivity.java @@ -8,9 +8,11 @@ import android.widget.TextView; import butterknife.BindView; import butterknife.ButterKnife; import fr.free.nrw.commons.theme.NavigationBaseActivity; +import fr.free.nrw.commons.ui.widget.HtmlTextView; public class AboutActivity extends NavigationBaseActivity { @BindView(R.id.about_version) TextView versionText; + @BindView(R.id.about_license) HtmlTextView aboutLicenseText; @Override public void onCreate(Bundle savedInstanceState) { @@ -19,6 +21,9 @@ public class AboutActivity extends NavigationBaseActivity { ButterKnife.bind(this); + String aboutText = getString(R.string.about_license, getString(R.string.trademarked_name)); + aboutLicenseText.setHtmlText(aboutText); + versionText.setText(BuildConfig.VERSION_NAME); initDrawer(); } diff --git a/app/src/main/java/fr/free/nrw/commons/CommonsApplication.java b/app/src/main/java/fr/free/nrw/commons/CommonsApplication.java index b78bfdc6f..94d6e3fb4 100644 --- a/app/src/main/java/fr/free/nrw/commons/CommonsApplication.java +++ b/app/src/main/java/fr/free/nrw/commons/CommonsApplication.java @@ -11,6 +11,7 @@ import android.content.pm.PackageManager; import android.database.sqlite.SQLiteDatabase; import android.preference.PreferenceManager; import android.support.v4.util.LruCache; +import android.util.Log; import com.facebook.drawee.backends.pipeline.Fresco; import com.facebook.stetho.Stetho; @@ -139,6 +140,10 @@ public class CommonsApplication extends Application { System.setProperty("in.yuvi.http.fluent.PROGRESS_TRIGGER_THRESHOLD", "3.0"); Fresco.initialize(this); + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences( + CommonsApplication.getInstance()); + // Increase counter by one, starts from 1 + prefs.edit().putInt("app_start_counter", prefs.getInt("app_start_counter" ,0) + 1).commit(); //For caching area -> categories cacheData = new CacheController(); @@ -197,8 +202,8 @@ public class CommonsApplication extends Application { AccountManager accountManager = AccountManager.get(this); Account[] allAccounts = accountManager.getAccountsByType(AccountUtil.accountType()); - for (int index = 0; index < allAccounts.length; index++) { - accountManager.removeAccount(allAccounts[index], null, null); + for (Account allAccount : allAccounts) { + accountManager.removeAccount(allAccount, null, null); } //TODO: fix preference manager diff --git a/app/src/main/java/fr/free/nrw/commons/Media.java b/app/src/main/java/fr/free/nrw/commons/Media.java index a1ae1cc84..1d07e9c16 100644 --- a/app/src/main/java/fr/free/nrw/commons/Media.java +++ b/app/src/main/java/fr/free/nrw/commons/Media.java @@ -142,7 +142,7 @@ public class Media implements Parcelable { return coordinates; } - public void setCoordinates(LatLng coordinates) { + public void setCoordinates(@Nullable LatLng coordinates) { this.coordinates = coordinates; } @@ -201,7 +201,7 @@ public class Media implements Parcelable { this.filename = filename; } - public Media(Uri localUri, String imageUrl, String filename, String description, long dataLength, Date dateCreated, Date dateUploaded, String creator) { + 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; diff --git a/app/src/main/java/fr/free/nrw/commons/WelcomeActivity.java b/app/src/main/java/fr/free/nrw/commons/WelcomeActivity.java index e35c7e6d0..f6c5999e9 100644 --- a/app/src/main/java/fr/free/nrw/commons/WelcomeActivity.java +++ b/app/src/main/java/fr/free/nrw/commons/WelcomeActivity.java @@ -27,12 +27,7 @@ public class WelcomeActivity extends BaseActivity { pager.setAdapter(adapter); indicator.setViewPager(pager); - adapter.setCallback(new WelcomePagerAdapter.Callback() { - @Override - public void onYesClicked() { - finish(); - } - }); + adapter.setCallback(this::finish); } @Override 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 37a4b0e05..aca419b9c 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 @@ -26,6 +26,9 @@ import fr.free.nrw.commons.PageTitle; import fr.free.nrw.commons.contributions.ContributionsActivity; import timber.log.Timber; +import static android.view.KeyEvent.KEYCODE_ENTER; +import static android.view.inputmethod.EditorInfo.IME_ACTION_DONE; + public class LoginActivity extends AccountAuthenticatorActivity { @@ -61,20 +64,10 @@ public class LoginActivity extends AccountAuthenticatorActivity { usernameEdit.addTextChangedListener(textWatcher); passwordEdit.addTextChangedListener(textWatcher); twoFactorEdit.addTextChangedListener(textWatcher); - passwordEdit.setOnEditorActionListener( newLoginInputActionListener() ); + passwordEdit.setOnEditorActionListener(newLoginInputActionListener()); - loginButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - performLogin(); - } - }); - signupButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - signUp(v); - } - }); + loginButton.setOnClickListener(this::performLogin); + signupButton.setOnClickListener(this::signUp); } private class LoginTextWatcher implements TextWatcher { @@ -98,20 +91,17 @@ public class LoginActivity extends AccountAuthenticatorActivity { } private TextView.OnEditorActionListener newLoginInputActionListener() { - return new TextView.OnEditorActionListener() { - @Override - public boolean onEditorAction(TextView textView, int actionId, KeyEvent keyEvent) { - if (loginButton.isEnabled()) { - if (actionId == EditorInfo.IME_ACTION_DONE) { - performLogin(); - return true; - } else if ((keyEvent != null) && keyEvent.getKeyCode() == KeyEvent.KEYCODE_ENTER) { - performLogin(); - return true; - } + return (textView, actionId, keyEvent) -> { + if (loginButton.isEnabled()) { + if (actionId == IME_ACTION_DONE) { + performLogin(textView); + return true; + } else if ((keyEvent != null) && keyEvent.getKeyCode() == KEYCODE_ENTER) { + performLogin(textView); + return true; } - return false; } + return false; }; } @@ -142,7 +132,7 @@ public class LoginActivity extends AccountAuthenticatorActivity { super.onDestroy(); } - private void performLogin() { + private void performLogin(View view) { Timber.d("Login to start!"); LoginTask task = getLoginTask(); task.execute(); @@ -151,7 +141,7 @@ public class LoginActivity extends AccountAuthenticatorActivity { private LoginTask getLoginTask() { return new LoginTask( this, - canonicializeUsername( usernameEdit.getText().toString() ), + canonicializeUsername(usernameEdit.getText().toString()), passwordEdit.getText().toString(), twoFactorEdit.getText().toString() ); @@ -162,16 +152,16 @@ public class LoginActivity extends AccountAuthenticatorActivity { * @param username String * @return String canonicial username */ - private String canonicializeUsername( String username ) { + private String canonicializeUsername(String username) { return new PageTitle(username).getText(); } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { - case android.R.id.home: - NavUtils.navigateUpFromSameTask(this); - return true; + case android.R.id.home: + NavUtils.navigateUpFromSameTask(this); + return true; } return super.onOptionsItemSelected(item); } @@ -186,20 +176,20 @@ public class LoginActivity extends AccountAuthenticatorActivity { } public void askUserForTwoFactorAuth() { - if(BuildConfig.DEBUG) { + if (BuildConfig.DEBUG) { twoFactorEdit.setVisibility(View.VISIBLE); - showUserToastAndCancelDialog( R.string.login_failed_2fa_needed ); - }else{ - showUserToastAndCancelDialog( R.string.login_failed_2fa_not_supported ); + showUserToastAndCancelDialog(R.string.login_failed_2fa_needed); + } else { + showUserToastAndCancelDialog(R.string.login_failed_2fa_not_supported); } } - public void showUserToastAndCancelDialog( int resId ) { - showUserToast( resId ); + public void showUserToastAndCancelDialog(int resId) { + showUserToast(resId); progressDialog.cancel(); } - private void showUserToast( int resId ) { + private void showUserToast(int resId) { Toast.makeText(this, resId, Toast.LENGTH_LONG).show(); } diff --git a/app/src/main/java/fr/free/nrw/commons/auth/LoginTask.java b/app/src/main/java/fr/free/nrw/commons/auth/LoginTask.java index b7e1ab252..dd4f1c4e7 100644 --- a/app/src/main/java/fr/free/nrw/commons/auth/LoginTask.java +++ b/app/src/main/java/fr/free/nrw/commons/auth/LoginTask.java @@ -67,7 +67,7 @@ class LoginTask extends AsyncTask { if (result.equals("PASS")) { handlePassResult(); } else { - handleOtherResults( result ); + handleOtherResults(result); } } @@ -88,38 +88,38 @@ class LoginTask extends AsyncTask { } } - AccountUtil.createAccount( response, username, password ); + AccountUtil.createAccount(response, username, password); loginActivity.startMainActivity(); } /** - * Match known failure message codes and provide messages + * Match known failure message codes and provide messages. * @param result String */ - private void handleOtherResults( String result ) { + private void handleOtherResults(String result) { if (result.equals("NetworkFailure")) { // Matches NetworkFailure which is created by the doInBackground method - loginActivity.showUserToastAndCancelDialog( R.string.login_failed_network ); + loginActivity.showUserToastAndCancelDialog(R.string.login_failed_network); } else if (result.toLowerCase().contains("nosuchuser".toLowerCase()) || result.toLowerCase().contains("noname".toLowerCase())) { // Matches nosuchuser, nosuchusershort, noname - loginActivity.showUserToastAndCancelDialog( R.string.login_failed_username ); + loginActivity.showUserToastAndCancelDialog(R.string.login_failed_username); loginActivity.emptySensitiveEditFields(); } else if (result.toLowerCase().contains("wrongpassword".toLowerCase())) { // Matches wrongpassword, wrongpasswordempty - loginActivity.showUserToastAndCancelDialog( R.string.login_failed_password ); + loginActivity.showUserToastAndCancelDialog(R.string.login_failed_password); loginActivity.emptySensitiveEditFields(); } else if (result.toLowerCase().contains("throttle".toLowerCase())) { // Matches unknown throttle error codes - loginActivity.showUserToastAndCancelDialog( R.string.login_failed_throttled ); + loginActivity.showUserToastAndCancelDialog(R.string.login_failed_throttled); } else if (result.toLowerCase().contains("userblocked".toLowerCase())) { // Matches login-userblocked - loginActivity.showUserToastAndCancelDialog( R.string.login_failed_blocked ); + loginActivity.showUserToastAndCancelDialog(R.string.login_failed_blocked); } else if (result.equals("2FA")) { loginActivity.askUserForTwoFactorAuth(); } else { // Occurs with unhandled login failure codes Timber.d("Login failed with reason: %s", result); - loginActivity.showUserToastAndCancelDialog( R.string.login_failed_generic ); + loginActivity.showUserToastAndCancelDialog(R.string.login_failed_generic); } } } diff --git a/app/src/main/java/fr/free/nrw/commons/auth/WikiAccountAuthenticatorService.java b/app/src/main/java/fr/free/nrw/commons/auth/WikiAccountAuthenticatorService.java index c5201f95a..0a996b7d4 100644 --- a/app/src/main/java/fr/free/nrw/commons/auth/WikiAccountAuthenticatorService.java +++ b/app/src/main/java/fr/free/nrw/commons/auth/WikiAccountAuthenticatorService.java @@ -5,17 +5,17 @@ import android.app.Service; import android.content.Intent; import android.os.IBinder; -public class WikiAccountAuthenticatorService extends Service{ +public class WikiAccountAuthenticatorService extends Service { private static WikiAccountAuthenticator wikiAccountAuthenticator = null; @Override public IBinder onBind(Intent intent) { if (!intent.getAction().equals(AccountManager.ACTION_AUTHENTICATOR_INTENT)) { - return null; + return null; } - if(wikiAccountAuthenticator == null) { + if (wikiAccountAuthenticator == null) { wikiAccountAuthenticator = new WikiAccountAuthenticator(this); } return wikiAccountAuthenticator.getIBinder(); diff --git a/app/src/main/java/fr/free/nrw/commons/caching/CacheController.java b/app/src/main/java/fr/free/nrw/commons/caching/CacheController.java index 49fec4c2e..85f545567 100644 --- a/app/src/main/java/fr/free/nrw/commons/caching/CacheController.java +++ b/app/src/main/java/fr/free/nrw/commons/caching/CacheController.java @@ -74,14 +74,14 @@ public class CacheController { double offset = 100; //Coordinate offsets in radians - double dLat = offset/EARTH_RADIUS; - double dLon = offset/(EARTH_RADIUS*Math.cos(Math.PI*lat/180)); + double dLat = offset / EARTH_RADIUS; + double dLon = offset / (EARTH_RADIUS * Math.cos(Math.PI * lat / 180)); //OffsetPosition, decimal degrees - yPlus = lat + dLat * 180/Math.PI; - yMinus = lat - dLat * 180/Math.PI; - xPlus = lon + dLon * 180/Math.PI; - xMinus = lon - dLon * 180/Math.PI; + yPlus = lat + dLat * 180 / Math.PI; + yMinus = lat - dLat * 180 / Math.PI; + xPlus = lon + dLon * 180 / Math.PI; + xMinus = lon - dLon * 180 / Math.PI; Timber.d("Search within: xMinus=%s, yMinus=%s, xPlus=%s, yPlus=%s", xMinus, yMinus, xPlus, yPlus); } diff --git a/app/src/main/java/fr/free/nrw/commons/category/CategoriesAdapter.java b/app/src/main/java/fr/free/nrw/commons/category/CategoriesAdapter.java deleted file mode 100644 index 2c0055c73..000000000 --- a/app/src/main/java/fr/free/nrw/commons/category/CategoriesAdapter.java +++ /dev/null @@ -1,67 +0,0 @@ -package fr.free.nrw.commons.category; - - -import android.content.Context; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.BaseAdapter; -import android.widget.CheckedTextView; - -import java.util.ArrayList; - -import fr.free.nrw.commons.R; - -public class CategoriesAdapter extends BaseAdapter { - - private LayoutInflater mInflater; - - private ArrayList items; - - public CategoriesAdapter(Context context, ArrayList items) { - this.items = items; - mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); - } - - @Override - public int getCount() { - return items.size(); - } - - @Override - public Object getItem(int i) { - return items.get(i); - } - - public ArrayList getItems() { - return items; - } - - public void setItems(ArrayList items) { - this.items = items; - } - - @Override - public long getItemId(int i) { - return i; - } - - @Override - public View getView(int i, View view, ViewGroup viewGroup) { - CheckedTextView checkedView; - - if(view == null) { - checkedView = (CheckedTextView) mInflater.inflate(R.layout.layout_categories_item, null); - - } else { - checkedView = (CheckedTextView) view; - } - - CategorizationFragment.CategoryItem item = (CategorizationFragment.CategoryItem) this.getItem(i); - checkedView.setChecked(item.selected); - checkedView.setText(item.name); - checkedView.setTag(i); - - return checkedView; - } -} \ No newline at end of file diff --git a/app/src/main/java/fr/free/nrw/commons/category/CategoriesAdapterFactory.java b/app/src/main/java/fr/free/nrw/commons/category/CategoriesAdapterFactory.java new file mode 100644 index 000000000..417121c44 --- /dev/null +++ b/app/src/main/java/fr/free/nrw/commons/category/CategoriesAdapterFactory.java @@ -0,0 +1,24 @@ +package fr.free.nrw.commons.category; + +import com.pedrogomez.renderers.ListAdapteeCollection; +import com.pedrogomez.renderers.RVRendererAdapter; +import com.pedrogomez.renderers.RendererBuilder; + +import java.util.Collections; +import java.util.List; + +class CategoriesAdapterFactory { + private final CategoriesRenderer.CategoryClickedListener listener; + + CategoriesAdapterFactory(CategoriesRenderer.CategoryClickedListener listener) { + this.listener = listener; + } + + public RVRendererAdapter create(List placeList) { + RendererBuilder builder = new RendererBuilder() + .bind(CategoryItem.class, new CategoriesRenderer(listener)); + ListAdapteeCollection collection = new ListAdapteeCollection<>( + placeList != null ? placeList : Collections.emptyList()); + return new RVRendererAdapter<>(builder, collection); + } +} diff --git a/app/src/main/java/fr/free/nrw/commons/category/CategoriesRenderer.java b/app/src/main/java/fr/free/nrw/commons/category/CategoriesRenderer.java new file mode 100644 index 000000000..a138736cc --- /dev/null +++ b/app/src/main/java/fr/free/nrw/commons/category/CategoriesRenderer.java @@ -0,0 +1,57 @@ +package fr.free.nrw.commons.category; + +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.CheckedTextView; + +import com.pedrogomez.renderers.Renderer; + +import butterknife.BindView; +import butterknife.ButterKnife; +import fr.free.nrw.commons.R; + +class CategoriesRenderer extends Renderer { + @BindView(R.id.tvName) CheckedTextView checkedView; + private final CategoryClickedListener listener; + + CategoriesRenderer(CategoryClickedListener listener) { + this.listener = listener; + } + + @Override + protected View inflate(LayoutInflater layoutInflater, ViewGroup viewGroup) { + return layoutInflater.inflate(R.layout.layout_categories_item, viewGroup, false); + } + + @Override + protected void setUpView(View view) { + ButterKnife.bind(this, view); + } + + @Override + protected void hookListeners(View view) { + view.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + CategoryItem item = getContent(); + item.setSelected(!item.isSelected()); + checkedView.setChecked(item.isSelected()); + if (listener != null) { + listener.categoryClicked(item); + } + } + }); + } + + @Override + public void render() { + CategoryItem item = getContent(); + checkedView.setChecked(item.isSelected()); + checkedView.setText(item.getName()); + } + + interface CategoryClickedListener { + void categoryClicked(CategoryItem item); + } +} diff --git a/app/src/main/java/fr/free/nrw/commons/category/CategorizationFragment.java b/app/src/main/java/fr/free/nrw/commons/category/CategorizationFragment.java index 3f467183d..bda7eecc9 100644 --- a/app/src/main/java/fr/free/nrw/commons/category/CategorizationFragment.java +++ b/app/src/main/java/fr/free/nrw/commons/category/CategorizationFragment.java @@ -1,36 +1,33 @@ package fr.free.nrw.commons.category; import android.content.ContentProviderClient; -import android.content.DialogInterface; import android.content.SharedPreferences; import android.database.Cursor; import android.os.AsyncTask; import android.os.Bundle; -import android.os.Parcel; -import android.os.Parcelable; import android.os.RemoteException; import android.preference.PreferenceManager; import android.support.v4.app.Fragment; import android.support.v7.app.AlertDialog; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; import android.text.Editable; import android.text.TextUtils; import android.text.TextWatcher; -import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; -import android.widget.AdapterView; -import android.widget.CheckedTextView; import android.widget.EditText; -import android.widget.ListView; import android.widget.ProgressBar; import android.widget.TextView; +import com.pedrogomez.renderers.ListAdapteeCollection; +import com.pedrogomez.renderers.RVRendererAdapter; + import java.util.ArrayList; -import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashSet; @@ -40,90 +37,191 @@ import java.util.concurrent.CountDownLatch; import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.TimeUnit; +import butterknife.BindView; +import butterknife.ButterKnife; import fr.free.nrw.commons.R; +import fr.free.nrw.commons.category.CategoriesRenderer.CategoryClickedListener; import fr.free.nrw.commons.upload.MwVolleyApi; import timber.log.Timber; +import static android.view.KeyEvent.ACTION_UP; +import static android.view.KeyEvent.KEYCODE_BACK; +import static fr.free.nrw.commons.category.CategoryContentProvider.AUTHORITY; + /** * Displays the category suggestion and selection screen. Category search is initiated here. */ -public class CategorizationFragment extends Fragment { - public interface OnCategoriesSaveHandler { - void onCategoriesSave(ArrayList categories); - } +public class CategorizationFragment extends Fragment implements CategoryClickedListener { + public static final int SEARCH_CATS_LIMIT = 25; - ListView categoriesList; - protected EditText categoriesFilter; + @BindView(R.id.categoriesListBox) + RecyclerView categoriesList; + @BindView(R.id.categoriesSearchBox) + EditText categoriesFilter; + @BindView(R.id.categoriesSearchInProgress) ProgressBar categoriesSearchInProgress; + @BindView(R.id.categoriesNotFound) TextView categoriesNotFoundView; + @BindView(R.id.categoriesExplanation) TextView categoriesSkip; - private CategoryTextWatcher textWatcher = new CategoryTextWatcher(); - - CategoriesAdapter categoriesAdapter; - ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(2); + private RVRendererAdapter categoriesAdapter; private OnCategoriesSaveHandler onCategoriesSaveHandler; - - protected HashMap> categoriesCache; - + private HashMap> categoriesCache; private ArrayList selectedCategories = new ArrayList<>(); - + private ContentProviderClient client; + private PrefixUpdater prefixUpdaterSub; + private MethodAUpdater methodAUpdaterSub; + private final CategoryTextWatcher textWatcher = new CategoryTextWatcher(); + private final CategoriesAdapterFactory adapterFactory = new CategoriesAdapterFactory(this); + private final ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(2); + private final ArrayList titleCatItems = new ArrayList<>(); + private final CountDownLatch mergeLatch = new CountDownLatch(1); // LHS guarantees ordered insertions, allowing for prioritized method A results private final Set results = new LinkedHashSet<>(); - PrefixUpdater prefixUpdaterSub; - MethodAUpdater methodAUpdaterSub; - private final ArrayList titleCatItems = new ArrayList<>(); - final CountDownLatch mergeLatch = new CountDownLatch(1); + @SuppressWarnings("unchecked") + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View rootView = inflater.inflate(R.layout.fragment_categorization, container, false); + ButterKnife.bind(this, rootView); - private ContentProviderClient client; + categoriesList.setLayoutManager(new LinearLayoutManager(getContext())); - protected final static int SEARCH_CATS_LIMIT = 25; + categoriesSkip.setOnClickListener(view -> { + getActivity().onBackPressed(); + getActivity().finish(); + }); - public static class CategoryItem implements Parcelable { - public String name; - public boolean selected; - - public static Creator CREATOR = new Creator() { - @Override - public CategoryItem createFromParcel(Parcel parcel) { - return new CategoryItem(parcel); - } - - @Override - public CategoryItem[] newArray(int i) { - return new CategoryItem[0]; - } - }; - - public CategoryItem(String name, boolean selected) { - this.name = name; - this.selected = selected; + ArrayList items; + if (savedInstanceState == null) { + items = new ArrayList<>(); + categoriesCache = new HashMap<>(); + } else { + items = savedInstanceState.getParcelableArrayList("currentCategories"); + categoriesCache = (HashMap>) savedInstanceState + .getSerializable("categoriesCache"); } - public CategoryItem(Parcel in) { - name = in.readString(); - selected = in.readInt() == 1; - } + categoriesAdapter = adapterFactory.create(items); + categoriesList.setAdapter(categoriesAdapter); + categoriesFilter.addTextChangedListener(textWatcher); - @Override - public int describeContents() { - return 0; - } + startUpdatingCategoryList(); - @Override - public void writeToParcel(Parcel parcel, int flags) { - parcel.writeString(name); - parcel.writeInt(selected ? 1 : 0); + return rootView; + } + + @Override + public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { + menu.clear(); + inflater.inflate(R.menu.fragment_categorization, menu); + } + + @Override + public void onResume() { + super.onResume(); + + View rootView = getView(); + if (rootView != null) { + rootView.setFocusableInTouchMode(true); + rootView.requestFocus(); + rootView.setOnKeyListener((v, keyCode, event) -> { + if (event.getAction() == ACTION_UP && keyCode == KEYCODE_BACK) { + backButtonDialog(); + return true; + } + return false; + }); } } + @Override + public void onDestroyView() { + categoriesFilter.removeTextChangedListener(textWatcher); + super.onDestroyView(); + } + + @Override + public void onDestroy() { + super.onDestroy(); + client.release(); + } + + @Override + public void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + int itemCount = categoriesAdapter.getItemCount(); + ArrayList items = new ArrayList<>(itemCount); + for (int i = 0; i < itemCount; i++) { + items.add(categoriesAdapter.getItem(i)); + } + outState.putParcelableArrayList("currentCategories", items); + outState.putSerializable("categoriesCache", categoriesCache); + } + + @Override + public boolean onOptionsItemSelected(MenuItem menuItem) { + switch (menuItem.getItemId()) { + case R.id.menu_save_categories: + + int numberSelected = 0; + + selectedCategories = new ArrayList<>(); + int count = categoriesAdapter.getItemCount(); + for (int i = 0; i < count; i++) { + CategoryItem item = categoriesAdapter.getItem(i); + if (item.isSelected()) { + selectedCategories.add(item.getName()); + numberSelected++; + } + } + + //If no categories selected, display warning to user + if (numberSelected == 0) { + new AlertDialog.Builder(getActivity()) + .setMessage("Images without categories are rarely usable. " + + "Are you sure you want to submit without selecting " + + "categories?") + .setTitle("No Categories Selected") + .setPositiveButton("No, go back", (dialog, id) -> { + //Exit menuItem so user can select their categories + }) + .setNegativeButton("Yes, submit", (dialog, id) -> { + //Proceed to submission + onCategoriesSaveHandler.onCategoriesSave(selectedCategories); + }) + .create() + .show(); + } else { + //Proceed to submission + onCategoriesSaveHandler.onCategoriesSave(selectedCategories); + return true; + } + } + return super.onOptionsItemSelected(menuItem); + } + + @Override + public void onActivityCreated(Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + setHasOptionsMenu(true); + onCategoriesSaveHandler = (OnCategoriesSaveHandler) getActivity(); + getActivity().setTitle(R.string.categories_activity_title); + client = getActivity().getContentResolver().acquireContentProviderClient(AUTHORITY); + } + + public HashMap> getCategoriesCache() { + return categoriesCache; + } + /** * Retrieves category suggestions from title input + * * @return a list containing title-related categories */ - protected ArrayList titleCatQuery() { - + private ArrayList titleCatQuery() { TitleCategories titleCategoriesSub; //Retrieve the title that was saved when user tapped submit icon @@ -157,37 +255,42 @@ public class CategorizationFragment extends Fragment { /** * Retrieves recently-used categories + * * @return a list containing recent categories */ - protected ArrayList recentCatQuery() { + private ArrayList recentCatQuery() { ArrayList items = new ArrayList<>(); - + Cursor cursor = null; try { - Cursor cursor = client.query( + cursor = client.query( CategoryContentProvider.BASE_URI, Category.Table.ALL_FIELDS, null, new String[]{}, Category.Table.COLUMN_LAST_USED + " DESC"); // fixme add a limit on the original query instead of falling out of the loop? - while (cursor.moveToNext() && cursor.getPosition() < SEARCH_CATS_LIMIT) { + while (cursor != null && cursor.moveToNext() + && cursor.getPosition() < SEARCH_CATS_LIMIT) { Category cat = Category.fromCursor(cursor); items.add(cat.getName()); } - cursor.close(); - } - catch (RemoteException e) { + } catch (RemoteException e) { throw new RuntimeException(e); + } finally { + if (cursor != null) { + cursor.close(); + } } return items; } /** - * Merges nearby categories, categories suggested based on title, and recent categories... without duplicates. + * Merges nearby categories, categories suggested based on title, and recent categories... + * without duplicates. + * * @return a list containing merged categories */ - protected ArrayList mergeItems() { - + ArrayList mergeItems() { Set mergedItems = new LinkedHashSet<>(); Timber.d("Calling APIs for GPS cats, title cats and recent cats..."); @@ -213,8 +316,9 @@ public class CategorizationFragment extends Fragment { Timber.d("Adding title items: %s", titleItems); mergedItems.addAll(recentItems); Timber.d("Adding recent items: %s", recentItems); - - //Needs to be an ArrayList and not a List unless we want to modify a big portion of preexisting code + + // Needs to be an ArrayList and not a List unless we want to modify a big portion + // of preexisting code ArrayList mergedItemsList = new ArrayList<>(mergedItems); Timber.d("Merged item list: %s", mergedItemsList); @@ -223,18 +327,20 @@ public class CategorizationFragment extends Fragment { /** * Displays categories found to the user as they type in the search box + * * @param categories a list of all categories found for the search string - * @param filter the search string + * @param filter the search string */ - protected void setCatsAfterAsync(ArrayList categories, String filter) { - + private void setCatsAfterAsync(ArrayList categories, String filter) { if (getActivity() != null) { ArrayList items = new ArrayList<>(); HashSet existingKeys = new HashSet<>(); - for (CategoryItem item : categoriesAdapter.getItems()) { - if (item.selected) { + int count = categoriesAdapter.getItemCount(); + for (int i = 0; i < count; i++) { + CategoryItem item = categoriesAdapter.getItem(i); + if (item.isSelected()) { items.add(item); - existingKeys.add(item.name); + existingKeys.add(item.getName()); } } for (String category : categories) { @@ -243,8 +349,8 @@ public class CategorizationFragment extends Fragment { } } - categoriesAdapter.setItems(items); - categoriesAdapter.notifyDataSetInvalidated(); + categoriesAdapter.setCollection(new ListAdapteeCollection<>(items)); + categoriesAdapter.notifyDataSetChanged(); categoriesSearchInProgress.setVisibility(View.GONE); if (categories.isEmpty()) { @@ -258,8 +364,7 @@ public class CategorizationFragment extends Fragment { } else { categoriesList.smoothScrollToPosition(existingKeys.size()); } - } - else { + } else { Timber.e("Error: Fragment is null"); } } @@ -272,7 +377,6 @@ public class CategorizationFragment extends Fragment { * above Prefix results. */ private void requestSearchResults() { - final CountDownLatch latch = new CountDownLatch(1); prefixUpdaterSub = new PrefixUpdater(this) { @@ -282,8 +386,7 @@ public class CategorizationFragment extends Fragment { try { result = super.doInBackground(); latch.await(); - } - catch (InterruptedException e) { + } catch (InterruptedException e) { Timber.w(e); //Thread.currentThread().interrupt(); } @@ -325,7 +428,6 @@ public class CategorizationFragment extends Fragment { } private void startUpdatingCategoryList() { - if (prefixUpdaterSub != null) { prefixUpdaterSub.cancel(true); } @@ -339,238 +441,34 @@ public class CategorizationFragment extends Fragment { public int getCurrentSelectedCount() { int count = 0; - for(CategoryItem item: categoriesAdapter.getItems()) { - if(item.selected) { + int numberOfItems = categoriesAdapter.getItemCount(); + for (int i = 0; i < numberOfItems; i++) { + CategoryItem item = categoriesAdapter.getItem(i); + if (item.isSelected()) { count++; } } return count; } - private Category lookupCategory(String name) { - Cursor cursor = null; - try { - cursor = client.query( - CategoryContentProvider.BASE_URI, - Category.Table.ALL_FIELDS, - Category.Table.COLUMN_NAME + "=?", - new String[] {name}, - null); - if (cursor.moveToFirst()) { - return Category.fromCursor(cursor); - } - } catch (RemoteException e) { - // This feels lazy, but to hell with checked exceptions. :) - throw new RuntimeException(e); - } finally { - if ( cursor != null ) { - cursor.close(); - } - } - - // Newly used category... - Category cat = new Category(); - cat.setName(name); - cat.setLastUsed(new Date()); - cat.setTimesUsed(0); - return cat; - } - - private class CategoryCountUpdater extends AsyncTask { - - private String name; - - public CategoryCountUpdater(String name) { - this.name = name; - } - - @Override - protected Void doInBackground(Void... voids) { - Category cat = lookupCategory(name); - cat.incTimesUsed(); - - cat.setContentProviderClient(client); - cat.save(); - - return null; // Make the compiler happy. - } - } - - private void updateCategoryCount(String name) { - new CategoryCountUpdater(name).executeOnExecutor(executor); - } - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - View rootView = inflater.inflate(R.layout.fragment_categorization, null); - categoriesList = (ListView) rootView.findViewById(R.id.categoriesListBox); - categoriesFilter = (EditText) rootView.findViewById(R.id.categoriesSearchBox); - categoriesSearchInProgress = (ProgressBar) rootView.findViewById(R.id.categoriesSearchInProgress); - categoriesNotFoundView = (TextView) rootView.findViewById(R.id.categoriesNotFound); - categoriesSkip = (TextView) rootView.findViewById(R.id.categoriesExplanation); - - categoriesSkip.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - getActivity().onBackPressed(); - getActivity().finish(); - } - }); - - ArrayList items; - if(savedInstanceState == null) { - items = new ArrayList<>(); - categoriesCache = new HashMap<>(); - } else { - items = savedInstanceState.getParcelableArrayList("currentCategories"); - categoriesCache = (HashMap>) savedInstanceState.getSerializable("categoriesCache"); - } - - categoriesAdapter = new CategoriesAdapter(getActivity(), items); - categoriesList.setAdapter(categoriesAdapter); - - categoriesList.setOnItemClickListener(new AdapterView.OnItemClickListener() { - @Override - public void onItemClick(AdapterView adapterView, View view, int index, long id) { - CheckedTextView checkedView = (CheckedTextView) view; - CategoryItem item = (CategoryItem) adapterView.getAdapter().getItem(index); - item.selected = !item.selected; - checkedView.setChecked(item.selected); - if (item.selected) { - updateCategoryCount(item.name); - } - } - }); - - categoriesFilter.addTextChangedListener(textWatcher); - - startUpdatingCategoryList(); - - return rootView; - } - - @Override - public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { - menu.clear(); - inflater.inflate(R.menu.fragment_categorization, menu); - } - - @Override - public void onResume() { - super.onResume(); - - View rootView = getView(); - if (rootView != null) { - rootView.setFocusableInTouchMode(true); - rootView.requestFocus(); - rootView.setOnKeyListener(new View.OnKeyListener() { - @Override - public boolean onKey(View v, int keyCode, KeyEvent event) { - if (event.getAction() == KeyEvent.ACTION_UP && keyCode == KeyEvent.KEYCODE_BACK) { - backButtonDialog(); - return true; - } - return false; - } - }); - } - } - - @Override - public void onDestroyView() { - categoriesFilter.removeTextChangedListener(textWatcher); - super.onDestroyView(); - } - public void backButtonDialog() { - AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); - - builder.setMessage("Are you sure you want to go back? The image will not have any categories saved.") - .setTitle("Warning"); - builder.setPositiveButton("No", new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int id) { - //No need to do anything, user remains on categorization screen - } - }); - builder.setNegativeButton("Yes", new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int id) { - getActivity().finish(); - } - }); - - AlertDialog dialog = builder.create(); - dialog.show(); + new AlertDialog.Builder(getActivity()) + .setMessage("Are you sure you want to go back? The image will not " + + "have any categories saved.") + .setTitle("Warning") + .setPositiveButton("No", (dialog, id) -> { + //No need to do anything, user remains on categorization screen + }) + .setNegativeButton("Yes", (dialog, id) -> getActivity().finish()) + .create() + .show(); } @Override - public void onDestroy() { - super.onDestroy(); - client.release(); - } - - @Override - public void onSaveInstanceState(Bundle outState) { - super.onSaveInstanceState(outState); - outState.putParcelableArrayList("currentCategories", categoriesAdapter.getItems()); - outState.putSerializable("categoriesCache", categoriesCache); - } - - @Override - public boolean onOptionsItemSelected(MenuItem menuItem) { - switch(menuItem.getItemId()) { - case R.id.menu_save_categories: - - int numberSelected = 0; - - for(CategoryItem item: categoriesAdapter.getItems()) { - if(item.selected) { - selectedCategories.add(item.name); - numberSelected++; - } - } - - //If no categories selected, display warning to user - if (numberSelected == 0) { - AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); - - builder.setMessage("Images without categories are rarely usable. Are you sure you want to submit without selecting categories?") - .setTitle("No Categories Selected"); - builder.setPositiveButton("No, go back", new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int id) { - //Exit menuItem so user can select their categories - return; - } - }); - builder.setNegativeButton("Yes, submit", new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int id) { - //Proceed to submission - onCategoriesSaveHandler.onCategoriesSave(selectedCategories); - return; - } - }); - - AlertDialog dialog = builder.create(); - dialog.show(); - } else { - //Proceed to submission - onCategoriesSaveHandler.onCategoriesSave(selectedCategories); - return true; - } + public void categoryClicked(CategoryItem item) { + if (item.isSelected()) { + new CategoryCountUpdater(item.getName(), client).executeOnExecutor(executor); } - return super.onOptionsItemSelected(menuItem); - } - - @Override - public void onActivityCreated(Bundle savedInstanceState) { - super.onActivityCreated(savedInstanceState); - setHasOptionsMenu(true); - onCategoriesSaveHandler = (OnCategoriesSaveHandler) getActivity(); - getActivity().setTitle(R.string.categories_activity_title); - client = getActivity().getContentResolver().acquireContentProviderClient(CategoryContentProvider.AUTHORITY); } private class CategoryTextWatcher implements TextWatcher { diff --git a/app/src/main/java/fr/free/nrw/commons/category/Category.java b/app/src/main/java/fr/free/nrw/commons/category/Category.java index f290dd741..68dd9200e 100644 --- a/app/src/main/java/fr/free/nrw/commons/category/Category.java +++ b/app/src/main/java/fr/free/nrw/commons/category/Category.java @@ -26,7 +26,7 @@ public class Category { this.name = name; } - public Date getLastUsed() { + private Date getLastUsed() { // warning: Date objects are mutable. return (Date)lastUsed.clone(); } @@ -36,11 +36,11 @@ public class Category { this.lastUsed = (Date)lastUsed.clone(); } - public void touch() { + private void touch() { lastUsed = new Date(); } - public int getTimesUsed() { + private int getTimesUsed() { return timesUsed; } @@ -60,17 +60,17 @@ public class Category { public void save() { try { - if(contentUri == null) { + if (contentUri == null) { contentUri = client.insert(CategoryContentProvider.BASE_URI, this.toContentValues()); } else { client.update(contentUri, toContentValues(), null, null); } - } catch(RemoteException e) { + } catch (RemoteException e) { throw new RuntimeException(e); } } - public ContentValues toContentValues() { + private ContentValues toContentValues() { ContentValues cv = new ContentValues(); cv.put(Table.COLUMN_NAME, getName()); cv.put(Table.COLUMN_LAST_USED, getLastUsed().getTime()); @@ -121,23 +121,23 @@ public class Category { } public static void onUpdate(SQLiteDatabase db, int from, int to) { - if(from == to) { + if (from == to) { return; } - if(from < 4) { + if (from < 4) { // doesn't exist yet from++; onUpdate(db, from, to); return; } - if(from == 4) { + if (from == 4) { // table added in version 5 onCreate(db); from++; onUpdate(db, from, to); return; } - if(from == 5) { + if (from == 5) { from++; onUpdate(db, from, to); return; diff --git a/app/src/main/java/fr/free/nrw/commons/category/CategoryContentProvider.java b/app/src/main/java/fr/free/nrw/commons/category/CategoryContentProvider.java index de157265b..c95e17cf6 100644 --- a/app/src/main/java/fr/free/nrw/commons/category/CategoryContentProvider.java +++ b/app/src/main/java/fr/free/nrw/commons/category/CategoryContentProvider.java @@ -7,6 +7,7 @@ import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteQueryBuilder; import android.net.Uri; +import android.support.annotation.NonNull; import android.text.TextUtils; import fr.free.nrw.commons.CommonsApplication; @@ -41,8 +42,10 @@ public class CategoryContentProvider extends ContentProvider { return false; } + @SuppressWarnings("ConstantConditions") @Override - public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { + public Cursor query(@NonNull Uri uri, String[] projection, String selection, + String[] selectionArgs, String sortOrder) { SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder(); queryBuilder.setTables(Category.Table.TABLE_NAME); @@ -53,7 +56,8 @@ public class CategoryContentProvider extends ContentProvider { switch(uriType) { case CATEGORIES: - cursor = queryBuilder.query(db, projection, selection, selectionArgs, null, null, sortOrder); + cursor = queryBuilder.query(db, projection, selection, selectionArgs, + null, null, sortOrder); break; case CATEGORIES_ID: cursor = queryBuilder.query(db, @@ -75,15 +79,16 @@ public class CategoryContentProvider extends ContentProvider { } @Override - public String getType(Uri uri) { + public String getType(@NonNull Uri uri) { return null; } + @SuppressWarnings("ConstantConditions") @Override - public Uri insert(Uri uri, ContentValues contentValues) { + public Uri insert(@NonNull Uri uri, ContentValues contentValues) { int uriType = uriMatcher.match(uri); SQLiteDatabase sqlDB = dbOpenHelper.getWritableDatabase(); - long id = 0; + long id; switch (uriType) { case CATEGORIES: id = sqlDB.insert(Category.Table.TABLE_NAME, null, contentValues); @@ -96,12 +101,13 @@ public class CategoryContentProvider extends ContentProvider { } @Override - public int delete(Uri uri, String s, String[] strings) { + public int delete(@NonNull Uri uri, String s, String[] strings) { return 0; } + @SuppressWarnings("ConstantConditions") @Override - public int bulkInsert(Uri uri, ContentValues[] values) { + public int bulkInsert(@NonNull Uri uri, @NonNull ContentValues[] values) { Timber.d("Hello, bulk insert! (CategoryContentProvider)"); int uriType = uriMatcher.match(uri); SQLiteDatabase sqlDB = dbOpenHelper.getWritableDatabase(); @@ -122,8 +128,10 @@ public class CategoryContentProvider extends ContentProvider { return values.length; } + @SuppressWarnings("ConstantConditions") @Override - public int update(Uri uri, ContentValues contentValues, String selection, String[] selectionArgs) { + public int update(@NonNull Uri uri, ContentValues contentValues, String selection, + String[] selectionArgs) { /* SQL Injection warnings: First, note that we're not exposing this to the outside world (exported="false") Even then, we should make sure to sanitize all user input appropriately. Input that passes through ContentValues @@ -133,7 +141,7 @@ public class CategoryContentProvider extends ContentProvider { */ int uriType = uriMatcher.match(uri); SQLiteDatabase sqlDB = dbOpenHelper.getWritableDatabase(); - int rowsUpdated = 0; + int rowsUpdated; switch (uriType) { case CATEGORIES_ID: int id = Integer.valueOf(uri.getLastPathSegment()); @@ -144,7 +152,8 @@ public class CategoryContentProvider extends ContentProvider { Category.Table.COLUMN_ID + " = ?", new String[] { String.valueOf(id) } ); } else { - throw new IllegalArgumentException("Parameter `selection` should be empty when updating an ID"); + throw new IllegalArgumentException( + "Parameter `selection` should be empty when updating an ID"); } break; default: diff --git a/app/src/main/java/fr/free/nrw/commons/category/CategoryCountUpdater.java b/app/src/main/java/fr/free/nrw/commons/category/CategoryCountUpdater.java new file mode 100644 index 000000000..bebbc03a8 --- /dev/null +++ b/app/src/main/java/fr/free/nrw/commons/category/CategoryCountUpdater.java @@ -0,0 +1,59 @@ +package fr.free.nrw.commons.category; + +import android.content.ContentProviderClient; +import android.database.Cursor; +import android.os.AsyncTask; +import android.os.RemoteException; + +import java.util.Date; + +class CategoryCountUpdater extends AsyncTask { + + private final String name; + private final ContentProviderClient client; + + CategoryCountUpdater(String name, ContentProviderClient client) { + this.name = name; + this.client = client; + } + + @Override + protected Void doInBackground(Void... voids) { + Category cat = lookupCategory(name); + cat.incTimesUsed(); + + cat.setContentProviderClient(client); + cat.save(); + + return null; // Make the compiler happy. + } + + private Category lookupCategory(String name) { + Cursor cursor = null; + try { + cursor = client.query( + CategoryContentProvider.BASE_URI, + Category.Table.ALL_FIELDS, + Category.Table.COLUMN_NAME + "=?", + new String[]{name}, + null); + if (cursor != null && cursor.moveToFirst()) { + return Category.fromCursor(cursor); + } + } catch (RemoteException e) { + // This feels lazy, but to hell with checked exceptions. :) + throw new RuntimeException(e); + } finally { + if (cursor != null) { + cursor.close(); + } + } + + // Newly used category... + Category cat = new Category(); + cat.setName(name); + cat.setLastUsed(new Date()); + cat.setTimesUsed(0); + return cat; + } +} diff --git a/app/src/main/java/fr/free/nrw/commons/category/CategoryItem.java b/app/src/main/java/fr/free/nrw/commons/category/CategoryItem.java new file mode 100644 index 000000000..1063979ad --- /dev/null +++ b/app/src/main/java/fr/free/nrw/commons/category/CategoryItem.java @@ -0,0 +1,54 @@ +package fr.free.nrw.commons.category; + +import android.os.Parcel; +import android.os.Parcelable; + +class CategoryItem implements Parcelable { + private final String name; + private boolean selected; + + public static Creator CREATOR = new Creator() { + @Override + public CategoryItem createFromParcel(Parcel parcel) { + return new CategoryItem(parcel); + } + + @Override + public CategoryItem[] newArray(int i) { + return new CategoryItem[0]; + } + }; + + CategoryItem(String name, boolean selected) { + this.name = name; + this.selected = selected; + } + + private CategoryItem(Parcel in) { + name = in.readString(); + selected = in.readInt() == 1; + } + + public String getName() { + return name; + } + + public boolean isSelected() { + return selected; + } + + public void setSelected(boolean selected) { + this.selected = selected; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel parcel, int flags) { + parcel.writeString(name); + parcel.writeInt(selected ? 1 : 0); + } +} diff --git a/app/src/main/java/fr/free/nrw/commons/category/MethodAUpdater.java b/app/src/main/java/fr/free/nrw/commons/category/MethodAUpdater.java index 326f85ee3..72b1f5732 100644 --- a/app/src/main/java/fr/free/nrw/commons/category/MethodAUpdater.java +++ b/app/src/main/java/fr/free/nrw/commons/category/MethodAUpdater.java @@ -13,6 +13,8 @@ import fr.free.nrw.commons.CommonsApplication; import fr.free.nrw.commons.mwapi.MediaWikiApi; import timber.log.Timber; +import static fr.free.nrw.commons.category.CategorizationFragment.SEARCH_CATS_LIMIT; + /** * Sends asynchronous queries to the Commons MediaWiki API to retrieve categories that are close to * the keyword typed in by the user. The 'srsearch' action-specific parameter is used for this @@ -20,8 +22,8 @@ import timber.log.Timber; */ class MethodAUpdater extends AsyncTask> { + private final CategorizationFragment catFragment; private String filter; - private CategorizationFragment catFragment; MethodAUpdater(CategorizationFragment catFragment) { this.catFragment = catFragment; @@ -84,7 +86,7 @@ class MethodAUpdater extends AsyncTask> { //URL https://commons.wikimedia.org/w/api.php?action=query&format=xml&list=search&srwhat=text&srenablerewrites=1&srnamespace=14&srlimit=10&srsearch= try { - categories = api.searchCategories(CategorizationFragment.SEARCH_CATS_LIMIT, filter); + categories = api.searchCategories(SEARCH_CATS_LIMIT, filter); Timber.d("Method A URL filter %s", categories); } catch (IOException e) { Timber.e(e, "IO Exception: "); diff --git a/app/src/main/java/fr/free/nrw/commons/category/OnCategoriesSaveHandler.java b/app/src/main/java/fr/free/nrw/commons/category/OnCategoriesSaveHandler.java new file mode 100644 index 000000000..a7ae0bfed --- /dev/null +++ b/app/src/main/java/fr/free/nrw/commons/category/OnCategoriesSaveHandler.java @@ -0,0 +1,7 @@ +package fr.free.nrw.commons.category; + +import java.util.ArrayList; + +public interface OnCategoriesSaveHandler { + void onCategoriesSave(ArrayList categories); +} diff --git a/app/src/main/java/fr/free/nrw/commons/category/PrefixUpdater.java b/app/src/main/java/fr/free/nrw/commons/category/PrefixUpdater.java index 121ae5a1c..7df56eff5 100644 --- a/app/src/main/java/fr/free/nrw/commons/category/PrefixUpdater.java +++ b/app/src/main/java/fr/free/nrw/commons/category/PrefixUpdater.java @@ -7,6 +7,7 @@ import android.view.View; import java.io.IOException; import java.util.ArrayList; import java.util.Calendar; +import java.util.HashMap; import java.util.Iterator; import java.util.List; @@ -14,18 +15,20 @@ import fr.free.nrw.commons.CommonsApplication; import fr.free.nrw.commons.mwapi.MediaWikiApi; import timber.log.Timber; +import static fr.free.nrw.commons.category.CategorizationFragment.SEARCH_CATS_LIMIT; + /** * Sends asynchronous queries to the Commons MediaWiki API to retrieve categories that share the * same prefix as the keyword typed in by the user. The 'acprefix' action-specific parameter is used * for this purpose. This class should be subclassed in CategorizationFragment.java to aggregate * the results. */ -public class PrefixUpdater extends AsyncTask> { +class PrefixUpdater extends AsyncTask> { + private final CategorizationFragment catFragment; private String filter; - private CategorizationFragment catFragment; - public PrefixUpdater(CategorizationFragment catFragment) { + PrefixUpdater(CategorizationFragment catFragment) { this.catFragment = catFragment; } @@ -47,7 +50,7 @@ public class PrefixUpdater extends AsyncTask> { * @param items Unfiltered list of categories * @return Filtered category list */ - private List filterYears(List items) { + private List filterIrrelevantResults(List items) { Iterator iterator; @@ -62,15 +65,18 @@ public class PrefixUpdater extends AsyncTask> { Timber.d("Previous year: %s", prevYearInString); //Copy to Iterator to prevent ConcurrentModificationException when removing item - for (iterator = items.iterator(); iterator.hasNext(); ) { + for (iterator = items.iterator(); iterator.hasNext();) { String s = iterator.next(); //Check if s contains a 4-digit word anywhere within the string (.* is wildcard) //And that s does not equal the current year or previous year - if (s.matches(".*(19|20)\\d{2}.*") && !s.contains(yearInString) && !s.contains(prevYearInString)) { - Timber.d("Filtering out year %s", s); + //And if it is an irrelevant category such as Media_needing_categories_as_of_16_June_2017(Issue #750) + if ((s.matches(".*(19|20)\\d{2}.*") && !s.contains(yearInString) && !s.contains(prevYearInString)) + || s.matches("(.*)needing(.*)")||s.matches("(.*)taken on(.*)")) { + Timber.d("Filtering out irrelevant result: %s", s); iterator.remove(); } + } Timber.d("Items: %s", items); @@ -83,14 +89,15 @@ public class PrefixUpdater extends AsyncTask> { if (TextUtils.isEmpty(filter)) { ArrayList mergedItems = new ArrayList<>(catFragment.mergeItems()); Timber.d("Merged items, waiting for filter"); - return new ArrayList<>(filterYears(mergedItems)); + return new ArrayList<>(filterIrrelevantResults(mergedItems)); } //if user types in something that is in cache, return cached category - if (catFragment.categoriesCache.containsKey(filter)) { - ArrayList cachedItems = new ArrayList<>(catFragment.categoriesCache.get(filter)); + HashMap> categoriesCache = catFragment.getCategoriesCache(); + if (categoriesCache.containsKey(filter)) { + ArrayList cachedItems = new ArrayList<>(categoriesCache.get(filter)); Timber.d("Found cache items, waiting for filter"); - return new ArrayList<>(filterYears(cachedItems)); + return new ArrayList<>(filterIrrelevantResults(cachedItems)); } //otherwise if user has typed something in that isn't in cache, search API for matching categories @@ -98,7 +105,7 @@ public class PrefixUpdater extends AsyncTask> { MediaWikiApi api = CommonsApplication.getInstance().getMWApi(); List categories = new ArrayList<>(); try { - categories = api.allCategories(CategorizationFragment.SEARCH_CATS_LIMIT, this.filter); + categories = api.allCategories(SEARCH_CATS_LIMIT, this.filter); Timber.d("Prefix URL filter %s", categories); } catch (IOException e) { Timber.e(e, "IO Exception: "); @@ -107,6 +114,6 @@ public class PrefixUpdater extends AsyncTask> { } Timber.d("Found categories from Prefix search, waiting for filter"); - return new ArrayList<>(filterYears(categories)); + return new ArrayList<>(filterIrrelevantResults(categories)); } } diff --git a/app/src/main/java/fr/free/nrw/commons/category/TitleCategories.java b/app/src/main/java/fr/free/nrw/commons/category/TitleCategories.java index 414c87e8a..a4a94cf1d 100644 --- a/app/src/main/java/fr/free/nrw/commons/category/TitleCategories.java +++ b/app/src/main/java/fr/free/nrw/commons/category/TitleCategories.java @@ -19,17 +19,12 @@ class TitleCategories extends AsyncTask> { private final static int SEARCH_CATS_LIMIT = 25; - private String title; + private final String title; TitleCategories(String title) { this.title = title; } - @Override - protected void onPreExecute() { - super.onPreExecute(); - } - @Override protected List doInBackground(Void... voids) { diff --git a/app/src/main/java/fr/free/nrw/commons/concurrency/BackgroundPoolExceptionHandler.java b/app/src/main/java/fr/free/nrw/commons/concurrency/BackgroundPoolExceptionHandler.java index 2c730a0d1..489a45c4e 100644 --- a/app/src/main/java/fr/free/nrw/commons/concurrency/BackgroundPoolExceptionHandler.java +++ b/app/src/main/java/fr/free/nrw/commons/concurrency/BackgroundPoolExceptionHandler.java @@ -9,11 +9,8 @@ public class BackgroundPoolExceptionHandler implements ExceptionHandler { public void onException(@NonNull final Throwable t) { //Crash for debug build if (BuildConfig.DEBUG) { - Thread thread = new Thread(new Runnable() { - @Override - public void run() { - throw new RuntimeException(t); - } + Thread thread = new Thread(() -> { + throw new RuntimeException(t); }); thread.start(); } diff --git a/app/src/main/java/fr/free/nrw/commons/concurrency/ThreadFactoryMaker.java b/app/src/main/java/fr/free/nrw/commons/concurrency/ThreadFactoryMaker.java index 221ebef41..d535fe5bd 100644 --- a/app/src/main/java/fr/free/nrw/commons/concurrency/ThreadFactoryMaker.java +++ b/app/src/main/java/fr/free/nrw/commons/concurrency/ThreadFactoryMaker.java @@ -11,17 +11,13 @@ class ThreadFactoryMaker { private int count = 0; @Override - public Thread newThread(final Runnable runnable) { + public Thread newThread(@NonNull final Runnable runnable) { count++; - Runnable wrapperRunnable = new Runnable() { - @Override - public void run() { - Process.setThreadPriority(priority); - runnable.run(); - } + Runnable wrapperRunnable = () -> { + Process.setThreadPriority(priority); + runnable.run(); }; - Thread t = new Thread(wrapperRunnable, String.format("%s-%s", name, count)); - return t; + return new Thread(wrapperRunnable, String.format("%s-%s", name, count)); } }; } diff --git a/app/src/main/java/fr/free/nrw/commons/concurrency/ThreadPoolExecutorService.java b/app/src/main/java/fr/free/nrw/commons/concurrency/ThreadPoolExecutorService.java index 1516d85d8..85f8cbfeb 100644 --- a/app/src/main/java/fr/free/nrw/commons/concurrency/ThreadPoolExecutorService.java +++ b/app/src/main/java/fr/free/nrw/commons/concurrency/ThreadPoolExecutorService.java @@ -39,7 +39,7 @@ public class ThreadPoolExecutorService implements Executor { } @Override - public void execute(Runnable command) { + public void execute(@NonNull Runnable command) { backgroundPool.execute(command); } diff --git a/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsActivity.java b/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsActivity.java index f1a4adfe2..4509818a4 100644 --- a/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsActivity.java +++ b/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsActivity.java @@ -3,11 +3,13 @@ package fr.free.nrw.commons.contributions; import android.content.ComponentName; import android.content.ContentResolver; import android.content.Context; +import android.content.DialogInterface; import android.content.Intent; import android.content.ServiceConnection; import android.content.SharedPreferences; import android.database.Cursor; import android.database.DataSetObserver; +import android.net.Uri; import android.os.Bundle; import android.os.IBinder; import android.preference.PreferenceManager; @@ -17,6 +19,7 @@ import android.support.v4.app.LoaderManager; import android.support.v4.content.CursorLoader; import android.support.v4.content.Loader; import android.support.v4.widget.CursorAdapter; +import android.support.v7.app.AlertDialog; import android.view.Menu; import android.view.MenuItem; import android.view.View; @@ -27,7 +30,10 @@ import com.google.common.util.concurrent.FutureCallback; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; +import java.text.ParseException; +import java.text.SimpleDateFormat; import java.util.ArrayList; +import java.util.Date; import butterknife.ButterKnife; import fr.free.nrw.commons.CommonsApplication; @@ -110,6 +116,12 @@ public class ContributionsActivity super.onPause(); } + @Override + protected void onStart() { + super.onStart(); + displayFeedbackPopup(); + } + @Override protected void onAuthCookieAcquired(String authCookie) { // Do a sync everytime we get here! @@ -342,4 +354,56 @@ public class ContributionsActivity Intent contributionsIntent = new Intent(context, ContributionsActivity.class); context.startActivity(contributionsIntent); } + + private void displayFeedbackPopup() { + + Date popupMessageEndDate = null; + try { + String validUntil = "23/08/2017"; + SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy"); + popupMessageEndDate = sdf.parse(validUntil); + } catch (ParseException e) { + e.printStackTrace(); + } + + final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences( + CommonsApplication.getInstance()); + + // boolean to save users request about displaying popup + boolean displayFeedbackPopup = prefs.getBoolean("display_feedbak_popup", true); + + // boolean to recognize is application re-started. Will be used for "remind me later" option + int appStartCounter = prefs.getInt("app_start_counter" ,0); + + // if time is valid and shared pref says display + if (new Date().before(popupMessageEndDate) && displayFeedbackPopup && (appStartCounter == 4)) { + + new AlertDialog.Builder(this) + .setTitle(getResources().getString(R.string.feedback_popup_title)) + .setMessage(getResources().getString(R.string.feedback_popup_description)) + .setPositiveButton(getResources().getString(R.string.feedback_popup_accept), + new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + // Go to the page + Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri + .parse(getResources() + .getString(R.string.feedback_page_url))); + startActivity(browserIntent); + // No need to dislay this window to the user again. + prefs.edit().putBoolean("display_feedbak_popup" , false).commit(); + dialog.dismiss(); + } + }) + .setNegativeButton(getResources().getString(R.string.feedback_popup_decline), + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + // Dismiss the dialog and not to show it later + prefs.edit().putBoolean("display_feedbak_popup", false).commit(); + dialog.dismiss(); + } + }) + .create().show(); + } + } } diff --git a/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsContentProvider.java b/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsContentProvider.java index 9dc933358..6e84065f2 100644 --- a/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsContentProvider.java +++ b/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsContentProvider.java @@ -7,6 +7,7 @@ import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteQueryBuilder; import android.net.Uri; +import android.support.annotation.NonNull; import android.text.TextUtils; import fr.free.nrw.commons.CommonsApplication; @@ -38,7 +39,7 @@ public class ContributionsContentProvider extends ContentProvider{ } @Override - public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { + public Cursor query(@NonNull Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder(); queryBuilder.setTables(Contribution.Table.TABLE_NAME); @@ -71,12 +72,12 @@ public class ContributionsContentProvider extends ContentProvider{ } @Override - public String getType(Uri uri) { + public String getType(@NonNull Uri uri) { return null; } @Override - public Uri insert(Uri uri, ContentValues contentValues) { + public Uri insert(@NonNull Uri uri, ContentValues contentValues) { int uriType = uriMatcher.match(uri); SQLiteDatabase sqlDB = CommonsApplication.getInstance().getDBOpenHelper().getWritableDatabase(); long id = 0; @@ -92,7 +93,7 @@ public class ContributionsContentProvider extends ContentProvider{ } @Override - public int delete(Uri uri, String s, String[] strings) { + public int delete(@NonNull Uri uri, String s, String[] strings) { int rows = 0; int uriType = uriMatcher.match(uri); @@ -114,7 +115,7 @@ public class ContributionsContentProvider extends ContentProvider{ } @Override - public int bulkInsert(Uri uri, ContentValues[] values) { + public int bulkInsert(@NonNull Uri uri, @NonNull ContentValues[] values) { Timber.d("Hello, bulk insert! (ContributionsContentProvider)"); int uriType = uriMatcher.match(uri); SQLiteDatabase sqlDB = CommonsApplication.getInstance().getDBOpenHelper().getWritableDatabase(); @@ -136,7 +137,7 @@ public class ContributionsContentProvider extends ContentProvider{ } @Override - public int update(Uri uri, ContentValues contentValues, String selection, String[] selectionArgs) { + public int update(@NonNull Uri uri, ContentValues contentValues, String selection, String[] selectionArgs) { /* SQL Injection warnings: First, note that we're not exposing this to the outside world (exported="false") Even then, we should make sure to sanitize all user input appropriately. Input that passes through ContentValues diff --git a/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsListFragment.java b/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsListFragment.java index 8025b94bf..bcbb5a739 100644 --- a/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsListFragment.java +++ b/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsListFragment.java @@ -8,6 +8,7 @@ import android.content.SharedPreferences; import android.content.pm.PackageManager; import android.os.Build; import android.os.Bundle; +import android.support.annotation.NonNull; import android.support.v4.app.Fragment; import android.support.v4.content.ContextCompat; import android.support.v7.app.AlertDialog; @@ -29,6 +30,7 @@ import fr.free.nrw.commons.R; import fr.free.nrw.commons.nearby.NearbyActivity; import timber.log.Timber; +import static android.Manifest.permission.READ_EXTERNAL_STORAGE; import static android.app.Activity.RESULT_OK; public class ContributionsListFragment extends Fragment { @@ -110,11 +112,11 @@ public class ContributionsListFragment extends Fragment { // Here, thisActivity is the current activity if (ContextCompat.checkSelfPermission(getActivity(), - Manifest.permission.READ_EXTERNAL_STORAGE) + READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { // Should we show an explanation? - if (shouldShowRequestPermissionRationale(Manifest.permission.READ_EXTERNAL_STORAGE)) { + if (shouldShowRequestPermissionRationale(READ_EXTERNAL_STORAGE)) { // Show an explanation to the user *asynchronously* -- don't block // this thread waiting for the user's response! After the user @@ -122,15 +124,9 @@ public class ContributionsListFragment extends Fragment { new AlertDialog.Builder(getActivity()) .setMessage(getString(R.string.storage_permission_rationale)) - .setPositiveButton("OK", new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - - requestPermissions( - new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, - 1); - dialog.dismiss(); - } + .setPositiveButton("OK", (dialog, which) -> { + requestPermissions(new String[]{READ_EXTERNAL_STORAGE}, 1); + dialog.dismiss(); }) .setNegativeButton("Cancel", null) .create() @@ -140,7 +136,7 @@ public class ContributionsListFragment extends Fragment { // No explanation needed, we can request the permission. - requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, + requestPermissions(new String[]{READ_EXTERNAL_STORAGE}, 1); // MY_PERMISSIONS_REQUEST_READ_CONTACTS is an @@ -167,7 +163,7 @@ public class ContributionsListFragment extends Fragment { } @Override - public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { + public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { Timber.d("onRequestPermissionsResult: req code = " + " perm = " + permissions + " grant =" + grantResults); diff --git a/app/src/main/java/fr/free/nrw/commons/contributions/UploadCountClient.java b/app/src/main/java/fr/free/nrw/commons/contributions/UploadCountClient.java index 9667f9057..4a04e3888 100644 --- a/app/src/main/java/fr/free/nrw/commons/contributions/UploadCountClient.java +++ b/app/src/main/java/fr/free/nrw/commons/contributions/UploadCountClient.java @@ -14,10 +14,10 @@ import fr.free.nrw.commons.concurrency.BackgroundPoolExceptionHandler; import fr.free.nrw.commons.concurrency.ThreadPoolExecutorService; import timber.log.Timber; -public class UploadCountClient { +class UploadCountClient { private ThreadPoolExecutorService threadPoolExecutor; - public UploadCountClient() { + UploadCountClient() { threadPoolExecutor = new ThreadPoolExecutorService.Builder("bg-pool") .setPoolSize(Runtime.getRuntime().availableProcessors()) .setExceptionHandler(new BackgroundPoolExceptionHandler()) @@ -27,29 +27,26 @@ public class UploadCountClient { private static final String UPLOAD_COUNT_URL_TEMPLATE = "https://tools.wmflabs.org/urbanecmbot/uploadsbyuser/uploadsbyuser.py?user=%s"; - public ListenableFuture getUploadCount(final String userName) { + ListenableFuture getUploadCount(final String userName) { final SettableFuture future = SettableFuture.create(); - threadPoolExecutor.schedule(new Runnable() { - @Override - public void run() { - URL url; + threadPoolExecutor.schedule(() -> { + URL url; + try { + url = new URL(String.format(Locale.ENGLISH, UPLOAD_COUNT_URL_TEMPLATE, + new PageTitle(userName).getText())); + HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection(); try { - url = new URL(String.format(Locale.ENGLISH, UPLOAD_COUNT_URL_TEMPLATE, - new PageTitle(userName).getText())); - HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection(); - try { - BufferedReader bufferedReader = new BufferedReader(new - InputStreamReader(urlConnection.getInputStream())); - String uploadCount = bufferedReader.readLine(); - bufferedReader.close(); - future.set(Integer.parseInt(uploadCount)); - } finally { - urlConnection.disconnect(); - } - } catch (Exception e) { - Timber.e("Error getting upload count Error", e); - future.setException(e); + BufferedReader bufferedReader = new BufferedReader(new + InputStreamReader(urlConnection.getInputStream())); + String uploadCount = bufferedReader.readLine(); + bufferedReader.close(); + future.set(Integer.parseInt(uploadCount)); + } finally { + urlConnection.disconnect(); } + } catch (Exception e) { + Timber.e("Error getting upload count Error", e); + future.setException(e); } }); return future; diff --git a/app/src/main/java/fr/free/nrw/commons/media/MediaDetailFragment.java b/app/src/main/java/fr/free/nrw/commons/media/MediaDetailFragment.java index 784db337d..d739e9040 100644 --- a/app/src/main/java/fr/free/nrw/commons/media/MediaDetailFragment.java +++ b/app/src/main/java/fr/free/nrw/commons/media/MediaDetailFragment.java @@ -119,12 +119,7 @@ public class MediaDetailFragment extends Fragment { licenseList = new LicenseList(getActivity()); // Progressively darken the image in the background when we scroll detail pane up - scrollListener = new ViewTreeObserver.OnScrollChangedListener() { - @Override - public void onScrollChanged() { - updateTheDarkness(); - } - }; + scrollListener = this::updateTheDarkness; view.getViewTreeObserver().addOnScrollChangedListener(scrollListener); // Layout layoutListener to size the spacer item relative to the available space. @@ -216,9 +211,23 @@ public class MediaDetailFragment extends Fragment { if (success) { extractor.fill(media); - setTextFields(media); - setOnClickListeners(media); - } else { + // Set text of desc, license, and categories + desc.setText(prettyDescription(media)); + license.setText(prettyLicense(media)); + coordinates.setText(prettyCoordinates(media)); + uploadedDate.setText(prettyUploadedDate(media)); + + categoryNames.clear(); + categoryNames.addAll(media.getCategories()); + + categoriesLoaded = true; + categoriesPresent = (categoryNames.size() > 0); + if (!categoriesPresent) { + // Stick in a filler element. + categoryNames.add(getString(R.string.detail_panel_cats_none)); + } + rebuildCatList(); + } else { Timber.d("Failed to load photo details."); } } @@ -251,41 +260,6 @@ public class MediaDetailFragment extends Fragment { super.onDestroyView(); } - private void setTextFields(Media media) { - desc.setText(prettyDescription(media)); - license.setText(prettyLicense(media)); - coordinates.setText(prettyCoordinates(media)); - uploadedDate.setText(prettyUploadedDate(media)); - - categoryNames.clear(); - categoryNames.addAll(media.getCategories()); - - categoriesLoaded = true; - categoriesPresent = (categoryNames.size() > 0); - if (!categoriesPresent) { - // Stick in a filler element. - categoryNames.add(getString(R.string.detail_panel_cats_none)); - } - rebuildCatList(); - } - - private void setOnClickListeners(final Media media) { - license.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - openWebBrowser(licenseLink(media)); - } - }); - if (media.getCoordinates() != null) { - coordinates.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - openMap(media.getCoordinates()); - } - }); - } - } - private void rebuildCatList() { categoryContainer.removeAllViews(); // @fixme add the category items @@ -301,15 +275,12 @@ public class MediaDetailFragment extends Fragment { textView.setText(catName); if (categoriesLoaded && categoriesPresent) { - textView.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - String selectedCategoryTitle = "Category:" + catName; - Intent viewIntent = new Intent(); - viewIntent.setAction(Intent.ACTION_VIEW); - viewIntent.setData(new PageTitle(selectedCategoryTitle).getCanonicalUri()); - startActivity(viewIntent); - } + textView.setOnClickListener(view -> { + String selectedCategoryTitle = "Category:" + catName; + Intent viewIntent = new Intent(); + viewIntent.setAction(Intent.ACTION_VIEW); + viewIntent.setData(new PageTitle(selectedCategoryTitle).getCanonicalUri()); + startActivity(viewIntent); }); } return item; @@ -371,33 +342,4 @@ public class MediaDetailFragment extends Fragment { } return media.getCoordinates().getPrettyCoordinateString(); } - - private @Nullable String licenseLink(Media media) { - String licenseKey = media.getLicense(); - if (licenseKey == null || licenseKey.equals("")) { - return null; - } - License licenseObj = licenseList.get(licenseKey); - if (licenseObj == null) { - return null; - } else { - return licenseObj.getUrl(Locale.getDefault().getLanguage()); - } - } - - private void openWebBrowser(String url) { - Intent browser = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); - startActivity(browser); - } - - private void openMap(LatLng coordinates) { - //Open map app at given position - Uri gmmIntentUri = Uri.parse( - "geo:0,0?q=" + coordinates.getLatitude() + "," + coordinates.getLatitude()); - Intent mapIntent = new Intent(Intent.ACTION_VIEW, gmmIntentUri); - - if (mapIntent.resolveActivity(getActivity().getPackageManager()) != null) { - startActivity(mapIntent); - } - } } diff --git a/app/src/main/java/fr/free/nrw/commons/media/MediaDetailPagerFragment.java b/app/src/main/java/fr/free/nrw/commons/media/MediaDetailPagerFragment.java index f684c6484..271ac5c92 100644 --- a/app/src/main/java/fr/free/nrw/commons/media/MediaDetailPagerFragment.java +++ b/app/src/main/java/fr/free/nrw/commons/media/MediaDetailPagerFragment.java @@ -35,6 +35,19 @@ import fr.free.nrw.commons.contributions.ContributionsActivity; import fr.free.nrw.commons.mwapi.EventLog; public class MediaDetailPagerFragment extends Fragment implements ViewPager.OnPageChangeListener { + + public interface MediaDetailProvider { + Media getMediaAtPosition(int i); + + int getTotalMediaCount(); + + void notifyDatasetChanged(); + + void registerDataSetObserver(DataSetObserver observer); + + void unregisterDataSetObserver(DataSetObserver observer); + } + private ViewPager pager; private Boolean editable; private CommonsApplication app; @@ -48,14 +61,6 @@ public class MediaDetailPagerFragment extends Fragment implements ViewPager.OnPa this.editable = editable; } - 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 { @@ -65,14 +70,9 @@ public class MediaDetailPagerFragment extends Fragment implements ViewPager.OnPa @Override public Fragment getItem(int i) { - if(i == 0) { + if (i == 0) { // See bug https://code.google.com/p/android/issues/detail?id=27526 - pager.postDelayed(new Runnable() { - @Override - public void run() { - getActivity().supportInvalidateOptionsMenu(); - } - }, 5); + pager.postDelayed(() -> getActivity().supportInvalidateOptionsMenu(), 5); } return MediaDetailFragment.forMedia(i, editable); } @@ -95,14 +95,11 @@ public class MediaDetailPagerFragment extends Fragment implements ViewPager.OnPa final int pageNumber = savedInstanceState.getInt("current-page"); // Adapter doesn't seem to be loading immediately. // Dear God, please forgive us for our sins - view.postDelayed(new Runnable() { - @Override - public void run() { - pager.setAdapter(adapter); - pager.setCurrentItem(pageNumber, false); - getActivity().supportInvalidateOptionsMenu(); - adapter.notifyDataSetChanged(); - } + view.postDelayed(() -> { + pager.setAdapter(adapter); + pager.setCurrentItem(pageNumber, false); + getActivity().supportInvalidateOptionsMenu(); + adapter.notifyDataSetChanged(); }, 100); } else { pager.setAdapter(adapter); @@ -120,7 +117,7 @@ public class MediaDetailPagerFragment extends Fragment implements ViewPager.OnPa @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - if(savedInstanceState != null) { + if (savedInstanceState != null) { editable = savedInstanceState.getBoolean("editable"); } app = CommonsApplication.getInstance(); @@ -191,13 +188,8 @@ public class MediaDetailPagerFragment extends Fragment implements ViewPager.OnPa if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !(ContextCompat.checkSelfPermission(getContext(), Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED)) { Snackbar.make(getView(), R.string.storage_permission_rationale, Snackbar.LENGTH_INDEFINITE) - .setAction(R.string.ok, new View.OnClickListener() { - @Override - public void onClick(View view) { - ActivityCompat.requestPermissions(getActivity(), - new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, 1); - } - }).show(); + .setAction(R.string.ok, view -> ActivityCompat.requestPermissions(getActivity(), + new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, 1)).show(); } else { final DownloadManager manager = (DownloadManager)getActivity().getSystemService(Context.DOWNLOAD_SERVICE); manager.enqueue(req); @@ -206,13 +198,13 @@ public class MediaDetailPagerFragment extends Fragment implements ViewPager.OnPa @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { - if(!editable) { // Disable menu options for editable views + if (!editable) { // Disable menu options for editable views menu.clear(); // see http://stackoverflow.com/a/8495697/17865 inflater.inflate(R.menu.fragment_image_detail, menu); - if(pager != null) { + if (pager != null) { MediaDetailProvider provider = (MediaDetailProvider)getActivity(); 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 menu.findItem(R.id.menu_retry_current_image).setEnabled(false).setVisible(false); menu.findItem(R.id.menu_cancel_current_image).setEnabled(false).setVisible(false); diff --git a/app/src/main/java/fr/free/nrw/commons/modifications/ModificationsContentProvider.java b/app/src/main/java/fr/free/nrw/commons/modifications/ModificationsContentProvider.java index 9c9421864..11caa94fa 100644 --- a/app/src/main/java/fr/free/nrw/commons/modifications/ModificationsContentProvider.java +++ b/app/src/main/java/fr/free/nrw/commons/modifications/ModificationsContentProvider.java @@ -7,6 +7,7 @@ import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteQueryBuilder; import android.net.Uri; +import android.support.annotation.NonNull; import android.text.TextUtils; import fr.free.nrw.commons.CommonsApplication; @@ -39,7 +40,7 @@ public class ModificationsContentProvider extends ContentProvider{ } @Override - public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { + public Cursor query(@NonNull Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder(); queryBuilder.setTables(ModifierSequence.Table.TABLE_NAME); @@ -61,12 +62,12 @@ public class ModificationsContentProvider extends ContentProvider{ } @Override - public String getType(Uri uri) { + public String getType(@NonNull Uri uri) { return null; } @Override - public Uri insert(Uri uri, ContentValues contentValues) { + public Uri insert(@NonNull Uri uri, ContentValues contentValues) { int uriType = uriMatcher.match(uri); SQLiteDatabase sqlDB = CommonsApplication.getInstance().getDBOpenHelper().getWritableDatabase(); long id = 0; @@ -82,7 +83,7 @@ public class ModificationsContentProvider extends ContentProvider{ } @Override - public int delete(Uri uri, String s, String[] strings) { + public int delete(@NonNull Uri uri, String s, String[] strings) { int uriType = uriMatcher.match(uri); SQLiteDatabase sqlDB = CommonsApplication.getInstance().getDBOpenHelper().getWritableDatabase(); switch (uriType) { @@ -99,7 +100,7 @@ public class ModificationsContentProvider extends ContentProvider{ } @Override - public int bulkInsert(Uri uri, ContentValues[] values) { + public int bulkInsert(@NonNull Uri uri, @NonNull ContentValues[] values) { Timber.d("Hello, bulk insert! (ModificationsContentProvider)"); int uriType = uriMatcher.match(uri); SQLiteDatabase sqlDB = CommonsApplication.getInstance().getDBOpenHelper().getWritableDatabase(); @@ -121,7 +122,7 @@ public class ModificationsContentProvider extends ContentProvider{ } @Override - public int update(Uri uri, ContentValues contentValues, String selection, String[] selectionArgs) { + public int update(@NonNull Uri uri, ContentValues contentValues, String selection, String[] selectionArgs) { /* SQL Injection warnings: First, note that we're not exposing this to the outside world (exported="false") Even then, we should make sure to sanitize all user input appropriately. Input that passes through ContentValues 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 bb2356dd6..9dd0f9939 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 @@ -351,12 +351,7 @@ public class ApacheHttpClientMediaWikiApi implements MediaWikiApi { @Override @NonNull public UploadResult uploadFile(String filename, InputStream file, long dataLength, String pageContents, String editSummary, final ProgressListener progressListener) throws IOException { - ApiResult result = api.upload(filename, file, dataLength, pageContents, editSummary, new in.yuvi.http.fluent.ProgressListener() { - @Override - public void onProgress(long transferred, long total) { - progressListener.onProgress(transferred, total); - } - }); + ApiResult result = api.upload(filename, file, dataLength, pageContents, editSummary, progressListener::onProgress); Log.e("WTF", "Result: "+result.toString()); diff --git a/app/src/main/java/fr/free/nrw/commons/nearby/NearbyActivity.java b/app/src/main/java/fr/free/nrw/commons/nearby/NearbyActivity.java index 3d26b22f1..d58eb3566 100644 --- a/app/src/main/java/fr/free/nrw/commons/nearby/NearbyActivity.java +++ b/app/src/main/java/fr/free/nrw/commons/nearby/NearbyActivity.java @@ -2,7 +2,6 @@ package fr.free.nrw.commons.nearby; import android.Manifest; import android.content.Context; -import android.content.DialogInterface; import android.content.Intent; import android.content.pm.PackageManager; import android.location.LocationManager; @@ -41,7 +40,8 @@ import timber.log.Timber; public class NearbyActivity extends NavigationBaseActivity { - @BindView(R.id.progressBar) ProgressBar progressBar; + @BindView(R.id.progressBar) + ProgressBar progressBar; private boolean isMapViewActive = false; private static final int LOCATION_REQUEST = 1; @@ -115,15 +115,11 @@ public class NearbyActivity extends NavigationBaseActivity { new AlertDialog.Builder(this) .setMessage(getString(R.string.location_permission_rationale)) - .setPositiveButton("OK", new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - - ActivityCompat.requestPermissions(NearbyActivity.this, - new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, - LOCATION_REQUEST); - dialog.dismiss(); - } + .setPositiveButton("OK", (dialog, which) -> { + ActivityCompat.requestPermissions(NearbyActivity.this, + new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, + LOCATION_REQUEST); + dialog.dismiss(); }) .setNegativeButton("Cancel", null) .create() @@ -175,26 +171,19 @@ public class NearbyActivity extends NavigationBaseActivity { LocationManager manager = (LocationManager) getSystemService(LOCATION_SERVICE); if (!manager.isProviderEnabled(LocationManager.GPS_PROVIDER)) { Timber.d("GPS is not enabled"); - AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this); - alertDialogBuilder.setMessage(R.string.gps_disabled) + new AlertDialog.Builder(this) + .setMessage(R.string.gps_disabled) .setCancelable(false) .setPositiveButton(R.string.enable_gps, - new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - Intent callGPSSettingIntent = new Intent( - android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS); - Timber.d("Loaded settings page"); - startActivityForResult(callGPSSettingIntent, 1); - } - }); - alertDialogBuilder.setNegativeButton(R.string.menu_cancel_upload, - new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - dialog.cancel(); - } - }); - AlertDialog alert = alertDialogBuilder.create(); - alert.show(); + (dialog, id) -> { + Intent callGPSSettingIntent = new Intent( + android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS); + Timber.d("Loaded settings page"); + startActivityForResult(callGPSSettingIntent, 1); + }) + .setNegativeButton(R.string.menu_cancel_upload, (dialog, id) -> dialog.cancel()) + .create() + .show(); } else { Timber.d("GPS is enabled"); } @@ -257,7 +246,7 @@ public class NearbyActivity extends NavigationBaseActivity { private final Context mContext; - private NearbyAsyncTask (Context context) { + private NearbyAsyncTask(Context context) { mContext = context; } diff --git a/app/src/main/java/fr/free/nrw/commons/nearby/NearbyAdapterFactory.java b/app/src/main/java/fr/free/nrw/commons/nearby/NearbyAdapterFactory.java index 5fffcab2a..d5eb05851 100644 --- a/app/src/main/java/fr/free/nrw/commons/nearby/NearbyAdapterFactory.java +++ b/app/src/main/java/fr/free/nrw/commons/nearby/NearbyAdapterFactory.java @@ -1,5 +1,7 @@ package fr.free.nrw.commons.nearby; +import android.support.annotation.NonNull; + import com.pedrogomez.renderers.ListAdapteeCollection; import com.pedrogomez.renderers.RVRendererAdapter; import com.pedrogomez.renderers.RendererBuilder; @@ -10,7 +12,7 @@ import java.util.List; class NearbyAdapterFactory { private PlaceRenderer.PlaceClickedListener listener; - NearbyAdapterFactory(PlaceRenderer.PlaceClickedListener listener) { + NearbyAdapterFactory(@NonNull PlaceRenderer.PlaceClickedListener listener) { this.listener = listener; } diff --git a/app/src/main/java/fr/free/nrw/commons/nearby/NearbyBaseMarker.java b/app/src/main/java/fr/free/nrw/commons/nearby/NearbyBaseMarker.java index e0d08f8cb..e8f1b0da0 100644 --- a/app/src/main/java/fr/free/nrw/commons/nearby/NearbyBaseMarker.java +++ b/app/src/main/java/fr/free/nrw/commons/nearby/NearbyBaseMarker.java @@ -16,6 +16,17 @@ import fr.free.nrw.commons.utils.UriDeserializer; import fr.free.nrw.commons.utils.UriSerializer; public class NearbyBaseMarker extends BaseMarkerOptions { + + public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { + public NearbyBaseMarker createFromParcel(Parcel in) { + return new NearbyBaseMarker(in); + } + + public NearbyBaseMarker[] newArray(int size) { + return new NearbyBaseMarker[size]; + } + }; + private Place place; NearbyBaseMarker() { @@ -74,15 +85,4 @@ public class NearbyBaseMarker extends BaseMarkerOptions CREATOR - = new Parcelable.Creator() { - public NearbyBaseMarker createFromParcel(Parcel in) { - return new NearbyBaseMarker(in); - } - - public NearbyBaseMarker[] newArray(int size) { - return new NearbyBaseMarker[size]; - } - }; } diff --git a/app/src/main/java/fr/free/nrw/commons/nearby/NearbyController.java b/app/src/main/java/fr/free/nrw/commons/nearby/NearbyController.java index b38c01022..b08b99d72 100644 --- a/app/src/main/java/fr/free/nrw/commons/nearby/NearbyController.java +++ b/app/src/main/java/fr/free/nrw/commons/nearby/NearbyController.java @@ -2,9 +2,10 @@ package fr.free.nrw.commons.nearby; import android.content.Context; import android.content.SharedPreferences; +import android.graphics.Bitmap; import android.preference.PreferenceManager; +import android.support.graphics.drawable.VectorDrawableCompat; -import com.mapbox.mapboxsdk.annotations.Icon; import com.mapbox.mapboxsdk.annotations.IconFactory; import java.util.ArrayList; @@ -18,6 +19,7 @@ import java.util.Map; import fr.free.nrw.commons.CommonsApplication; import fr.free.nrw.commons.R; import fr.free.nrw.commons.location.LatLng; +import fr.free.nrw.commons.utils.UiUtils; import timber.log.Timber; import static fr.free.nrw.commons.utils.LengthUtils.computeDistanceBetween; @@ -50,13 +52,10 @@ public class NearbyController { distances.put(place, computeDistanceBetween(place.location, curLatLng)); } Collections.sort(places, - new Comparator() { - @Override - public int compare(Place lhs, Place rhs) { - double lhsDistance = distances.get(lhs); - double rhsDistance = distances.get(rhs); - return (int) (lhsDistance - rhsDistance); - } + (lhs, rhs) -> { + double lhsDistance = distances.get(lhs); + double rhsDistance = distances.get(rhs); + return (int) (lhsDistance - rhsDistance); } ); } @@ -98,13 +97,15 @@ public class NearbyController { placeList = placeList.subList(0, Math.min(placeList.size(), MAX_RESULTS)); + Bitmap icon = UiUtils.getBitmap( + VectorDrawableCompat.create( + context.getResources(), R.drawable.ic_custom_map_marker, context.getTheme() + )); + for (Place place: placeList) { String distance = formatDistanceBetween(curLatLng, place.location); place.setDistance(distance); - Icon icon = IconFactory.getInstance(context) - .fromResource(R.drawable.custom_map_marker); - NearbyBaseMarker nearbyBaseMarker = new NearbyBaseMarker(); nearbyBaseMarker.title(place.name); nearbyBaseMarker.position( @@ -112,7 +113,8 @@ public class NearbyController { place.location.getLatitude(), place.location.getLongitude())); nearbyBaseMarker.place(place); - nearbyBaseMarker.icon(icon); + nearbyBaseMarker.icon(IconFactory.getInstance(context) + .fromBitmap(icon)); baseMarkerOptions.add(nearbyBaseMarker); } diff --git a/app/src/main/java/fr/free/nrw/commons/nearby/NearbyInfoDialog.java b/app/src/main/java/fr/free/nrw/commons/nearby/NearbyInfoDialog.java index bb2d2fed9..1203d5a0d 100644 --- a/app/src/main/java/fr/free/nrw/commons/nearby/NearbyInfoDialog.java +++ b/app/src/main/java/fr/free/nrw/commons/nearby/NearbyInfoDialog.java @@ -63,15 +63,10 @@ public class NearbyInfoDialog extends OverlayDialog { overflowButton.setVisibility(showMenu() ? View.VISIBLE : View.GONE); - overflowButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - popupMenuListener(); - } - }); + overflowButton.setOnClickListener(this::popupMenuListener); } - private void popupMenuListener() { + private void popupMenuListener(View v) { PopupMenu popupMenu = new PopupMenu(getActivity(), overflowButton); popupMenu.inflate(R.menu.nearby_info_dialog_options); diff --git a/app/src/main/java/fr/free/nrw/commons/nearby/NearbyListFragment.java b/app/src/main/java/fr/free/nrw/commons/nearby/NearbyListFragment.java index ea7ce3478..00b8a2840 100644 --- a/app/src/main/java/fr/free/nrw/commons/nearby/NearbyListFragment.java +++ b/app/src/main/java/fr/free/nrw/commons/nearby/NearbyListFragment.java @@ -48,12 +48,7 @@ public class NearbyListFragment extends Fragment { View view = inflater.inflate(R.layout.fragment_nearby, container, false); recyclerView = (RecyclerView) view.findViewById(R.id.listView); recyclerView.setLayoutManager(new LinearLayoutManager(getContext())); - adapterFactory = new NearbyAdapterFactory(new PlaceRenderer.PlaceClickedListener() { - @Override - public void placeClicked(Place place) { - NearbyInfoDialog.showYourself(getActivity(), place); - } - }); + adapterFactory = new NearbyAdapterFactory(place -> NearbyInfoDialog.showYourself(getActivity(), place)); return view; } diff --git a/app/src/main/java/fr/free/nrw/commons/nearby/NearbyMapFragment.java b/app/src/main/java/fr/free/nrw/commons/nearby/NearbyMapFragment.java index 54c1a565e..bc5830809 100644 --- a/app/src/main/java/fr/free/nrw/commons/nearby/NearbyMapFragment.java +++ b/app/src/main/java/fr/free/nrw/commons/nearby/NearbyMapFragment.java @@ -88,25 +88,19 @@ public class NearbyMapFragment extends android.support.v4.app.Fragment { // create map mapView = new MapView(getActivity(), options); mapView.onCreate(savedInstanceState); - mapView.getMapAsync(new OnMapReadyCallback() { - @Override - public void onMapReady(MapboxMap mapboxMap) { - mapboxMap.addMarkers(baseMarkerOptions); + mapView.getMapAsync(mapboxMap -> { + mapboxMap.addMarkers(baseMarkerOptions); - mapboxMap.setOnMarkerClickListener(new MapboxMap.OnMarkerClickListener() { - @Override - public boolean onMarkerClick(@NonNull Marker marker) { - if (marker instanceof NearbyMarker) { - NearbyMarker nearbyMarker = (NearbyMarker) marker; - Place place = nearbyMarker.getNearbyBaseMarker().getPlace(); - NearbyInfoDialog.showYourself(getActivity(), place); - } - return false; - } - }); + mapboxMap.setOnMarkerClickListener(marker -> { + if (marker instanceof NearbyMarker) { + NearbyMarker nearbyMarker = (NearbyMarker) marker; + Place place = nearbyMarker.getNearbyBaseMarker().getPlace(); + NearbyInfoDialog.showYourself(getActivity(), place); + } + return false; + }); - addCurrentLocationMarker(mapboxMap); - } + addCurrentLocationMarker(mapboxMap); }); if (PreferenceManager.getDefaultSharedPreferences(getActivity()).getBoolean("theme",true)) { mapView.setStyleUrl(getResources().getString(R.string.map_theme_dark)); diff --git a/app/src/main/java/fr/free/nrw/commons/nearby/PlaceRenderer.java b/app/src/main/java/fr/free/nrw/commons/nearby/PlaceRenderer.java index 12e24f1ae..f4c8a5d61 100644 --- a/app/src/main/java/fr/free/nrw/commons/nearby/PlaceRenderer.java +++ b/app/src/main/java/fr/free/nrw/commons/nearby/PlaceRenderer.java @@ -1,5 +1,6 @@ package fr.free.nrw.commons.nearby; +import android.support.annotation.NonNull; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -19,7 +20,7 @@ class PlaceRenderer extends Renderer { @BindView(R.id.icon) ImageView icon; private final PlaceClickedListener listener; - PlaceRenderer(PlaceClickedListener listener) { + PlaceRenderer(@NonNull PlaceClickedListener listener) { this.listener = listener; } @@ -35,14 +36,7 @@ class PlaceRenderer extends Renderer { @Override protected void hookListeners(View view) { - view.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - if (listener != null) { - listener.placeClicked(getContent()); - } - } - }); + view.setOnClickListener(v -> listener.placeClicked(getContent())); } @Override diff --git a/app/src/main/java/fr/free/nrw/commons/settings/SettingsFragment.java b/app/src/main/java/fr/free/nrw/commons/settings/SettingsFragment.java index bdac4a0f5..cfeda91d1 100644 --- a/app/src/main/java/fr/free/nrw/commons/settings/SettingsFragment.java +++ b/app/src/main/java/fr/free/nrw/commons/settings/SettingsFragment.java @@ -28,21 +28,15 @@ public class SettingsFragment extends PreferenceFragment { licensePreference.setSummary(getString(Utils.licenseNameFor(licensePreference.getValue()))); // Keep summary updated when changing value - licensePreference.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { - @Override - public boolean onPreferenceChange(Preference preference, Object newValue) { - preference.setSummary(getString(Utils.licenseNameFor((String) newValue))); - return true; - } + licensePreference.setOnPreferenceChangeListener((preference, newValue) -> { + preference.setSummary(getString(Utils.licenseNameFor((String) newValue))); + return true; }); CheckBoxPreference themePreference = (CheckBoxPreference) findPreference("theme"); - themePreference.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { - @Override - public boolean onPreferenceChange(Preference preference, Object newValue) { - getActivity().recreate(); - return true; - } + themePreference.setOnPreferenceChangeListener((preference, newValue) -> { + getActivity().recreate(); + return true; }); final EditTextPreference uploadLimit = (EditTextPreference) findPreference("uploads"); @@ -51,36 +45,27 @@ public class SettingsFragment extends PreferenceFragment { int uploads = sharedPref.getInt(Prefs.UPLOADS_SHOWING, 100); uploadLimit.setText(uploads + ""); uploadLimit.setSummary(uploads + ""); - uploadLimit.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { - - @Override - public boolean onPreferenceChange(Preference preference, Object newValue) { - int value = Integer.parseInt(newValue.toString()); - final SharedPreferences.Editor editor = sharedPref.edit(); - if (value > 500) { - new AlertDialog.Builder(getActivity()) - .setTitle(R.string.maximum_limit) - .setMessage(R.string.maximum_limit_alert) - .setPositiveButton(android.R.string.yes, - new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int which) { - } - }) - .setIcon(android.R.drawable.ic_dialog_alert) - .show(); - editor.putInt(Prefs.UPLOADS_SHOWING, 500); - editor.putBoolean(Prefs.IS_CONTRIBUTION_COUNT_CHANGED,true); - uploadLimit.setSummary(500 + ""); - uploadLimit.setText(500 + ""); - } else { - editor.putInt(Prefs.UPLOADS_SHOWING, Integer.parseInt(newValue.toString())); - editor.putBoolean(Prefs.IS_CONTRIBUTION_COUNT_CHANGED,true); - uploadLimit.setSummary(newValue.toString()); - } - editor.apply(); - return true; + uploadLimit.setOnPreferenceChangeListener((preference, newValue) -> { + int value = Integer.parseInt(newValue.toString()); + final SharedPreferences.Editor editor = sharedPref.edit(); + if (value > 500) { + new AlertDialog.Builder(getActivity()) + .setTitle(R.string.maximum_limit) + .setMessage(R.string.maximum_limit_alert) + .setPositiveButton(android.R.string.yes, (dialog, which) -> {}) + .setIcon(android.R.drawable.ic_dialog_alert) + .show(); + editor.putInt(Prefs.UPLOADS_SHOWING, 500); + editor.putBoolean(Prefs.IS_CONTRIBUTION_COUNT_CHANGED,true); + uploadLimit.setSummary(500 + ""); + uploadLimit.setText(500 + ""); + } else { + editor.putInt(Prefs.UPLOADS_SHOWING, Integer.parseInt(newValue.toString())); + editor.putBoolean(Prefs.IS_CONTRIBUTION_COUNT_CHANGED,true); + uploadLimit.setSummary(newValue.toString()); } - + editor.apply(); + return true; }); diff --git a/app/src/main/java/fr/free/nrw/commons/theme/NavigationBaseActivity.java b/app/src/main/java/fr/free/nrw/commons/theme/NavigationBaseActivity.java index a9c27e5e3..af0d38243 100644 --- a/app/src/main/java/fr/free/nrw/commons/theme/NavigationBaseActivity.java +++ b/app/src/main/java/fr/free/nrw/commons/theme/NavigationBaseActivity.java @@ -3,6 +3,7 @@ package fr.free.nrw.commons.theme; import android.content.ActivityNotFoundException; import android.content.DialogInterface; import android.content.Intent; +import android.net.Uri; import android.support.annotation.NonNull; import android.support.design.widget.NavigationView; import android.support.v4.widget.DrawerLayout; @@ -55,12 +56,7 @@ public class NavigationBaseActivity extends BaseActivity public void initBackButton() { int backStackEntryCount = getSupportFragmentManager().getBackStackEntryCount(); toggle.setDrawerIndicatorEnabled(backStackEntryCount == 0); - toggle.setToolbarNavigationClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - onBackPressed(); - } - }); + toggle.setToolbarNavigationClickListener(v -> onBackPressed()); } public void initBack() { @@ -114,29 +110,29 @@ public class NavigationBaseActivity extends BaseActivity Toast.makeText(this, R.string.no_email_client, Toast.LENGTH_SHORT).show(); } return true; + case R.id.action_developer_plans: + drawerLayout.closeDrawer(navigationView); + // Go to the page + Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri + .parse(getResources() + .getString(R.string.feedback_page_url))); + startActivity(browserIntent); + return true; case R.id.action_logout: new AlertDialog.Builder(this) .setMessage(R.string.logout_verification) .setCancelable(false) - .setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - ((CommonsApplication) getApplicationContext()) - .clearApplicationData(NavigationBaseActivity.this); - Intent nearbyIntent = new Intent( - NavigationBaseActivity.this, LoginActivity.class); - nearbyIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK); - nearbyIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - startActivity(nearbyIntent); - finish(); - } - }) - .setNegativeButton(R.string.no, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - dialog.cancel(); - } + .setPositiveButton(R.string.yes, (dialog, which) -> { + ((CommonsApplication) getApplicationContext()) + .clearApplicationData(NavigationBaseActivity.this); + Intent nearbyIntent = new Intent( + NavigationBaseActivity.this, LoginActivity.class); + nearbyIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK); + nearbyIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + startActivity(nearbyIntent); + finish(); }) + .setNegativeButton(R.string.no, (dialog, which) -> dialog.cancel()) .show(); return true; default: diff --git a/app/src/main/java/fr/free/nrw/commons/ui/widget/HtmlTextView.java b/app/src/main/java/fr/free/nrw/commons/ui/widget/HtmlTextView.java index e0924505c..5afa5cac3 100644 --- a/app/src/main/java/fr/free/nrw/commons/ui/widget/HtmlTextView.java +++ b/app/src/main/java/fr/free/nrw/commons/ui/widget/HtmlTextView.java @@ -19,4 +19,8 @@ public class HtmlTextView extends AppCompatTextView { setMovementMethod(LinkMovementMethod.getInstance()); setText(Utils.fromHtml(getText().toString())); } + + public void setHtmlText(String newText) { + setText(Utils.fromHtml(newText)); + } } diff --git a/app/src/main/java/fr/free/nrw/commons/upload/ExistingFileAsync.java b/app/src/main/java/fr/free/nrw/commons/upload/ExistingFileAsync.java index cacc75596..09fed56ea 100644 --- a/app/src/main/java/fr/free/nrw/commons/upload/ExistingFileAsync.java +++ b/app/src/main/java/fr/free/nrw/commons/upload/ExistingFileAsync.java @@ -72,21 +72,13 @@ public class ExistingFileAsync extends AsyncTask { AlertDialog.Builder builder = new AlertDialog.Builder(context); builder.setMessage(R.string.file_exists) .setTitle(R.string.warning); - builder.setPositiveButton(R.string.no, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int id) { - //Go back to ContributionsActivity - Intent intent = new Intent(context, ContributionsActivity.class); - context.startActivity(intent); - callback.onResult(Result.DUPLICATE_CANCELLED); - } - }); - builder.setNegativeButton(R.string.yes, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int id) { - callback.onResult(Result.DUPLICATE_PROCEED); - } + builder.setPositiveButton(R.string.no, (dialog, id) -> { + //Go back to ContributionsActivity + Intent intent = new Intent(context, ContributionsActivity.class); + context.startActivity(intent); + callback.onResult(Result.DUPLICATE_CANCELLED); }); + builder.setNegativeButton(R.string.yes, (dialog, id) -> callback.onResult(Result.DUPLICATE_PROCEED)); AlertDialog dialog = builder.create(); dialog.show(); diff --git a/app/src/main/java/fr/free/nrw/commons/upload/MultipleShareActivity.java b/app/src/main/java/fr/free/nrw/commons/upload/MultipleShareActivity.java index d7c807777..1ab00c88f 100644 --- a/app/src/main/java/fr/free/nrw/commons/upload/MultipleShareActivity.java +++ b/app/src/main/java/fr/free/nrw/commons/upload/MultipleShareActivity.java @@ -11,6 +11,7 @@ import android.database.DataSetObserver; import android.net.Uri; import android.os.Build; import android.os.Bundle; +import android.support.annotation.NonNull; import android.support.v4.app.ActivityCompat; import android.support.v4.app.FragmentManager; import android.support.v4.content.ContextCompat; @@ -28,6 +29,7 @@ import fr.free.nrw.commons.Media; import fr.free.nrw.commons.R; import fr.free.nrw.commons.auth.AuthenticatedActivity; import fr.free.nrw.commons.category.CategorizationFragment; +import fr.free.nrw.commons.category.OnCategoriesSaveHandler; import fr.free.nrw.commons.contributions.Contribution; import fr.free.nrw.commons.media.MediaDetailPagerFragment; import fr.free.nrw.commons.modifications.CategoryModifier; @@ -43,7 +45,7 @@ public class MultipleShareActivity AdapterView.OnItemClickListener, FragmentManager.OnBackStackChangedListener, MultipleUploadListFragment.OnMultipleUploadInitiatedHandler, - CategorizationFragment.OnCategoriesSaveHandler { + OnCategoriesSaveHandler { private CommonsApplication app; private ArrayList photosList = null; @@ -104,7 +106,7 @@ public class MultipleShareActivity } @Override - public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { + public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { if (requestCode == 1 && grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { multipleUploadBegins(); } @@ -125,19 +127,16 @@ public class MultipleShareActivity Contribution up = photosList.get(i); final int uploadCount = i + 1; // Goddamn Java - uploadController.startUpload(up, new UploadController.ContributionUploadProgress() { - @Override - public void onUploadStarted(Contribution contribution) { - dialog.setProgress(uploadCount); - if(uploadCount == photosList.size()) { - dialog.dismiss(); - Toast startingToast = Toast.makeText( - CommonsApplication.getInstance(), - R.string.uploading_started, - Toast.LENGTH_LONG - ); - startingToast.show(); - } + uploadController.startUpload(up, contribution -> { + dialog.setProgress(uploadCount); + if (uploadCount == photosList.size()) { + dialog.dismiss(); + Toast startingToast = Toast.makeText( + CommonsApplication.getInstance(), + R.string.uploading_started, + Toast.LENGTH_LONG + ); + startingToast.show(); } }); } diff --git a/app/src/main/java/fr/free/nrw/commons/upload/MwVolleyApi.java b/app/src/main/java/fr/free/nrw/commons/upload/MwVolleyApi.java index 666b8cb31..f515f2d0c 100644 --- a/app/src/main/java/fr/free/nrw/commons/upload/MwVolleyApi.java +++ b/app/src/main/java/fr/free/nrw/commons/upload/MwVolleyApi.java @@ -57,7 +57,7 @@ public class MwVolleyApi { Timber.d("URL: %s", apiUrl); JsonRequest request = new QueryRequest(apiUrl, - new LogResponseListener(), new LogResponseErrorListener()); + new LogResponseListener<>(), new LogResponseErrorListener()); getQueue().add(request); } diff --git a/app/src/main/java/fr/free/nrw/commons/upload/ShareActivity.java b/app/src/main/java/fr/free/nrw/commons/upload/ShareActivity.java index 7b9111841..1ce86a86a 100644 --- a/app/src/main/java/fr/free/nrw/commons/upload/ShareActivity.java +++ b/app/src/main/java/fr/free/nrw/commons/upload/ShareActivity.java @@ -9,6 +9,7 @@ import android.os.Build; import android.os.Bundle; import android.os.Environment; import android.os.ParcelFileDescriptor; +import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.annotation.RequiresApi; import android.support.design.widget.Snackbar; @@ -36,6 +37,7 @@ import fr.free.nrw.commons.R; import fr.free.nrw.commons.Utils; import fr.free.nrw.commons.auth.AuthenticatedActivity; import fr.free.nrw.commons.category.CategorizationFragment; +import fr.free.nrw.commons.category.OnCategoriesSaveHandler; import fr.free.nrw.commons.contributions.Contribution; import fr.free.nrw.commons.modifications.CategoryModifier; import fr.free.nrw.commons.modifications.ModificationsContentProvider; @@ -44,6 +46,9 @@ import fr.free.nrw.commons.modifications.TemplateRemoveModifier; import fr.free.nrw.commons.mwapi.EventLog; import timber.log.Timber; +import static fr.free.nrw.commons.upload.ExistingFileAsync.Result.DUPLICATE_PROCEED; +import static fr.free.nrw.commons.upload.ExistingFileAsync.Result.NO_DUPLICATE; + /** * Activity for the title/desc screen after image is selected. Also starts processing image * GPS coordinates or user location (if enabled in Settings) for category suggestions. @@ -51,7 +56,7 @@ import timber.log.Timber; public class ShareActivity extends AuthenticatedActivity implements SingleUploadFragment.OnUploadActionInitiated, - CategorizationFragment.OnCategoriesSaveHandler { + OnCategoriesSaveHandler { private static final int REQUEST_PERM_ON_CREATE_STORAGE = 1; private static final int REQUEST_PERM_ON_CREATE_LOCATION = 2; @@ -133,12 +138,9 @@ public class ShareActivity Timber.d("Cache the categories found"); } - uploadController.startUpload(title, mediaUri, description, mimeType, source, decimalCoords, new UploadController.ContributionUploadProgress() { - @Override - public void onUploadStarted(Contribution contribution) { - ShareActivity.this.contribution = contribution; - showPostUpload(); - } + uploadController.startUpload(title, mediaUri, description, mimeType, source, decimalCoords, c -> { + ShareActivity.this.contribution = c; + showPostUpload(); }); } @@ -317,7 +319,7 @@ public class ShareActivity @Override public void onRequestPermissionsResult(int requestCode, - String[] permissions, int[] grantResults) { + @NonNull String[] permissions, @NonNull int[] grantResults) { switch (requestCode) { case REQUEST_PERM_ON_CREATE_STORAGE: { if (grantResults.length >= 1 @@ -379,14 +381,10 @@ public class ShareActivity Timber.d("File SHA1 is: %s", fileSHA1); ExistingFileAsync fileAsyncTask = - new ExistingFileAsync(fileSHA1, this, new ExistingFileAsync.Callback() { - @Override - public void onResult(ExistingFileAsync.Result result) { - Timber.d("%s duplicate check: %s", mediaUri.toString(), result); - duplicateCheckPassed = - result == ExistingFileAsync.Result.DUPLICATE_PROCEED - || result == ExistingFileAsync.Result.NO_DUPLICATE; - } + new ExistingFileAsync(fileSHA1, this, result -> { + Timber.d("%s duplicate check: %s", mediaUri.toString(), result); + duplicateCheckPassed = (result == DUPLICATE_PROCEED + || result == NO_DUPLICATE); }); fileAsyncTask.execute(); } catch (IOException e) { @@ -401,17 +399,12 @@ public class ShareActivity } } - private Snackbar requestPermissionUsingSnackBar( - String rationale, final String[] perms, final int code) { + private Snackbar requestPermissionUsingSnackBar(String rationale, + final String[] perms, + final int code) { Snackbar snackbar = Snackbar.make(findViewById(android.R.id.content), rationale, - Snackbar.LENGTH_INDEFINITE) - .setAction(R.string.ok, new View.OnClickListener() { - @Override - public void onClick(View view) { - ActivityCompat.requestPermissions(ShareActivity.this, - perms, code); - } - }); + Snackbar.LENGTH_INDEFINITE).setAction(R.string.ok, + view -> ActivityCompat.requestPermissions(ShareActivity.this, perms, code)); snackbar.show(); return snackbar; } diff --git a/app/src/main/java/fr/free/nrw/commons/upload/UploadService.java b/app/src/main/java/fr/free/nrw/commons/upload/UploadService.java index 1165d85fe..f6e4ee6a2 100644 --- a/app/src/main/java/fr/free/nrw/commons/upload/UploadService.java +++ b/app/src/main/java/fr/free/nrw/commons/upload/UploadService.java @@ -86,12 +86,12 @@ public class UploadService extends HandlerService { @Override public void onProgress(long transferred, long total) { Timber.d("Uploaded %d of %d", transferred, total); - if(!notificationTitleChanged) { + if (!notificationTitleChanged) { curProgressNotification.setContentTitle(notificationProgressTitle); notificationTitleChanged = true; contribution.setState(Contribution.STATE_IN_PROGRESS); } - if(transferred == total) { + if (transferred == total) { // Completed! curProgressNotification.setContentTitle(notificationFinishingTitle); curProgressNotification.setProgress(0, 100, true); @@ -124,7 +124,7 @@ public class UploadService extends HandlerService { @Override protected void handle(int what, Contribution contribution) { - switch(what) { + switch (what) { case ACTION_UPLOAD_FILE: //FIXME: Google Photos bug uploadContribution(contribution); @@ -162,7 +162,7 @@ public class UploadService extends HandlerService { @Override public int onStartCommand(Intent intent, int flags, int startId) { - if(intent.getAction().equals(ACTION_START_SERVICE) && freshStart) { + if (intent.getAction().equals(ACTION_START_SERVICE) && freshStart) { ContentValues failedValues = new ContentValues(); failedValues.put(Contribution.Table.COLUMN_STATE, Contribution.STATE_FAILED); @@ -189,7 +189,7 @@ public class UploadService extends HandlerService { try { //FIXME: Google Photos bug file = this.getContentResolver().openInputStream(contribution.getLocalUri()); - } catch(FileNotFoundException e) { + } catch (FileNotFoundException e) { Timber.d("File not found"); Toast fileNotFound = Toast.makeText(this, R.string.upload_failed, Toast.LENGTH_LONG); fileNotFound.show(); @@ -220,9 +220,9 @@ public class UploadService extends HandlerService { filename = findUniqueFilename(filename); unfinishedUploads.add(filename); } - if(!api.validateLogin()) { + if (!api.validateLogin()) { // Need to revalidate! - if(app.revalidateAuthToken()) { + if (app.revalidateAuthToken()) { Timber.d("Successfully revalidated token!"); } else { Timber.d("Unable to revalidate :("); @@ -245,7 +245,7 @@ public class UploadService extends HandlerService { curProgressNotification = null; String resultStatus = uploadResult.getResultStatus(); - if(!resultStatus.equals("Success")) { + if (!resultStatus.equals("Success")) { showFailedNotification(contribution); EventLog.schema(CommonsApplication.EVENT_UPLOAD_ATTEMPT) .param("username", app.getCurrentAccount().name) @@ -269,15 +269,15 @@ public class UploadService extends HandlerService { .param("result", "success") .log(); } - } catch(IOException e) { + } catch (IOException e) { Timber.d("I have a network fuckup"); showFailedNotification(contribution); } finally { - if ( filename != null ) { + if (filename != null) { unfinishedUploads.remove(filename); } toUpload--; - if(toUpload == 0) { + if (toUpload == 0) { // Sync modifications right after all uplaods are processed ContentResolver.requestSync((CommonsApplication.getInstance()).getCurrentAccount(), ModificationsContentProvider.AUTHORITY, new Bundle()); stopForeground(true); @@ -287,7 +287,7 @@ public class UploadService extends HandlerService { @SuppressLint("StringFormatInvalid") private void showFailedNotification(Contribution contribution) { - Notification failureNotification = new NotificationCompat.Builder(this).setAutoCancel(true) + Notification failureNotification = new NotificationCompat.Builder(this).setAutoCancel(true) .setSmallIcon(R.drawable.ic_launcher) .setAutoCancel(true) .setContentIntent(PendingIntent.getActivity(this, 0, new Intent(this, ContributionsActivity.class), 0)) @@ -304,7 +304,7 @@ public class UploadService extends HandlerService { private String findUniqueFilename(String fileName) throws IOException { MediaWikiApi api = app.getMWApi(); String sequenceFileName; - for ( int sequenceNumber = 1; true; sequenceNumber++ ) { + for (int sequenceNumber = 1; true; sequenceNumber++) { if (sequenceNumber == 1) { sequenceFileName = fileName; } else { @@ -318,9 +318,8 @@ public class UploadService extends HandlerService { sequenceFileName = regexMatcher.replaceAll("$1 " + sequenceNumber + "$2"); } } - if ( api.fileExistsWithName(sequenceFileName) || unfinishedUploads.contains(sequenceFileName) ) { - continue; - } else { + if (!api.fileExistsWithName(sequenceFileName) + && !unfinishedUploads.contains(sequenceFileName)) { break; } } diff --git a/app/src/main/java/fr/free/nrw/commons/utils/ExecutorUtils.java b/app/src/main/java/fr/free/nrw/commons/utils/ExecutorUtils.java index 2cb93a058..df67cfea7 100644 --- a/app/src/main/java/fr/free/nrw/commons/utils/ExecutorUtils.java +++ b/app/src/main/java/fr/free/nrw/commons/utils/ExecutorUtils.java @@ -7,14 +7,11 @@ import java.util.concurrent.Executor; public class ExecutorUtils { - private static final Executor uiExecutor = new Executor() { - @Override - public void execute(Runnable command) { - if (Looper.myLooper() == Looper.getMainLooper()) { - command.run(); - } else { - new Handler(Looper.getMainLooper()).post(command); - } + private static final Executor uiExecutor = command -> { + if (Looper.myLooper() == Looper.getMainLooper()) { + command.run(); + } else { + new Handler(Looper.getMainLooper()).post(command); } }; diff --git a/app/src/main/java/fr/free/nrw/commons/utils/FileUtils.java b/app/src/main/java/fr/free/nrw/commons/utils/FileUtils.java index 0596327e3..4d50f32aa 100644 --- a/app/src/main/java/fr/free/nrw/commons/utils/FileUtils.java +++ b/app/src/main/java/fr/free/nrw/commons/utils/FileUtils.java @@ -42,8 +42,8 @@ public class FileUtils { if (file != null) { if (file.isDirectory()) { String[] children = file.list(); - for (int i = 0; i < children.length; i++) { - deletedAll = deleteFile(new File(file, children[i])) && deletedAll; + for (String child : children) { + deletedAll = deleteFile(new File(file, child)) && deletedAll; } } else { deletedAll = file.delete(); diff --git a/app/src/main/java/fr/free/nrw/commons/utils/UiUtils.java b/app/src/main/java/fr/free/nrw/commons/utils/UiUtils.java new file mode 100644 index 000000000..b2c073850 --- /dev/null +++ b/app/src/main/java/fr/free/nrw/commons/utils/UiUtils.java @@ -0,0 +1,22 @@ +package fr.free.nrw.commons.utils; + +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.support.graphics.drawable.VectorDrawableCompat; + +public class UiUtils { + + /** + * Draws a vectorial image onto a bitmap. + * @param vectorDrawable vectorial image + * @return bitmap representation of the vectorial image + */ + public static Bitmap getBitmap(VectorDrawableCompat vectorDrawable) { + Bitmap bitmap = Bitmap.createBitmap(vectorDrawable.getIntrinsicWidth(), + vectorDrawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888); + Canvas canvas = new Canvas(bitmap); + vectorDrawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight()); + vectorDrawable.draw(canvas); + return bitmap; + } +} diff --git a/app/src/main/res/drawable-hdpi/ic_exit_to_app_black_24dp.png b/app/src/main/res/drawable-hdpi/ic_exit_to_app_black_24dp.png deleted file mode 100644 index ad0f63e5b..000000000 Binary files a/app/src/main/res/drawable-hdpi/ic_exit_to_app_black_24dp.png and /dev/null differ diff --git a/app/src/main/res/drawable-hdpi/ic_feedback_black_24dp.png b/app/src/main/res/drawable-hdpi/ic_feedback_black_24dp.png deleted file mode 100644 index f03168559..000000000 Binary files a/app/src/main/res/drawable-hdpi/ic_feedback_black_24dp.png and /dev/null differ diff --git a/app/src/main/res/drawable-hdpi/ic_file_upload_black_24dp.png b/app/src/main/res/drawable-hdpi/ic_file_upload_black_24dp.png deleted file mode 100644 index 5e5b9fc4a..000000000 Binary files a/app/src/main/res/drawable-hdpi/ic_file_upload_black_24dp.png and /dev/null differ diff --git a/app/src/main/res/drawable-hdpi/ic_home_black_24dp.png b/app/src/main/res/drawable-hdpi/ic_home_black_24dp.png deleted file mode 100644 index 9f61d7bf2..000000000 Binary files a/app/src/main/res/drawable-hdpi/ic_home_black_24dp.png and /dev/null differ diff --git a/app/src/main/res/drawable-hdpi/ic_info_outline_black_24dp.png b/app/src/main/res/drawable-hdpi/ic_info_outline_black_24dp.png deleted file mode 100644 index 4b5ab06e1..000000000 Binary files a/app/src/main/res/drawable-hdpi/ic_info_outline_black_24dp.png and /dev/null differ diff --git a/app/src/main/res/drawable-hdpi/ic_list_white_24dp.png b/app/src/main/res/drawable-hdpi/ic_list_white_24dp.png deleted file mode 100644 index f8f7e7dda..000000000 Binary files a/app/src/main/res/drawable-hdpi/ic_list_white_24dp.png and /dev/null differ diff --git a/app/src/main/res/drawable-hdpi/ic_location_on_black_24dp.png b/app/src/main/res/drawable-hdpi/ic_location_on_black_24dp.png deleted file mode 100644 index df1f34062..000000000 Binary files a/app/src/main/res/drawable-hdpi/ic_location_on_black_24dp.png and /dev/null differ diff --git a/app/src/main/res/drawable-hdpi/ic_map_white_24dp.png b/app/src/main/res/drawable-hdpi/ic_map_white_24dp.png deleted file mode 100644 index b7631d7d7..000000000 Binary files a/app/src/main/res/drawable-hdpi/ic_map_white_24dp.png and /dev/null differ diff --git a/app/src/main/res/drawable-hdpi/ic_photo_black_24dp.png b/app/src/main/res/drawable-hdpi/ic_photo_black_24dp.png deleted file mode 100644 index 52c788746..000000000 Binary files a/app/src/main/res/drawable-hdpi/ic_photo_black_24dp.png and /dev/null differ diff --git a/app/src/main/res/drawable-hdpi/ic_photo_camera_white_24dp.png b/app/src/main/res/drawable-hdpi/ic_photo_camera_white_24dp.png deleted file mode 100644 index 497c88ca8..000000000 Binary files a/app/src/main/res/drawable-hdpi/ic_photo_camera_white_24dp.png and /dev/null differ diff --git a/app/src/main/res/drawable-hdpi/ic_photo_white_24dp.png b/app/src/main/res/drawable-hdpi/ic_photo_white_24dp.png deleted file mode 100644 index b414cf5b6..000000000 Binary files a/app/src/main/res/drawable-hdpi/ic_photo_white_24dp.png and /dev/null differ diff --git a/app/src/main/res/drawable-hdpi/ic_save_white_24dp.png b/app/src/main/res/drawable-hdpi/ic_save_white_24dp.png deleted file mode 100644 index dd3f10664..000000000 Binary files a/app/src/main/res/drawable-hdpi/ic_save_white_24dp.png and /dev/null differ diff --git a/app/src/main/res/drawable-hdpi/ic_send_white_24dp.png b/app/src/main/res/drawable-hdpi/ic_send_white_24dp.png deleted file mode 100644 index 0f0017201..000000000 Binary files a/app/src/main/res/drawable-hdpi/ic_send_white_24dp.png and /dev/null differ diff --git a/app/src/main/res/drawable-hdpi/ic_settings_black_24dp.png b/app/src/main/res/drawable-hdpi/ic_settings_black_24dp.png deleted file mode 100644 index acf1ddf85..000000000 Binary files a/app/src/main/res/drawable-hdpi/ic_settings_black_24dp.png and /dev/null differ diff --git a/app/src/main/res/drawable-hdpi/ic_undo_white_24dp.png b/app/src/main/res/drawable-hdpi/ic_undo_white_24dp.png deleted file mode 100644 index eb7522cdb..000000000 Binary files a/app/src/main/res/drawable-hdpi/ic_undo_white_24dp.png and /dev/null differ diff --git a/app/src/main/res/drawable-ldrtl-hdpi/ic_send_white_24dp.png b/app/src/main/res/drawable-ldrtl-hdpi/ic_send_white_24dp.png deleted file mode 100644 index 0cc14e754..000000000 Binary files a/app/src/main/res/drawable-ldrtl-hdpi/ic_send_white_24dp.png and /dev/null differ diff --git a/app/src/main/res/drawable-ldrtl-mdpi/ic_send_white_24dp.png b/app/src/main/res/drawable-ldrtl-mdpi/ic_send_white_24dp.png deleted file mode 100644 index d5fe50b36..000000000 Binary files a/app/src/main/res/drawable-ldrtl-mdpi/ic_send_white_24dp.png and /dev/null differ diff --git a/app/src/main/res/drawable-ldrtl-xhdpi/ic_send_white_24dp.png b/app/src/main/res/drawable-ldrtl-xhdpi/ic_send_white_24dp.png deleted file mode 100644 index 4735a7d71..000000000 Binary files a/app/src/main/res/drawable-ldrtl-xhdpi/ic_send_white_24dp.png and /dev/null differ diff --git a/app/src/main/res/drawable-ldrtl-xxhdpi/ic_send_white_24dp.png b/app/src/main/res/drawable-ldrtl-xxhdpi/ic_send_white_24dp.png deleted file mode 100644 index 9f64e5b38..000000000 Binary files a/app/src/main/res/drawable-ldrtl-xxhdpi/ic_send_white_24dp.png and /dev/null differ diff --git a/app/src/main/res/drawable-ldrtl-xxxhdpi/ic_send_white_24dp.png b/app/src/main/res/drawable-ldrtl-xxxhdpi/ic_send_white_24dp.png deleted file mode 100644 index 76d135b90..000000000 Binary files a/app/src/main/res/drawable-ldrtl-xxxhdpi/ic_send_white_24dp.png and /dev/null differ diff --git a/app/src/main/res/drawable-mdpi/custom_map_marker.png b/app/src/main/res/drawable-mdpi/custom_map_marker.png deleted file mode 100644 index 0634167c5..000000000 Binary files a/app/src/main/res/drawable-mdpi/custom_map_marker.png and /dev/null differ diff --git a/app/src/main/res/drawable-mdpi/ic_exit_to_app_black_24dp.png b/app/src/main/res/drawable-mdpi/ic_exit_to_app_black_24dp.png deleted file mode 100644 index dee407b59..000000000 Binary files a/app/src/main/res/drawable-mdpi/ic_exit_to_app_black_24dp.png and /dev/null differ diff --git a/app/src/main/res/drawable-mdpi/ic_feedback_black_24dp.png b/app/src/main/res/drawable-mdpi/ic_feedback_black_24dp.png deleted file mode 100644 index 8be6849cb..000000000 Binary files a/app/src/main/res/drawable-mdpi/ic_feedback_black_24dp.png and /dev/null differ diff --git a/app/src/main/res/drawable-mdpi/ic_file_upload_black_24dp.png b/app/src/main/res/drawable-mdpi/ic_file_upload_black_24dp.png deleted file mode 100644 index c5f2954bd..000000000 Binary files a/app/src/main/res/drawable-mdpi/ic_file_upload_black_24dp.png and /dev/null differ diff --git a/app/src/main/res/drawable-mdpi/ic_home_black_24dp.png b/app/src/main/res/drawable-mdpi/ic_home_black_24dp.png deleted file mode 100644 index 9f2c3d2f7..000000000 Binary files a/app/src/main/res/drawable-mdpi/ic_home_black_24dp.png and /dev/null differ diff --git a/app/src/main/res/drawable-mdpi/ic_info_outline_black_24dp.png b/app/src/main/res/drawable-mdpi/ic_info_outline_black_24dp.png deleted file mode 100644 index e0c9fe0eb..000000000 Binary files a/app/src/main/res/drawable-mdpi/ic_info_outline_black_24dp.png and /dev/null differ diff --git a/app/src/main/res/drawable-mdpi/ic_list_white_24dp.png b/app/src/main/res/drawable-mdpi/ic_list_white_24dp.png deleted file mode 100644 index 15d8fc2bb..000000000 Binary files a/app/src/main/res/drawable-mdpi/ic_list_white_24dp.png and /dev/null differ diff --git a/app/src/main/res/drawable-mdpi/ic_location_on_black_24dp.png b/app/src/main/res/drawable-mdpi/ic_location_on_black_24dp.png deleted file mode 100644 index 92a073827..000000000 Binary files a/app/src/main/res/drawable-mdpi/ic_location_on_black_24dp.png and /dev/null differ diff --git a/app/src/main/res/drawable-mdpi/ic_map_white_24dp.png b/app/src/main/res/drawable-mdpi/ic_map_white_24dp.png deleted file mode 100644 index 4edb178dc..000000000 Binary files a/app/src/main/res/drawable-mdpi/ic_map_white_24dp.png and /dev/null differ diff --git a/app/src/main/res/drawable-mdpi/ic_photo_black_24dp.png b/app/src/main/res/drawable-mdpi/ic_photo_black_24dp.png deleted file mode 100644 index 377ce1331..000000000 Binary files a/app/src/main/res/drawable-mdpi/ic_photo_black_24dp.png and /dev/null differ diff --git a/app/src/main/res/drawable-mdpi/ic_photo_camera_white_24dp.png b/app/src/main/res/drawable-mdpi/ic_photo_camera_white_24dp.png deleted file mode 100644 index e83052200..000000000 Binary files a/app/src/main/res/drawable-mdpi/ic_photo_camera_white_24dp.png and /dev/null differ diff --git a/app/src/main/res/drawable-mdpi/ic_photo_white_24dp.png b/app/src/main/res/drawable-mdpi/ic_photo_white_24dp.png deleted file mode 100644 index d474bd577..000000000 Binary files a/app/src/main/res/drawable-mdpi/ic_photo_white_24dp.png and /dev/null differ diff --git a/app/src/main/res/drawable-mdpi/ic_save_white_24dp.png b/app/src/main/res/drawable-mdpi/ic_save_white_24dp.png deleted file mode 100644 index 015062ed3..000000000 Binary files a/app/src/main/res/drawable-mdpi/ic_save_white_24dp.png and /dev/null differ diff --git a/app/src/main/res/drawable-mdpi/ic_send_white_24dp.png b/app/src/main/res/drawable-mdpi/ic_send_white_24dp.png deleted file mode 100644 index 048d3eb29..000000000 Binary files a/app/src/main/res/drawable-mdpi/ic_send_white_24dp.png and /dev/null differ diff --git a/app/src/main/res/drawable-mdpi/ic_settings_black_24dp.png b/app/src/main/res/drawable-mdpi/ic_settings_black_24dp.png deleted file mode 100644 index c59419c02..000000000 Binary files a/app/src/main/res/drawable-mdpi/ic_settings_black_24dp.png and /dev/null differ diff --git a/app/src/main/res/drawable-mdpi/ic_undo_white_24dp.png b/app/src/main/res/drawable-mdpi/ic_undo_white_24dp.png deleted file mode 100644 index 294b57578..000000000 Binary files a/app/src/main/res/drawable-mdpi/ic_undo_white_24dp.png and /dev/null differ diff --git a/app/src/main/res/drawable-xhdpi/ic_exit_to_app_black_24dp.png b/app/src/main/res/drawable-xhdpi/ic_exit_to_app_black_24dp.png deleted file mode 100644 index 5a536d57c..000000000 Binary files a/app/src/main/res/drawable-xhdpi/ic_exit_to_app_black_24dp.png and /dev/null differ diff --git a/app/src/main/res/drawable-xhdpi/ic_feedback_black_24dp.png b/app/src/main/res/drawable-xhdpi/ic_feedback_black_24dp.png deleted file mode 100644 index 63bec2331..000000000 Binary files a/app/src/main/res/drawable-xhdpi/ic_feedback_black_24dp.png and /dev/null differ diff --git a/app/src/main/res/drawable-xhdpi/ic_file_upload_black_24dp.png b/app/src/main/res/drawable-xhdpi/ic_file_upload_black_24dp.png deleted file mode 100644 index 41694c101..000000000 Binary files a/app/src/main/res/drawable-xhdpi/ic_file_upload_black_24dp.png and /dev/null differ diff --git a/app/src/main/res/drawable-xhdpi/ic_home_black_24dp.png b/app/src/main/res/drawable-xhdpi/ic_home_black_24dp.png deleted file mode 100644 index dcdcfc0a8..000000000 Binary files a/app/src/main/res/drawable-xhdpi/ic_home_black_24dp.png and /dev/null differ diff --git a/app/src/main/res/drawable-xhdpi/ic_info_outline_black_24dp.png b/app/src/main/res/drawable-xhdpi/ic_info_outline_black_24dp.png deleted file mode 100644 index b706f0d06..000000000 Binary files a/app/src/main/res/drawable-xhdpi/ic_info_outline_black_24dp.png and /dev/null differ diff --git a/app/src/main/res/drawable-xhdpi/ic_list_white_24dp.png b/app/src/main/res/drawable-xhdpi/ic_list_white_24dp.png deleted file mode 100644 index 2b7253975..000000000 Binary files a/app/src/main/res/drawable-xhdpi/ic_list_white_24dp.png and /dev/null differ diff --git a/app/src/main/res/drawable-xhdpi/ic_location_on_black_24dp.png b/app/src/main/res/drawable-xhdpi/ic_location_on_black_24dp.png deleted file mode 100644 index b2696b6d4..000000000 Binary files a/app/src/main/res/drawable-xhdpi/ic_location_on_black_24dp.png and /dev/null differ diff --git a/app/src/main/res/drawable-xhdpi/ic_map_white_24dp.png b/app/src/main/res/drawable-xhdpi/ic_map_white_24dp.png deleted file mode 100644 index 301162e71..000000000 Binary files a/app/src/main/res/drawable-xhdpi/ic_map_white_24dp.png and /dev/null differ diff --git a/app/src/main/res/drawable-xhdpi/ic_photo_black_24dp.png b/app/src/main/res/drawable-xhdpi/ic_photo_black_24dp.png deleted file mode 100644 index 6b7cd7838..000000000 Binary files a/app/src/main/res/drawable-xhdpi/ic_photo_black_24dp.png and /dev/null differ diff --git a/app/src/main/res/drawable-xhdpi/ic_photo_camera_white_24dp.png b/app/src/main/res/drawable-xhdpi/ic_photo_camera_white_24dp.png deleted file mode 100644 index be9fb226a..000000000 Binary files a/app/src/main/res/drawable-xhdpi/ic_photo_camera_white_24dp.png and /dev/null differ diff --git a/app/src/main/res/drawable-xhdpi/ic_photo_white_24dp.png b/app/src/main/res/drawable-xhdpi/ic_photo_white_24dp.png deleted file mode 100644 index 2642b9e09..000000000 Binary files a/app/src/main/res/drawable-xhdpi/ic_photo_white_24dp.png and /dev/null differ diff --git a/app/src/main/res/drawable-xhdpi/ic_save_white_24dp.png b/app/src/main/res/drawable-xhdpi/ic_save_white_24dp.png deleted file mode 100644 index adda09575..000000000 Binary files a/app/src/main/res/drawable-xhdpi/ic_save_white_24dp.png and /dev/null differ diff --git a/app/src/main/res/drawable-xhdpi/ic_send_white_24dp.png b/app/src/main/res/drawable-xhdpi/ic_send_white_24dp.png deleted file mode 100644 index ef59e7767..000000000 Binary files a/app/src/main/res/drawable-xhdpi/ic_send_white_24dp.png and /dev/null differ diff --git a/app/src/main/res/drawable-xhdpi/ic_settings_black_24dp.png b/app/src/main/res/drawable-xhdpi/ic_settings_black_24dp.png deleted file mode 100644 index e84e188a1..000000000 Binary files a/app/src/main/res/drawable-xhdpi/ic_settings_black_24dp.png and /dev/null differ diff --git a/app/src/main/res/drawable-xhdpi/ic_undo_white_24dp.png b/app/src/main/res/drawable-xhdpi/ic_undo_white_24dp.png deleted file mode 100644 index c4c28d0a4..000000000 Binary files a/app/src/main/res/drawable-xhdpi/ic_undo_white_24dp.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_exit_to_app_black_24dp.png b/app/src/main/res/drawable-xxhdpi/ic_exit_to_app_black_24dp.png deleted file mode 100644 index 53b79d4c7..000000000 Binary files a/app/src/main/res/drawable-xxhdpi/ic_exit_to_app_black_24dp.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_feedback_black_24dp.png b/app/src/main/res/drawable-xxhdpi/ic_feedback_black_24dp.png deleted file mode 100644 index e68ceb906..000000000 Binary files a/app/src/main/res/drawable-xxhdpi/ic_feedback_black_24dp.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_file_upload_black_24dp.png b/app/src/main/res/drawable-xxhdpi/ic_file_upload_black_24dp.png deleted file mode 100644 index bb5d0923b..000000000 Binary files a/app/src/main/res/drawable-xxhdpi/ic_file_upload_black_24dp.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_home_black_24dp.png b/app/src/main/res/drawable-xxhdpi/ic_home_black_24dp.png deleted file mode 100644 index 2e86cc255..000000000 Binary files a/app/src/main/res/drawable-xxhdpi/ic_home_black_24dp.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_info_outline_black_24dp.png b/app/src/main/res/drawable-xxhdpi/ic_info_outline_black_24dp.png deleted file mode 100644 index 3847a9fe7..000000000 Binary files a/app/src/main/res/drawable-xxhdpi/ic_info_outline_black_24dp.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_list_white_24dp.png b/app/src/main/res/drawable-xxhdpi/ic_list_white_24dp.png deleted file mode 100644 index 4d2807e4e..000000000 Binary files a/app/src/main/res/drawable-xxhdpi/ic_list_white_24dp.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_location_on_black_24dp.png b/app/src/main/res/drawable-xxhdpi/ic_location_on_black_24dp.png deleted file mode 100644 index 5a21dfae6..000000000 Binary files a/app/src/main/res/drawable-xxhdpi/ic_location_on_black_24dp.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_map_white_24dp.png b/app/src/main/res/drawable-xxhdpi/ic_map_white_24dp.png deleted file mode 100644 index 0c38abeec..000000000 Binary files a/app/src/main/res/drawable-xxhdpi/ic_map_white_24dp.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_photo_black_24dp.png b/app/src/main/res/drawable-xxhdpi/ic_photo_black_24dp.png deleted file mode 100644 index 7297bd5d2..000000000 Binary files a/app/src/main/res/drawable-xxhdpi/ic_photo_black_24dp.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_photo_camera_white_24dp.png b/app/src/main/res/drawable-xxhdpi/ic_photo_camera_white_24dp.png deleted file mode 100644 index c8e69dceb..000000000 Binary files a/app/src/main/res/drawable-xxhdpi/ic_photo_camera_white_24dp.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_photo_white_24dp.png b/app/src/main/res/drawable-xxhdpi/ic_photo_white_24dp.png deleted file mode 100644 index f9f1defa6..000000000 Binary files a/app/src/main/res/drawable-xxhdpi/ic_photo_white_24dp.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_save_white_24dp.png b/app/src/main/res/drawable-xxhdpi/ic_save_white_24dp.png deleted file mode 100644 index 3e0ce1a5f..000000000 Binary files a/app/src/main/res/drawable-xxhdpi/ic_save_white_24dp.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_send_white_24dp.png b/app/src/main/res/drawable-xxhdpi/ic_send_white_24dp.png deleted file mode 100644 index 1bc7552a9..000000000 Binary files a/app/src/main/res/drawable-xxhdpi/ic_send_white_24dp.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_settings_black_24dp.png b/app/src/main/res/drawable-xxhdpi/ic_settings_black_24dp.png deleted file mode 100644 index 3023ff8da..000000000 Binary files a/app/src/main/res/drawable-xxhdpi/ic_settings_black_24dp.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_undo_white_24dp.png b/app/src/main/res/drawable-xxhdpi/ic_undo_white_24dp.png deleted file mode 100644 index 1e1e3d866..000000000 Binary files a/app/src/main/res/drawable-xxhdpi/ic_undo_white_24dp.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_exit_to_app_black_24dp.png b/app/src/main/res/drawable-xxxhdpi/ic_exit_to_app_black_24dp.png deleted file mode 100644 index e30632b6b..000000000 Binary files a/app/src/main/res/drawable-xxxhdpi/ic_exit_to_app_black_24dp.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_feedback_black_24dp.png b/app/src/main/res/drawable-xxxhdpi/ic_feedback_black_24dp.png deleted file mode 100644 index 1343fa837..000000000 Binary files a/app/src/main/res/drawable-xxxhdpi/ic_feedback_black_24dp.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_file_upload_black_24dp.png b/app/src/main/res/drawable-xxxhdpi/ic_file_upload_black_24dp.png deleted file mode 100644 index 9ce5b8a7b..000000000 Binary files a/app/src/main/res/drawable-xxxhdpi/ic_file_upload_black_24dp.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_home_black_24dp.png b/app/src/main/res/drawable-xxxhdpi/ic_home_black_24dp.png deleted file mode 100644 index 04e2b26ff..000000000 Binary files a/app/src/main/res/drawable-xxxhdpi/ic_home_black_24dp.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_info_outline_black_24dp.png b/app/src/main/res/drawable-xxxhdpi/ic_info_outline_black_24dp.png deleted file mode 100644 index c1e2a03a4..000000000 Binary files a/app/src/main/res/drawable-xxxhdpi/ic_info_outline_black_24dp.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_list_white_24dp.png b/app/src/main/res/drawable-xxxhdpi/ic_list_white_24dp.png deleted file mode 100644 index 2a6d3b044..000000000 Binary files a/app/src/main/res/drawable-xxxhdpi/ic_list_white_24dp.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_location_on_black_24dp.png b/app/src/main/res/drawable-xxxhdpi/ic_location_on_black_24dp.png deleted file mode 100644 index 7c2217e46..000000000 Binary files a/app/src/main/res/drawable-xxxhdpi/ic_location_on_black_24dp.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_map_white_24dp.png b/app/src/main/res/drawable-xxxhdpi/ic_map_white_24dp.png deleted file mode 100644 index 0cbfe89e5..000000000 Binary files a/app/src/main/res/drawable-xxxhdpi/ic_map_white_24dp.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_photo_black_24dp.png b/app/src/main/res/drawable-xxxhdpi/ic_photo_black_24dp.png deleted file mode 100644 index ebe206ff7..000000000 Binary files a/app/src/main/res/drawable-xxxhdpi/ic_photo_black_24dp.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_photo_camera_white_24dp.png b/app/src/main/res/drawable-xxxhdpi/ic_photo_camera_white_24dp.png deleted file mode 100644 index 777658e95..000000000 Binary files a/app/src/main/res/drawable-xxxhdpi/ic_photo_camera_white_24dp.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_photo_white_24dp.png b/app/src/main/res/drawable-xxxhdpi/ic_photo_white_24dp.png deleted file mode 100644 index 2ffdb55f2..000000000 Binary files a/app/src/main/res/drawable-xxxhdpi/ic_photo_white_24dp.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_save_white_24dp.png b/app/src/main/res/drawable-xxxhdpi/ic_save_white_24dp.png deleted file mode 100644 index bd80bf1f7..000000000 Binary files a/app/src/main/res/drawable-xxxhdpi/ic_save_white_24dp.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_send_white_24dp.png b/app/src/main/res/drawable-xxxhdpi/ic_send_white_24dp.png deleted file mode 100644 index 6aeaa850b..000000000 Binary files a/app/src/main/res/drawable-xxxhdpi/ic_send_white_24dp.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_settings_black_24dp.png b/app/src/main/res/drawable-xxxhdpi/ic_settings_black_24dp.png deleted file mode 100644 index 476d5c978..000000000 Binary files a/app/src/main/res/drawable-xxxhdpi/ic_settings_black_24dp.png and /dev/null differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_undo_white_24dp.png b/app/src/main/res/drawable-xxxhdpi/ic_undo_white_24dp.png deleted file mode 100644 index 6b10718b9..000000000 Binary files a/app/src/main/res/drawable-xxxhdpi/ic_undo_white_24dp.png and /dev/null differ diff --git a/app/src/main/res/drawable/ic_custom_map_marker.xml b/app/src/main/res/drawable/ic_custom_map_marker.xml new file mode 100644 index 000000000..01b540076 --- /dev/null +++ b/app/src/main/res/drawable/ic_custom_map_marker.xml @@ -0,0 +1,23 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_exit_to_app_black_24dp.xml b/app/src/main/res/drawable/ic_exit_to_app_black_24dp.xml new file mode 100644 index 000000000..6f40d7725 --- /dev/null +++ b/app/src/main/res/drawable/ic_exit_to_app_black_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_feedback_black_24dp.xml b/app/src/main/res/drawable/ic_feedback_black_24dp.xml new file mode 100644 index 000000000..29f9baabd --- /dev/null +++ b/app/src/main/res/drawable/ic_feedback_black_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_help_outline_black_24dp.xml b/app/src/main/res/drawable/ic_help_outline_black_24dp.xml new file mode 100644 index 000000000..e7cf8ea21 --- /dev/null +++ b/app/src/main/res/drawable/ic_help_outline_black_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_black_24dp.xml b/app/src/main/res/drawable/ic_home_black_24dp.xml new file mode 100644 index 000000000..70fb2910c --- /dev/null +++ b/app/src/main/res/drawable/ic_home_black_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_info_outline_black_24dp.xml b/app/src/main/res/drawable/ic_info_outline_black_24dp.xml new file mode 100644 index 000000000..cf53e145c --- /dev/null +++ b/app/src/main/res/drawable/ic_info_outline_black_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_list_white_24dp.xml b/app/src/main/res/drawable/ic_list_white_24dp.xml new file mode 100644 index 000000000..7f5d99c3b --- /dev/null +++ b/app/src/main/res/drawable/ic_list_white_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_location_black_24dp.xml b/app/src/main/res/drawable/ic_location_black_24dp.xml new file mode 100644 index 000000000..ad6431d42 --- /dev/null +++ b/app/src/main/res/drawable/ic_location_black_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_map_white_24dp.xml b/app/src/main/res/drawable/ic_map_white_24dp.xml new file mode 100644 index 000000000..4cb341e6e --- /dev/null +++ b/app/src/main/res/drawable/ic_map_white_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_photo_camera_white_24dp.xml b/app/src/main/res/drawable/ic_photo_camera_white_24dp.xml new file mode 100644 index 000000000..4fa7158a0 --- /dev/null +++ b/app/src/main/res/drawable/ic_photo_camera_white_24dp.xml @@ -0,0 +1,12 @@ + + + + diff --git a/app/src/main/res/drawable/ic_photo_white_24dp.xml b/app/src/main/res/drawable/ic_photo_white_24dp.xml new file mode 100644 index 000000000..0b56f71ae --- /dev/null +++ b/app/src/main/res/drawable/ic_photo_white_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_save_white_24dp.xml b/app/src/main/res/drawable/ic_save_white_24dp.xml new file mode 100644 index 000000000..a7a81a25d --- /dev/null +++ b/app/src/main/res/drawable/ic_save_white_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_send_white_24dp.xml b/app/src/main/res/drawable/ic_send_white_24dp.xml new file mode 100644 index 000000000..78a666de5 --- /dev/null +++ b/app/src/main/res/drawable/ic_send_white_24dp.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_settings_black_24dp.xml b/app/src/main/res/drawable/ic_settings_black_24dp.xml new file mode 100644 index 000000000..ace746c40 --- /dev/null +++ b/app/src/main/res/drawable/ic_settings_black_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_undo_white_24dp.xml b/app/src/main/res/drawable/ic_undo_white_24dp.xml new file mode 100644 index 000000000..d624b8b7e --- /dev/null +++ b/app/src/main/res/drawable/ic_undo_white_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/layout/fragment_categorization.xml b/app/src/main/res/layout/fragment_categorization.xml index a0b9b3c2f..83a8a746a 100644 --- a/app/src/main/res/layout/fragment_categorization.xml +++ b/app/src/main/res/layout/fragment_categorization.xml @@ -60,7 +60,7 @@ android:visibility="gone" /> - + + + diff --git a/app/src/main/res/layout/layout_categories_item.xml b/app/src/main/res/layout/layout_categories_item.xml index f0478c7dc..f9b84fb73 100644 --- a/app/src/main/res/layout/layout_categories_item.xml +++ b/app/src/main/res/layout/layout_categories_item.xml @@ -1,12 +1,12 @@ + android:padding="4dp" + android:theme="@style/DarkAppTheme"> \ No newline at end of file diff --git a/app/src/main/res/menu/drawer.xml b/app/src/main/res/menu/drawer.xml index bf6d3760e..cb6b63ffc 100644 --- a/app/src/main/res/menu/drawer.xml +++ b/app/src/main/res/menu/drawer.xml @@ -7,7 +7,7 @@ + + اكتمال رفع %1$s فشل رفع %1$s انقر لتشاهد - متبقى %d - مرفوعاتي الأخيرة + مرفوعاتي الأخيرة في قائمة الانتظار فشل انتهاء %1$d%% diff --git a/app/src/main/res/values-ast/strings.xml b/app/src/main/res/values-ast/strings.xml index af3286f06..dcee85e89 100644 --- a/app/src/main/res/values-ast/strings.xml +++ b/app/src/main/res/values-ast/strings.xml @@ -75,7 +75,7 @@ Configuración Date d\'alta Tocante a - Software de códigu abiertu lliberáu baxo la <a href=\"https://github.com/commons-app/apps-android-commons/blob/master/COPYING\">Llicencia Apache v2</a>. Wikimedia Commons ya\'l so logotipu son marques rexistraes de la Fundación Wikimedia y utilícense col so permisu. Nun tamos acreditaos pola Fundación Wikimedia nin tamos afiliaos con ella. + Software de códigu abiertu lliberáu baxo la <a href=\"https://github.com/commons-app/apps-android-commons/blob/master/COPYING\">Llicencia Apache v2</a>. %1$s ya\'l so logotipu son marques rexistraes de la Fundación Wikimedia y utilícense col so permisu. Nun tamos acreditaos pola Fundación Wikimedia nin tamos afiliaos con ella. El <a href=\"https://github.com/commons-app/apps-android-commons\">códigu fonte</a> ya\'l <a href=\"https://commons-app.github.io/\">sitiu web</a> tán en GitHub. Crea una nueva <a href=\"https://github.com/commons-app/apps-android-commons/issues\">incidencia en GitHub</a> pa informar de problemes y suxerencies. Wikimedia:Commons-android-strings-about privacy policy/ast <a href=\"https://github.com/commons-app/apps-android-commons/blob/master/CREDITS\">Créditos</a> @@ -149,6 +149,9 @@ Descripción Equí va la descripción del mediu. Posiblemente pué ser llargo enforma, y necesitará espardese per delles llinies. Sicasí, esperamos que se vea guapo. Data d\'unviu + Llicencia + Coordenaes + Nun se dio Faete probador beta Escueye\'l nuesu canal beta en Google Play y ten accesu tempranu a carauterístiques nueves ya igües de fallos Usar Wikidata @@ -187,7 +190,7 @@ Tutorial Los sitios cercanos nun pueden amosase ensin los permisos d\'allugamientu nun s\'atoparon descripciones - Artículu en Commons + Páxina del ficheru en Commons Elementu de WikiData Error al poner les fotos na caché diff --git a/app/src/main/res/values-b+tg+Cyrl/strings.xml b/app/src/main/res/values-b+tg+Cyrl/strings.xml index 138d88bf7..0785618e9 100644 --- a/app/src/main/res/values-b+tg+Cyrl/strings.xml +++ b/app/src/main/res/values-b+tg+Cyrl/strings.xml @@ -53,6 +53,7 @@ CC BY-SA 3.0 (Руминия) CC BY 3.0 CC Zero + Викианбор дорои бисёр файлҳое аст, ки тарафи Википедиа истифода мешаванд. Аксҳои шумо барои таълими одамон аз тамоми ҷаҳон кӯмак мерасонанд. Фикр мекунед дарк кардед? Бале! @@ -60,4 +61,9 @@ Дар ҳоли кушодашавӣ… Ҳеҷ яке интихоб нашудааст Иҷозатномаи ношинос + Иҷозатнома + Координатҳо + Истифодаи Викимаълумот + Элементи Викимаълумот + Хатогӣ ҳангоми кэшкунии тасвир diff --git a/app/src/main/res/values-bn/strings.xml b/app/src/main/res/values-bn/strings.xml index 441f807c8..4c59ee7ce 100644 --- a/app/src/main/res/values-bn/strings.xml +++ b/app/src/main/res/values-bn/strings.xml @@ -148,6 +148,8 @@ বিবরণ মিডিয়ার বিবরণ এখানে যাবে। এই মোটামুটি দীর্ঘ হতে পারে এবং একাধিক লাইনে লিখতে হতে পারে। আমরা আশা করি এটি দেখতে সুন্দর হবে। আপলোডের তারিখ + লাইসেন্স + স্থানাঙ্কসমূহ বিটা টেস্টার হোন উইকিউপাত্ত ব্যবহার করুন (সতর্কতা: এটি নিষ্ক্রিয় করা অধিক পরিমাণে মোবাইল ডেটা খরচ হওয়ার কারণ হতে পারে) @@ -182,6 +184,6 @@ ভূমিকা অবস্থানের অনুমতি ছাড়া কাছাকাছি জায়গাগুলি প্রদর্শন করা যাবে না কোন বিবরণ পাওয়া যায়নি - কমন্স নিবন্ধ + কমন্সে ফাইলের পাতা উইকিউপাত্ত পদ diff --git a/app/src/main/res/values-br/strings.xml b/app/src/main/res/values-br/strings.xml index 3340f59c8..ae698f6a9 100644 --- a/app/src/main/res/values-br/strings.xml +++ b/app/src/main/res/values-br/strings.xml @@ -75,7 +75,7 @@ Arventennoù En em enskrivañ Diwar-benn - Meziant frank a wirioù embannet dindan <a href=\"https://github.com/commons-app/apps-android-commons/blob/master/COPYING\">an Aotre-implijout Apache v2</a>. Merkoù kenwerzhel eus Diazezadur Wikimedia eo Wikimedia Commons hag e logoioù. Gallout a reont bezañ implijet gant aotre an Diazezadur. N\'omp nag aprouet gant Diazezadur Wiikimedia na stag outañ. + Meziant frank a wirioù embannet dindan <a href=\"https://github.com/commons-app/apps-android-commons/blob/master/COPYING\">an Aotre-implijout Apache v2</a>. Merkoù kenwerzhel eus Diazezadur Wikimedia eo Wikimedia Commons hag e logoioù. Gallout a reont bezañ implijet gant aotre an Diazezadur. N\'omp nag aprouet gant Diazezadur Wiikimedia na stag outañ. <a href=\"https://github.com/commons-app/apps-android-commons\">Mammenn</a> ha <a href=\"https://commons-app.github.io/\">lec\'hienn</a> war GitHub. Krouiñ ur <a href=\"https://github.com/commons-app/apps-android-commons/issues\">gemennadenn GitHub nevez</a> evit kelaouiñ a-zivout un draen bennak pe bet kinnigoù. <a href=\"https://wikimediafoundation.org/wiki/Privacy_policy\">Reolennoù prevezded</a> <a href=\"https://github.com/commons-app/apps-android-commons/blob/master/CREDITS\">Trugarekadennoù</a> @@ -183,6 +183,6 @@ Tutorial Ne c\'haller ket diskwel al lec\'hioù tost ma ne rannit ket ho lec\'hiadur N\'eus bet kavet deskrivadur ebet - Pennad Commons + Pennad Commons Elfenn Wikidata diff --git a/app/src/main/res/values-bs/strings.xml b/app/src/main/res/values-bs/strings.xml index d02b603e4..47027f176 100644 --- a/app/src/main/res/values-bs/strings.xml +++ b/app/src/main/res/values-bs/strings.xml @@ -75,7 +75,7 @@ Postavke Registracija O - Program otvorenog kod objavljen pod licencom <a href=\"https://github.com/commons-app/apps-android-commons/blob/master/COPYING\">Apache v2</a>. Wikimedia Commons i njen logo zaštitni su znaci Zadužbine Wikimedia i koriste se s njenom dozvolom. Nismo povezani niti nas podržava Zadužbina Wikimedia. + Program otvorenog kod objavljen pod licencom <a href=\"https://github.com/commons-app/apps-android-commons/blob/master/COPYING\">Apache v2</a>. Wikimedia Commons i njen logo zaštitni su znaci Zadužbine Wikimedia i koriste se s njenom dozvolom. Nismo povezani niti nas podržava Zadužbina Wikimedia. <a href=\"https://github.com/commons-app/apps-android-commons\">Izvorni kod</a> i <a href=\"https://commons-app.github.io/\">veb-sajt</a> na GitHubu. Započnite novi <a href=\"https://github.com/commons-app/apps-android-commons/issues\">slučaj na GitHubu</a> da biste prijavili greške i dali prijedloge. <a href=\"https://wikimediafoundation.org/wiki/Privacy_policy\">Politika privatnosti</a> <a href=\"https://github.com/commons-app/apps-android-commons/blob/master/CREDITS\">Zasluge</a> @@ -187,6 +187,6 @@ Uputstva Mjesta u blizini ne mogu se prikazati bez dozvole za lokaciju nema opisa - Članak na Commonsu + Članak na Commonsu Stavka na Wikipodacima diff --git a/app/src/main/res/values-ca/strings.xml b/app/src/main/res/values-ca/strings.xml index 6282effe5..5bfc72e43 100644 --- a/app/src/main/res/values-ca/strings.xml +++ b/app/src/main/res/values-ca/strings.xml @@ -8,7 +8,7 @@ Registre S’està iniciant la sessió Espereu… - S\'ha iniciat sessió correctament ! + S\'ha iniciat sessió correctament! Error en iniciar la sessió! No s\'ha trobat el fitxer. Proveu-ho amb un altre fitxer. L\'autenticació ha fallat! @@ -38,9 +38,9 @@ Títol Descripció No s\'ha pogut iniciar la sessió – error de xarxa - No s\'ha pogut iniciar la sessió – siusplau comprova el teu nom d\'usuari + No s\'ha pogut iniciar la sessió – si et plau comprova el teu nom d\'usuari No s’ha pogut iniciar la sessió. Comproveu la vostra contrasenya - Masses intents erronis – Proveu-ho de nou d\'aquí uns minuts. + Massa intents erronis – Proveu-ho de nou d\'aquí uns minuts. Ho sentim, aquest usuari ha estat blocat a Commons Ha fallat l\'inici de sessió Carrega @@ -144,6 +144,6 @@ Comentaris Finalitza la sessió no s\'ha trobat cap descripció - Article al Commons + Article al Commons Element del Wikidata diff --git a/app/src/main/res/values-cs/strings.xml b/app/src/main/res/values-cs/strings.xml index 4e00cc03d..49a1cb378 100644 --- a/app/src/main/res/values-cs/strings.xml +++ b/app/src/main/res/values-cs/strings.xml @@ -75,7 +75,7 @@ Nastavení Zaregistrovat se O aplikaci - Open Source software dostupný za podmínek <a href=\"https://github.com/commons-app/apps-android-commons/blob/master/COPYING\">Apache License v2</a>. Wikimedia Commons a logo Wikimedia Commons jsou ochranné známky Wikimedia Foundation a jsou použity se svolením Wikimedia Foundation. Nejsme podporováni Wikimedia Foundation ani nejsme její součástí. + Open Source software dostupný za podmínek <a href=\"https://github.com/commons-app/apps-android-commons/blob/master/COPYING\">Apache License v2</a>. Wikimedia Commons a logo Wikimedia Commons jsou ochranné známky Wikimedia Foundation a jsou použity se svolením Wikimedia Foundation. Nejsme podporováni Wikimedia Foundation ani nejsme její součástí. <a href=\"https://github.com/commons-app/apps-android-commons\">Zdrojový kód</a>, <a href=\"https://commons-app.github.io/\">webová stránka</a> a <a href=\"https://github.com/commons-app/apps-android-commons/issues\">hlášení chyb a sdílení nápadů</a> na GitHubu. <a href=\"https://wikimediafoundation.org/wiki/Ochrana_osobních_údajů\">Ochrana osobních údajů</a> <a href=\"https://github.com/commons-app/apps-android-commons/blob/master/CREDITS\">Autoři</a> @@ -186,6 +186,6 @@ Průvodce Místa poblíž nebude možné zobrazit, neuvedete-li svojí polohu. nebyl nalezen žádný popisek - Článek na Commons + Článek na Commons Položka Wikidat diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 4caaa96cf..5c429f66a 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -75,7 +75,7 @@ Einstellungen Registrieren Über - Die Open-Source-Software wurde veröffentlicht unter der <a href=\"https://github.com/commons-app/apps-android-commons/blob/master/COPYING\">Apache-Lizenz v2</a>. Wikimedia Commons und das Wikimedia-Commons-Logo sind Markenzeichen der Wikimedia Foundation und wurden mit Genehmigung der Wikimedia Foundation verwendet. Wir wurden nicht von der Wikimedia Foundation bestätigt oder sind nicht mit ihr verbunden. + Die Open-Source-Software wurde veröffentlicht unter der <a href=\"https://github.com/commons-app/apps-android-commons/blob/master/COPYING\">Apache-Lizenz v2</a>. %1$s und das entsprechende Logo sind Markenzeichen der Wikimedia Foundation und wurden mit Genehmigung der Wikimedia Foundation verwendet. Wir wurden nicht von der Wikimedia Foundation bestätigt oder sind nicht mit ihr verbunden. <a href=\"https://github.com/commons-app/apps-android-commons\">Quellcode</a> und <a href=\"https://commons-app.github.io/\">Website</a> auf GitHub. Einen neuen <a href=\"https://github.com/commons-app/apps-android-commons/issues\">GitHub-Eintrag</a> für Fehlerberichte und Vorschläge erstellen. <a href=\"//de.wikipedia.org/wiki/Wikipedia:Datenschutz\">Datenschutzrichtlinie</a> <a href=\"https://github.com/commons-app/apps-android-commons/blob/master/CREDITS\">Danksagungen</a> @@ -88,6 +88,7 @@ Erneut versuchen Abbrechen Dieses Bild wird lizenziert unter %1$s + Durch das Hochladen dieses Bildes erkläre ich, dass dies mein eigenes Werk ist, das kein urheberrechtlich geschütztes Material oder Selfies enthält und das auch sonst die <a href=\"https://commons.wikimedia.org/wiki/Commons:Policies_and_guidelines/de\">Wikimedia-Commons-Richtlinien</a> einhält. Herunterladen Lizenz Vorherige(n) Titel/Beschreibung verwenden @@ -118,11 +119,11 @@ Wikimedia Commons speichert die meisten Bilder, die in Wikipedia verwendet werden. Deine Bilder helfen bei der Ausbildung von Menschen auf der ganzen Welt! Bitte lade Bilder hoch, die du völlig selbst aufgenommen oder erstellt hast: - u2022 Natürliche Objekte (Blumen, Tiere, Berge)\nu2022 Nützliche Objekte (Fahrräder, Bahnhöfe)\nu2022 Berühmte Personen (deinen Bürgermeister, olympische Athleten, die du getroffen hast) + - Natürliche Objekte (Blumen, Tiere, Berge)\n- Nützliche Objekte (Fahrräder, Bahnhöfe)\n- Berühmte Personen (deinen Bürgermeister, olympische Athleten, die du getroffen hast) Bitte NICHT hochladen: - u2022 Selfies oder Bilder deiner Freunde\nu2022 Bilder, die du aus dem Internet heruntergeladen hast\nu2022 Screenshots von proprietären Softwareanwendungen + - Selfies oder Bilder deiner Freunde\n- Bilder, die du aus dem Internet heruntergeladen hast\n- Screenshots von proprietären Softwareanwendungen Beispiel-Upload: - u2022 Titel: Opernhaus von Sydney\nu2022 Beschreibung: Opernhaus von Sydney, von der Bucht aus gesehen\nu2022 Kategorien: Opernhaus von Sydney, Opernhaus von Sydney von Westen, Opernhaus von Sydney (Fernansicht) + - Titel: Opernhaus von Sydney\n- Beschreibung: Opernhaus von Sydney, von der Bucht aus gesehen\n- Kategorien: Opernhaus von Sydney, Opernhaus von Sydney von Westen, Opernhaus von Sydney (Fernansicht) Teile deine Bilder. Erwecke Wikipedia-Artikel zum Leben! Die Bilder auf Wikipedia kommen von Wikimedia Commons. Deine Bilder helfen dabei, Menschen auf der ganzen Welt zu bilden. @@ -149,6 +150,9 @@ Beschreibung Hier folgt die Beschreibung des Mediums. Diese kann möglicherweise ziemlich lang sein und erfordert dann einen Umbruch auf mehreren Zeilen. Wir hoffen, dass sie dennoch gut aussieht. Hochgeladen am + Lizenz + Koordinaten + Keine angegeben Beta-Tester werden Melde dich bei unserem Beta-Kanal auf Google Play an und erhalte frühen Zugriff auf neue Funktionen und Fehlerbehebungen Wikidata verwenden @@ -187,7 +191,7 @@ Anleitung Orte in der Nähe können ohne Berechtigung zur Standortbestimmung nicht ermittelt werden Keine Beschreibung gefunden - Commons-Artikel + Commons-Dateiseite Wikidata-Objekt Fehler beim Zwischenspeichern der Bilder diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 9d0759fa2..ca4611489 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -16,9 +16,9 @@ ¡Se subieron %1$s! Pulsa para ver tu subida Empezando la subida de %1$s - Cargando «%1$s» + Cargando %1$s Finalizando la subida de %1$s - Falló la carga de «%1$s» + Falló la carga de %1$s Toca para ver Subiendo %d archivo @@ -27,7 +27,7 @@ Mis subidas recientes En la cola Fallido - %1$d %% completado + %1$d%% completado Subiendo De la galería Tomar una foto @@ -75,7 +75,7 @@ Ajustes Regístrate Acerca de - Programa de código abierto publicado bajo la <a href=\"https://github.com/commons-app/apps-android-commons/blob/master/COPYING\">Licencia Apache ver. 2</a>. Wikimedia Commons y su logotipo son marcas registradas de la Fundación Wikimedia y se utilizan con su permiso. No hemos sido acreditados por la Fundación Wikimedia ni estamos afiliados con ella. + Programa de código abierto publicado bajo la <a href=\"https://github.com/commons-app/apps-android-commons/blob/master/COPYING\">Licencia Apache ver. 2</a>. %1$s y su logotipo son marcas registradas de la Fundación Wikimedia y se utilizan con su permiso. No hemos sido acreditados por la Fundación Wikimedia ni estamos afiliados con ella. <a href=\"https://github.com/commons-app/apps-android-commons\">Código fuente</a> y <a href=\"https://commons-app.github.io/\">sitio web</a> en GitHub. Crea <a href=\"https://github.com/commons-app/apps-android-commons/issues\">incidencias</a> para informar de problemas y sugerencias. <a href=\"https://wikimediafoundation.org/wiki/Privacy_policy\">Normativa de privacidad</a> <a href=\"https://github.com/commons-app/apps-android-commons/blob/master/CREDITS\">Créditos</a> @@ -149,6 +149,9 @@ Descripción Aquí va la descripción del multimedia. Potencialmente, puede ser bastante largo, y deberá agruparse en múltiples líneas. De todas formas, esperamos que se ve bien. Fecha de subida + Licencia + Coordenadas + No se proporcionaron Prueba la versión beta Opta por nuestro canal beta en Google Play y obtén acceso a funcionalidades nuevas y correcciones de errores Utilizar Wikidata @@ -187,6 +190,7 @@ Tutorial Los sitios cercanos no pueden mostrarse sin los permisos de ubicación no se encontró ninguna descripción - Artículo en Commons + Página del archivo en Commons Elemento de Wikidata + Error mientras se guardaban imágenes en la caché diff --git a/app/src/main/res/values-eu/strings.xml b/app/src/main/res/values-eu/strings.xml index 81b9a7588..1c3ba42da 100644 --- a/app/src/main/res/values-eu/strings.xml +++ b/app/src/main/res/values-eu/strings.xml @@ -73,6 +73,7 @@ Berriz saiatu Utzi Irudi hau %1$s lizentziapean egongo da + Irudi hau bidaltzen, nire lan propioa dela aitortzen dut, copyrighta duten materiala edo selfiak ez duela, eta beste motatakoak <a href=\"https://commons.wikimedia.org/wiki/Commons:Policies_and_guidelines\">Wikimedia Ohikoaren arauak</a> Jaitsi Lizentzia Aurreko izenburu/deskribapena erabili @@ -116,6 +117,9 @@ Izenburua Fitxategiaren izenburua Deskribapena + Lizentzia + Koordenatuak + Ez da eskeini Beta testatzaile bihurtu Wikidata erabili (Erne:hau kentzeak mugikorrak datu asko kontsumitzea ekar dezake) @@ -132,6 +136,7 @@ Ezarpenak Saioa itxi Sarrera - Commons Artikulua + Artxibo orrialde komuna WikiData Artikulua + Argazkiak hartzerakoan sortutako akatsa diff --git a/app/src/main/res/values-fi/strings.xml b/app/src/main/res/values-fi/strings.xml index a85d669a5..5925d548d 100644 --- a/app/src/main/res/values-fi/strings.xml +++ b/app/src/main/res/values-fi/strings.xml @@ -75,7 +75,7 @@ Asetukset Rekisteröidy Tietoja - Tämä on vapaan lähdekoodin ohjelmisto, joka on julkaistu <a href=\"https://github.com/commons-app/apps-android-commons/blob/master/COPYING\">Apache License v2</a> -lisenssin alaisena. Wikimedia Commons ja sen logo ovat Wikimedia Foundationin tavaramerkkejä ja niitä käytetään Wikimedia Foundationin luvalla. Emme ole hyväksyttyjä tai sidoksissa Wikimedia Foundationioniin. + Tämä on vapaan lähdekoodin ohjelmisto, joka on julkaistu <a href=\"https://github.com/commons-app/apps-android-commons/blob/master/COPYING\">Apache License v2</a> -lisenssin alaisena. Wikimedia Commons ja sen logo ovat Wikimedia Foundationin tavaramerkkejä ja niitä käytetään Wikimedia Foundationin luvalla. Emme ole hyväksyttyjä tai sidoksissa Wikimedia Foundationioniin. <a href=\"https://github.com/commons-app/apps-android-commons\">Lähde</a> ja <a href=\"https://commons-app.github.io/\">nettisivusto</a> GitHubissa. Luo uusi <a href=\"https://github.com/commons-app/apps-android-commons/issues\">GitHub-issue</a> bugiraporteille ja ehdotuksille. <a href=\"https://wikimediafoundation.org/wiki/Privacy_policy\">Yksityisyydensuoja</a> <a href=\"https://github.com/commons-app/apps-android-commons/blob/master/CREDITS\">Tekijät</a> @@ -95,6 +95,7 @@ Nouda nykyinen sijainti asettaaksesi käyttöön luokkaehdotuksia jos kuva ei ole paikkamerkitty Yötila Käytä tummaa teemaa + Nimeä-JaaSamoin 4.0 Nimeä 4.0 Nimeä-JaaSamoin 3.0 Nimeä 3.0 @@ -160,6 +161,6 @@ Asetukset Palaute Kirjaudu ulos - Commons-artikkeli + Commons-artikkeli Wikidata-kohde diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index c1e5d8896..43bb62f0d 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -75,7 +75,7 @@ Paramètres S’inscrire À propos - Les logiciels Open Source sont publiés sous la <a href=\"https://github.com/commons-app/apps-android-commons/blob/master/COPYING\">licence Apache v2</a>. Wikimédia Commons et son logo sont des marques déposées de la Fondation Wikimédia et sont utilisées avec l’autorisation de la Fondation Wikimédia. Nous ne sommes pas approuvés par ou affiliés à la Fondation Wikimédia. + Les logiciels Open Source sont publiés sous la <a href=\"https://github.com/commons-app/apps-android-commons/blob/master/COPYING\">licence Apache v2</a>. %1$s et son logo sont des marques déposées de la Fondation Wikimédia qui sont utilisées avec l’autorisation de la Fondation Wikimédia. Nous ne sommes pas approuvés par ou affiliés à la Fondation Wikimédia. <a href=\"https://github.com/commons-app/apps-android-commons\">Sources</a> et <a href=\"https://commons-app.github.io/\">site web</a> sur GitHub. Créer un nouveau <a href=\"https://github.com/commons-app/apps-android-commons/issues\">signalement GitHub</a> pour signales des bogues ou des suggestions. <a href=\"https://wikimediafoundation.org/wiki/Privacy_policy\">Politique de confidentialité</a> <a href=\"https://github.com/commons-app/apps-android-commons/blob/master/CREDITS\">Remerciements</a> @@ -88,6 +88,7 @@ Réessayer Annuler Cette image sera sous licence %1$s + En soumettant cette image, je déclare qu\'elle est l\'oeuvre de mon travail, qu\'elle ne contient pas d\'élément protégé par les droits d\'auteurs ni de portraits, et qu\'elle est par ailleur conforme à <a href=\"https://commons.wikimedia.org/wiki/Commons:Policies_and_guidelines\">la politique de Wikimedia Commons</a>. Télécharger Licence Utiliser le titre ou la description précédent @@ -149,6 +150,9 @@ Description La description du média vient ici. Cela peut être potentiellement assez long, et devra être réparti sur plusieurs lignes. Nous espérons que cela restera joli néanmoins. Date de téléversement + Licence + Coordonnées + Non fourni Devenir un bêta-testeur S’inscrire à notre canal bêta sur Google Play et obtenir un accès anticipé aux nouvelles fonctionnalités et corrections de bogue Utiliser Wikidata @@ -187,6 +191,7 @@ Tutoriel Les endroits proches ne peuvent pas être affichés si vous ne partagez pas votre position géographique. aucune description trouvée - Article de Communs + Page des fichiers de Communs Élément de Wikidata + Erreur en mettant les images en cache diff --git a/app/src/main/res/values-frr/strings.xml b/app/src/main/res/values-frr/strings.xml index ad4f79e51..7bde8ad92 100644 --- a/app/src/main/res/values-frr/strings.xml +++ b/app/src/main/res/values-frr/strings.xml @@ -170,6 +170,6 @@ Iinstelangen Ragmeldang Ufmelde - Commons-artiikel + Commons-artiikel WikiData-artiikel diff --git a/app/src/main/res/values-gl/strings.xml b/app/src/main/res/values-gl/strings.xml index 0fb064a95..836bcfa01 100644 --- a/app/src/main/res/values-gl/strings.xml +++ b/app/src/main/res/values-gl/strings.xml @@ -75,7 +75,7 @@ Configuracións Rexistrarse Acerca de - Software de código aberto liberado baixo a <a href=\"https://github.com/commons-app/apps-android-commons/blob/master/COPYING\">licenza Apache v2</a>. Wikimedia Commons e o seu logo son marcas rexistradas da Fundación Wikimedia e úsanse coa súa autorización. Non fomos acreditados pola Fundación Wikimedia nin estamos afiliados con ela. + Software de código aberto liberado baixo a <a href=\"https://github.com/commons-app/apps-android-commons/blob/master/COPYING\">licenza Apache v2</a>. %1$s e o seu logo son marcas rexistradas da Fundación Wikimedia e úsanse coa súa autorización. Non fomos acreditados pola Fundación Wikimedia nin estamos afiliados con ela. <a href=\"https://github.com/commons-app/apps-android-commons\">Código fonte</a> e <a href=\"https://commons-app.github.io/\">sitio web</a> en GitHub. Crear unha nova <a href=\"https://github.com/commons-app/apps-android-commons/issues\">incidencia</a> para informar de problemas e suxestións. <a href=\"https://wikimediafoundation.org/wiki/Política_de_protección_de_datos_(gl)\">Política de protección de datos</a> <a href=\"https://github.com/commons-app/apps-android-commons/blob/master/CREDITS\">Créditos</a> @@ -149,6 +149,9 @@ Descrición Aquí vai a descrición do ficheiro multimedia. Potencialmente, pode ser bastante longo, e necesitará agruparse en múltiples liñas. De tódolos xeitos esperamos que se vexa ben. Data de suba + Licenza + Coordenadas + Non proporcionado Converterse en beta-tester Siga a nosa canle beta en Google Play e obteña acceso a novas funcionalidades e correccións de erros Usar Wikidata @@ -187,6 +190,7 @@ Titorial Os sitios situados preto non poden visualizarse sen permisos de localización non se atopou descrición - Artigo en Commons + Páxina do ficheiro en Commons Elemento en Wikidata + Erro mentras se gardaban as imaxes na caché diff --git a/app/src/main/res/values-he/strings.xml b/app/src/main/res/values-he/strings.xml index eaef5a9c5..feb3cf436 100644 --- a/app/src/main/res/values-he/strings.xml +++ b/app/src/main/res/values-he/strings.xml @@ -18,8 +18,7 @@ העלאת %1$s מסתיימת העלאת %1$s נכשלה נא ללחוץ כדי להציג - נשארו %d - ההעלאות שלי + ההעלאות שלי בתור נכשלה %1$d%% הושלמו diff --git a/app/src/main/res/values-hu/strings.xml b/app/src/main/res/values-hu/strings.xml index 3a45d92f1..71f9afd7b 100644 --- a/app/src/main/res/values-hu/strings.xml +++ b/app/src/main/res/values-hu/strings.xml @@ -75,7 +75,7 @@ Beállítások Regisztráció Névjegy - Nyílt forráskódú szoftver <a href=\"https://github.com/commons-app/apps-android-commons/blob/master/COPYING\">Apache License v2</a> alatt kiadva. A Wikimédia Commons és a logója a Wikimédia Alapítvány védjegyei, és a Wikimédia Alapítvány engedélyével vannak használva. Az alkalmazás fejlesztői nincsenek semmilyen kapcsolatban Wikimédia Alapítvánnyal. + Nyílt forráskódú szoftver <a href=\"https://github.com/commons-app/apps-android-commons/blob/master/COPYING\">Apache License v2</a> alatt kiadva. A Wikimédia Commons és a logója a Wikimédia Alapítvány védjegyei, és a Wikimédia Alapítvány engedélyével vannak használva. Az alkalmazás fejlesztői nincsenek semmilyen kapcsolatban Wikimédia Alapítvánnyal. <a href=\"https://github.com/commons-app/apps-android-commons\">Forráskód</a> és <a href=\"https://commons-app.github.io/\">weboldal</a> a GitHubon. Nyiss egy új <a href=\"https://github.com/commons-app/apps-android-commons/issues\">GitHub-problémát</a> hibabejelentéssel vagy fejlesztési javaslattal. <a href=\"https://wikimediafoundation.org/wiki/Adatvédelmi_irányelv\">Adatvédelmi irányelvek</a> <a href=\"https://github.com/commons-app/apps-android-commons/blob/master/CREDITS\">Köszönetnyilvánítás</a> @@ -177,6 +177,6 @@ Kijelentkezés Bevezető nincs leírás - Commons szócikk + Commons szócikk Wikidata tétel diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index 0048678bd..6d837dda5 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -75,7 +75,7 @@ Impostazioni Registrati Informazioni - Software open source rilasciato con <a href=\"https://github.com/commons-app/apps-android-commons/blob/master/COPYING\">licenza Apache v2</a>. Wikimedia Commons ed il suo logo sono marchi registrati della Wikimedia Foundation e sono utilizzati con il permesso della Wikimedia Foundation. Non siamo approvati o affiliati con la Wikimedia Foundation. + Software open source rilasciato con <a href=\"https://github.com/commons-app/apps-android-commons/blob/master/COPYING\">licenza Apache v2</a>. %1$s ed il suo logo sono marchi registrati della Wikimedia Foundation e sono utilizzati con il permesso della Wikimedia Foundation. Non siamo approvati o affiliati con la Wikimedia Foundation. <a href=\"https://github.com/commons-app/apps-android-commons\">Codice sorgente</a> e <a href=\"https://commons-app.github.io/\">sito web</a> su GitHub. Crea una nuova <a href=\"https://github.com/commons-app/apps-android-commons/issues\">segnalazione GitHub</a> per riportare errori e suggerimenti. <a href=\"https://wikimediafoundation.org/wiki/Privacy_policy\">Politica sulla privacy</a> <a href=\"https://github.com/commons-app/apps-android-commons/blob/master/CREDITS\">Crediti</a> @@ -140,6 +140,8 @@ Titolo del file multimediale Descrizione Data di caricamento + Licenza + Coordinate Usa Wikidata Codice 2FA Limite massimo @@ -164,5 +166,6 @@ Esci Tutorial nessuna descrizione trovata + Pagina di Commons del file Elemento Wikidata diff --git a/app/src/main/res/values-iw/strings.xml b/app/src/main/res/values-iw/strings.xml index 2018e0774..d2fc2330c 100644 --- a/app/src/main/res/values-iw/strings.xml +++ b/app/src/main/res/values-iw/strings.xml @@ -74,7 +74,7 @@ הגדרות רישום אודות - תכנת קוד פתוח המתפרסמת לפי תנאי <a href=\"https://github.com/commons-app/apps-android-commons/blob/master/COPYING\">Apache License v2</a>. השם Wikimedia Commons והסמל שלו הם סימני מסחר של קרן ויקימדיה ומשמשים באישור קרן ויקימדיה. איננו נתמכים על־ידי קרן ויקימדיה או קשורים אליה בשותפות. + תכנת קוד פתוח המתפרסמת לפי תנאי <a href=\"https://github.com/commons-app/apps-android-commons/blob/master/COPYING\">Apache License v2</a>. השם %1$s והסמל שמשויך אליו הם סימני מסחר של קרן ויקימדיה ומשמשים באישור קרן ויקימדיה. איננו נתמכים על־ידי קרן ויקימדיה או קשורים אליה בשותפות. <a href=\"https://github.com/commons-app/apps-android-commons\">קוד מקור</a> ו<a href=\"https://commons-app.github.io/\">אתר</a> בגיטהאב. נא ליצור <a href=\"https://github.com/commons-app/apps-android-commons/issues\">דיווח בגיטהאב</a> בשביל באגים והצעות. <a href=\"https://github.com/commons-app/apps-android-commons/blob/master/CREDITS\">יוצרים</a> @@ -87,6 +87,7 @@ לנסות שוב ביטול התמונה הזאת היא תחת רשיון %1$s + שליחת התמונה הזאת מהווה את הצהרתי על כך שזאת יצירה שלי, שהיא לא מכילה חומר מוגבל בזכויות יוצרים או תמונות עצמיות (סלפי) ומתאימה בכל אופן ל<a href=\"https://commons.wikimedia.org/wiki/Commons:Policies_and_guidelines\">מדיניות של אתר ויקישיתוף של ויקימדיה</a>. הורדה רישיון להשתמש בכותרת ובתיאור קודמים @@ -148,6 +149,9 @@ תיאור תיאור המדיה יהיה כאן. זה יכול להיות ארוך למדי, ולהתפרס על מספר שורות. אנחנו מקווים שזה נראה טוב. תאריך העלאה + רישיון + נקודות ציון + לא סופקו להפוך לבודק בטא להירשם לערוץ הבטא שלנו בחנות גוגל Play ולקבל גישה מוקדמת לאפשרויות חדשות ותיקוני באגים להשתמש בוויקינתונים @@ -183,6 +187,7 @@ מדריך אי־אפשר להציג מקומות בסביבה ללא הרשאות מיקום לא נמצא תיאור + דף קובץ בוויקישיתוף פריט ויקינתונים שגיאה במשירת תמונות במטמון diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml index cdd6dbbc3..a5dc309b8 100644 --- a/app/src/main/res/values-ja/strings.xml +++ b/app/src/main/res/values-ja/strings.xml @@ -67,7 +67,7 @@ 設定 利用者登録 このアプリについて - <a href=\"https://github.com/commons-app/apps-android-commons/blob/master/COPYING\">Apache ライセンス v2</a> のもとで公開されているオープン ソース ソフトウェアです。Wikimedia Commons ならびにそのロゴはウィキメディア財団の商標であり、ウィキメディア財団の許可により使用しています。このサイトはウィキメディア財団の公認3でも提携先でもありません。 + <a href=\"https://github.com/commons-app/apps-android-commons/blob/master/COPYING\">Apache ライセンス v2</a> のもとで公開されているオープン ソース ソフトウェアです。Wikimedia Commons ならびにそのロゴはウィキメディア財団の商標であり、ウィキメディア財団の許可により使用しています。このサイトはウィキメディア財団の公認3でも提携先でもありません。 ソースは <a href=\"https://github.com/commons-app/apps-android-commons\">GitHub</a> にあります。バグとアイディアは <a href=\"https://github.com/commons-app/apps-android-commons/issues\">Github</a> へ。 <a href=\"https://wikimediafoundation.org/wiki/プライバシー・ポリシー\">プライバシー・ポリシー</a> <a href=\"https://github.com/commons-app/apps-android-commons/blob/master/CREDITS\">クレジット</a> diff --git a/app/src/main/res/values-ji/strings.xml b/app/src/main/res/values-ji/strings.xml index d7fbf831f..4f8aed92b 100644 --- a/app/src/main/res/values-ji/strings.xml +++ b/app/src/main/res/values-ji/strings.xml @@ -93,6 +93,8 @@ ווארענונג יא ניין + ליצענץ + קאארדינאטן טולפאן אַנולירן אפֿן diff --git a/app/src/main/res/values-jv/strings.xml b/app/src/main/res/values-jv/strings.xml index 87bfeaf51..dc719f622 100644 --- a/app/src/main/res/values-jv/strings.xml +++ b/app/src/main/res/values-jv/strings.xml @@ -165,6 +165,6 @@ Setèlan Pamrayoga Metu log - Artikel Commons + Artikel Commons Wiji Wikidata diff --git a/app/src/main/res/values-ka/strings.xml b/app/src/main/res/values-ka/strings.xml index a7762f304..300d463bf 100644 --- a/app/src/main/res/values-ka/strings.xml +++ b/app/src/main/res/values-ka/strings.xml @@ -71,7 +71,7 @@ კონფიგურაცია რეგისტრაცია პროგრამის შესახებ - ღია კოდის მქონე აპლიკაცია, ვრცელდება ლიცენზიით <a href=\"https://github.com/commons-app/apps-android-commons/blob/master/COPYING\">Apache License v2</a>. ვიკისაწყობი და მისი ლოგო ფონდი ვიკიმედიის სავაჭრო ნიშნებია და ფონდი ვიკიმედიის ნებართვით გამოიყენება. ჩვენ არ ვართ დაკავშირებული ფონდ ვიკიმედიასთან. + ღია კოდის მქონე აპლიკაცია, ვრცელდება ლიცენზიით <a href=\"https://github.com/commons-app/apps-android-commons/blob/master/COPYING\">Apache License v2</a>. ვიკისაწყობი და მისი ლოგო ფონდი ვიკიმედიის სავაჭრო ნიშნებია და ფონდი ვიკიმედიის ნებართვით გამოიყენება. ჩვენ არ ვართ დაკავშირებული ფონდ ვიკიმედიასთან. <a href=\"https://github.com/commons-app/apps-android-commons\">წყარო</a> და <a href=\"https://commons-app.github.io/\">საიტი</a> GitHub-ზე. შეცდომის შესატყობინებლად ან წინადადებისათვის შექმენით ახალი <a href=\"https://github.com/commons-app/apps-android-commons/issues\">მოთხოვნა GitHub-ზე</a>. <a href=\"https://wikimediafoundation.org/wiki/Privacy_policy\">კონფიდენციალურობის პოლიტიკა</a> <a href=\"https://github.com/commons-app/apps-android-commons/blob/master/CREDITS\">მადლობები</a> @@ -170,6 +170,6 @@ სახელმძღვანელო ახლომდებარე ადგილების ჩვენება მდებარეობის განსაზღვრის ნებართვის გარეშე შეუძლებელია აღწერა ვერ მოიძებნა - ვიკისაწყობის სტატია + ვიკისაწყობის სტატია ვიკიმონაცემების ელემენტი diff --git a/app/src/main/res/values-ko/strings.xml b/app/src/main/res/values-ko/strings.xml index 90c3faf50..938d53c38 100644 --- a/app/src/main/res/values-ko/strings.xml +++ b/app/src/main/res/values-ko/strings.xml @@ -142,6 +142,9 @@ 미디어 제목 설명 올린 날짜 + 라이선스 + 좌표 + 제공되지 않음 베타 테스터가 되세요 위키데이터 사용 (경고: 이것을 끄면 대량의 모바일 데이터를 소비할 수 있습니다) @@ -178,7 +181,7 @@ 강좌 위치 권한이 없으면 주변 장소를 표시할 수 없습니다 설명이 없습니다 - 공용 문서 + 공용 파일 문서 위키데이터 항목 그림 캐시 처리 오류 diff --git a/app/src/main/res/values-lb/strings.xml b/app/src/main/res/values-lb/strings.xml index 4e8146f50..2aaaeaf67 100644 --- a/app/src/main/res/values-lb/strings.xml +++ b/app/src/main/res/values-lb/strings.xml @@ -74,7 +74,7 @@ Astellungen Mellt Iech un Iwwer - \'Open-Source-Software\' verëffentlecht ënner der <a href=\"https://github.com/commons-app/apps-android-commons/blob/master/COPYING\">Apache Lizenz v2</a>. Wikimedia Commons a säi Logo si Markenzeeche vun der Wikimedia Foundation a gi mat der Autorisatioun vun der Wikimedia Foundation benotzt. Mir sinn net confirméiert vun oder liéiert mat der Wikimedia Foundation. + \'Open-Source-Software\' verëffentlecht ënner der <a href=\"https://github.com/commons-app/apps-android-commons/blob/master/COPYING\">Apache Lizenz v2</a>. %1$s a säi Logo si Markenzeeche vun der Wikimedia Foundation a gi mat der Autorisatioun vun der Wikimedia Foundation benotzt. Mir sinn net confirméiert vun oder liéiert mat der Wikimedia Foundation. <a href=\"https://github.com/commons-app/apps-android-commons\">Quell</a> an <a href=\"https://commons-app.github.io/\">Internetsite</a> vu GitHub.\nLeet w.e.g. <a href=\"https://github.com/commons-app/apps-android-commons/issues\"> e GitHub Problem</a> fir Problemer ze mellen a Proposen ze maachen. <a href=\"https://wikimediafoundation.org/wiki/Privacy_policy\">Dateschutzerklärung</a> <a href=\"https://github.com/commons-app/apps-android-commons/blob/master/CREDITS\">Merci</a> @@ -148,6 +148,9 @@ Beschreiwung D\' Beschreiwung vum Medium kënnt hei. Dëst ka méiglecherweis laang sinn a gëtt eventuell op méi Zeile verdeelt. Mir hoffen et gesäit trotzdeem gutt aus. Datum vum Eroplueden + Lizenz + Koordinaten + Keng uginn Beta-Tester ginn Schreift Iech op GooglePlay a fir eise Beta-Kanal a kritt fréi Zougang zu neie Funktiounen a Verbesserunge vu Feeler Wikidata benotzen @@ -182,6 +185,6 @@ Uleedung Plazen nobäi kënnen net gewise ginn ouni Rechter fir d\'Lokalisatioun keng Beschreiwung fonnt - Commons-Artikel + Commons-Fichierssäit Wikidata-Element diff --git a/app/src/main/res/values-lv/strings.xml b/app/src/main/res/values-lv/strings.xml index b3f080ac0..a71473023 100644 --- a/app/src/main/res/values-lv/strings.xml +++ b/app/src/main/res/values-lv/strings.xml @@ -54,6 +54,7 @@ Atcelt Lejupielādēt Licence + Nakts režīms CC0 Jums šķiet, ka sapratāt? Jā! @@ -66,6 +67,7 @@ Brīdinājums + Augšupielādēt attēlu Lama Tulpe Atcelt diff --git a/app/src/main/res/values-mk/strings.xml b/app/src/main/res/values-mk/strings.xml index 20743c676..2323d701d 100644 --- a/app/src/main/res/values-mk/strings.xml +++ b/app/src/main/res/values-mk/strings.xml @@ -75,7 +75,7 @@ Нагодувања Регистрација За извршникот - Програм со отворен код, издаден под лиценцата <a href=\"https://github.com/commons-app/apps-android-commons/blob/master/COPYING\">Апачи вер. 2</a>. ризницата и нејзиното лого се заштитни знаци на Фондацијата Викимедија и се користат со нејзина дозвола. Ние не сме поддржани и поврзани со Фондацијата Викимедија. + Програм со отворен код, издаден под лиценцата <a href=\"https://github.com/commons-app/apps-android-commons/blob/master/COPYING\">Апачи вер. 2</a>. %1$s и нејзиното лого се заштитни знаци на Фондацијата Викимедија и се користат со нејзина дозвола. Ние не сме поддржани и поврзани со Фондацијата Викимедија. <a href=\"https://github.com/commons-app/apps-android-commons\">Извор</a> и <a href=\"https://commons-app.github.io/\">мреж. место</a> на GitHub</a>. Создајте нов <a href=\"https://github.com/commons-app/apps-android-commons/issues\">случај на GitHub</a> за пријавување грешки и давање предлози. <a href=\"https://wikimediafoundation.org/wiki/Заштита на личните податоци\">Заштита_на_личните_податоци</a> <a href=\"https://github.com/commons-app/apps-android-commons/blob/master/CREDITS\">Заслуги</a> @@ -88,6 +88,7 @@ Пробај пак Откажи Сликава ќе се води под лиценцата %1$s + Поднесувајќи ја сликава, изјавувам дека истата е мое сопствено дело, дека не содржи никаков материјал заштитен со авторски права, не содржи самослици, и дека на секој друг начин е во склад со <a href=\"https://commons.wikimedia.org/wiki/Commons:Policies_and_guidelines/mk?uselang=mk\">правилата на Ризницата</a>. Преземи Лиценца Користи претходен наслов/опис @@ -149,6 +150,9 @@ Опис Тука оди описот на податотеката. Ова потенцијално може да биде прилично долго, и ќе треба да се преломи во неколку реда. Се надеваме дека ќе изгледа добро. Датум на подигање + Лиценца + Координати + не се укажани Станете бета-испробувач Пријавете се на нашиот бета-канал на Google Play и добивајте ран пристап до нови можности и исправки на грешки Користи Википодатоци @@ -187,7 +191,7 @@ Упатства Местата во близина не можат да се прикажат без дозволи за местоположба. не најдов описи - Статија на Ризницата + Податотечна страница Предмет на Википодатоците Грешка при меѓускладирање на сликите diff --git a/app/src/main/res/values-ms/strings.xml b/app/src/main/res/values-ms/strings.xml index ff342f3bf..fa5e00766 100644 --- a/app/src/main/res/values-ms/strings.xml +++ b/app/src/main/res/values-ms/strings.xml @@ -18,7 +18,6 @@ %1$s akan siap dimuat naik %1$s gagal dimuat naik Ketik untuk lihat - %d fail sedang dimuat naik Muat Naik Terbaru Saya Dibaris gilir Gagal @@ -48,8 +47,7 @@ %d muatnaik %d muatnaik - Memulakan %d kerja muat naik - + %d muatnaik %d muatnaik diff --git a/app/src/main/res/values-nb/strings.xml b/app/src/main/res/values-nb/strings.xml index 510fc6367..e1b03ad5d 100644 --- a/app/src/main/res/values-nb/strings.xml +++ b/app/src/main/res/values-nb/strings.xml @@ -75,7 +75,7 @@ Innstillinger Registrer deg Om - Programvare med åpen kildekode sluppet under <a href=\"https://github.com/commons-app/apps-android-commons/blob/master/COPYING\">Apache License v2</a>. Wikimedia Commons og dets logo er varemerker fra Wikimedia Foundation og brukes med tillatelse fra dem. Vi er verken støttet av eller koblet til Wikimedia Foundation. + Programvare med åpen kildekode sluppet under <a href=\"https://github.com/commons-app/apps-android-commons/blob/master/COPYING\">Apache License v2</a>. Wikimedia Commons og dets logo er varemerker fra Wikimedia Foundation og brukes med tillatelse fra dem. Vi er verken støttet av eller koblet til Wikimedia Foundation. <a href=\"https://github.com/commons-app/apps-android-commons\">Kildekode</a> og <a href=\"https://commons-app.github.io/\">nettside</a> på GitHub. Opprett en ny <a href=\"https://github.com/commons-app/apps-android-commons/issues\">GitHub-sak</a> for feilrapporter og forslag. <a href=\"https://wikimediafoundation.org/wiki/Privacy_policy\">Personvernpolicy</a> <a href=\"https://github.com/commons-app/apps-android-comons/blob/master/CREDITS\">Bidragsytere</a> @@ -187,6 +187,6 @@ Veiviser Steder i nærheten kan ikke vises uten tillatelse for stedsbestemmelse ingen beskrivelse funnet - Commons-artikkel + Commons-artikkel Wikidata-element diff --git a/app/src/main/res/values-nl/strings.xml b/app/src/main/res/values-nl/strings.xml index ee04c11fa..12af46170 100644 --- a/app/src/main/res/values-nl/strings.xml +++ b/app/src/main/res/values-nl/strings.xml @@ -155,4 +155,5 @@ Instellingen Terugkoppeling Afmelden + Error tijdens het laden van de afbeeldingen diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index 9b4dddab2..8109303a2 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -73,7 +73,7 @@ Ustawienia Zarejestruj się O aplikacji - Oprogramowanie Open Source, wydane na licencji <a href=\"https://github.com/commons-app/apps-android-commons/blob/master/COPYING\">Apache License v2</a>. Wikimedia Commons i jego logo są znakami towarowymi Wikimedia Foundation i są wykorzystywane za zgodą Wikimedia Foundation. Nie jesteśmy powiązani z Wikimedia Foundation. + Oprogramowanie Open Source, wydane na licencji <a href=\"https://github.com/commons-app/apps-android-commons/blob/master/COPYING\">Apache License v2</a>. Wikimedia Commons i jego logo są znakami towarowymi Wikimedia Foundation i są wykorzystywane za zgodą Wikimedia Foundation. Nie jesteśmy powiązani z Wikimedia Foundation. <a href=\"https://github.com/commons-app/apps-android-commons\">Kod źródłowy</a> oraz <a href=\"https://commons-app.github.io/\">strona internetowa</a> na GitHub. Aby zgłosić błąd lub sugestię, utwórz nowe <a href=\"https://github.com/commons-app/apps-android-commons/issues\">zgłoszenie na GitHub</a>. <a href=\"https://wikimediafoundation.org/wiki/Privacy_policy\">Polityka prywatności</a> <a href=\"https://github.com/commons-app/apps-android-commons/blob/master/CREDITS\">Twórcy</a> diff --git a/app/src/main/res/values-pms/strings.xml b/app/src/main/res/values-pms/strings.xml index 050449b25..ef2cc33e1 100644 --- a/app/src/main/res/values-pms/strings.xml +++ b/app/src/main/res/values-pms/strings.xml @@ -75,7 +75,7 @@ Paràmeter Marchesse A propòsit - Ij programa Open Source a son publicà sota la <a href=\"https://github.com/commons-app/apps-android-commons/blob/master/COPYING\">licensa Apache v2</a>. Wikimedia Commons e sò sìmbol a son dle marche argistrà dla Fondassion Wikimedia e a son dovrà con ël përmess ëd la Fondassion Wikimedia. Nojàutri i soma nen aprovà da o afilià a la Fondassion Wikimedia. + Ij programa Open Source a son publicà sota la <a href=\"https://github.com/commons-app/apps-android-commons/blob/master/COPYING\">licensa Apache v2</a>. %1$s e sò sìmbol a son dle marche argistrà dla Fondassion Wikimedia e a son dovrà con ël përmess ëd la Fondassion Wikimedia. Nojàutri i soma nen aprovà da o afilià a la Fondassion Wikimedia. <a href=\"https://github.com/commons-app/apps-android-commons\">Sorgiss</a> e <a href=\"https://commons-app.github.io/\">sit an sl\'aragnà</a> su GitHub. Creé na neuva <a href=\"https://github.com/commons-app/apps-android-commons/issues\">signalassion GitHub</a> për signalé dij givo e dij sugeriment. <a href=\"https://wikimediafoundation.org/wiki/Privacy_policy\">Régole ëd confidensialità</a> <a href=\"https://github.com/commons-app/apps-android-commons/blob/master/CREDITS\">Ringrassiament</a> @@ -88,6 +88,7 @@ Prové torna Anulé Costa plancia a sarà sota la licensa %1$s + An mandand costa plancia, i diciaro ch\'a l\'é euvra ëd mè travaj, ch\'a conten nen d\'element sota drit d\'autor o d\'àutoscat, e che comsëssìa a l\'é conforma a <a href=\"https://commons.wikimedia.org/wiki/Commons:Policies_and_guidelines\">le régole ëd Wikimedia Commons</a>. Dëscarié Licensa Dovré ël tìtol o la descrission precedent @@ -149,6 +150,9 @@ Descrission La descrission dël mojen a va ambelessì. Sòn a podrìa esse potensialman longh, e a dovrà esse spantià su vàire linie. I speroma comsëssìa ch\'a ven-a grassios. Dàita ëd cariament + Licensa + Coordinà + Nen fornì Dventé në sperimentador Beta Anscriv-se a nòstr canal beta su Google Play a oten-e n\'acess antissipà a le neuve fonsionalità e coression ëd givo Dovré Wikidàit @@ -187,7 +191,7 @@ Cors d\'antrodussion Ij pòst ant j\'anviron a peulo nen esse smonù sensa ij përmess ëd localisassion gnun-a descrission trovà - Artìcol ëd Comun + Pàgina dj\'archivi ëd Comun Element ëd WikiData Eror antramentre ch\'as butavo le plance an memòria local diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index 8ff19136f..91d226aff 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -24,7 +24,7 @@ carregando arquivo carregando %d arquivos - Meus envios + Meus envios recentes Na fila Falhou %1$d%% concluída @@ -53,9 +53,10 @@ Atualizar O GPS está desligado no seu aparelho. Gostarias de ligá-lo ? GPS inapto. - - Nenhum envio - 1 envio + Ainda não carregado + + \@string/contributions_subtitle_zero + %d envio %d envios @@ -74,10 +75,10 @@ Configurações Criar conta Sobre - Software livre distribuído sob a <a href=\"https://github.com/commons-app/apps-android-commons/blob/master/COPYING\">Apache License v2</a>. Wikimedia Commons e seu logotipo são marcas registradas da Wikimedia Foundation e são usadas com a permissão da Wikimedia Foundation. Não somos endossados nem afiliados à Wikimedia Foundation. + Software livre distribuído sob a <a href=\"https://github.com/commons-app/apps-android-commons/blob/master/COPYING\">Apache License v2</a>. %1$s e seu logotipo são marcas registradas da Wikimedia Foundation e são usadas com a permissão da Wikimedia Foundation. Não somos endossados nem afiliados à Wikimedia Foundation. <a href=\"https://github.com/commons-app/apps-android-commons\">Fonte</a> e <a href=\"https://commons-app.github.io/\">site</a> em GitHub. Crie um novo <a href=\"https://github.com/commons-app/apps-android-commons/issues\">GitHub issue</a> para relatórios de bugs e sugestões. <a href=\"https://wikimediafoundation.org/wiki/Privacy_policy\">Política de privacidade</a> - <a href=\"https://github.com/commons-app/apps-android-commons/blob/master/CREDITS\">CRÉDITOS</a> + <a href=\"https://github.com/commons-app/apps-android-commons/blob/master/CREDITS\">Créditos</a> Sobre Enviar comentários (por e-mail) Nenhum cliente de e-mail instalado @@ -87,6 +88,7 @@ Repetir Cancelar Essa imagem será licenciada sob %1$s + Ao enviar esta imagem, declaro que este é o meu próprio trabalho, que não contém material protegido ou selfies, e, de outra forma, adere a <a href=\"https://commons.wikimedia.org/wiki/Commons:Policies_and_guidelines\">Políticas do Wikimedia Commons</a>. Download Licença Usar o título/descrição anterior @@ -129,7 +131,7 @@ Você acha que conseguiu? Sim! Categorias - Carregando… + Carregando… Nenhum selecionado Sem descrição Licença desconhecida @@ -148,14 +150,34 @@ Descrição Descrição da mídia aqui. Isso pode ser potencialmente longo e precisará envolver múltiplas linhas. Esperamos que seja agradável. Data de envio. + Licença + Coordenadas + Nenhum fornecido Seja um Testador Beta Entre no nosso canal beta no Google Play e receba acesso prévio a novos recursos e correções de erros Usa Wikidata (Aviso: desabilitar isso pode causar grande consumo de dados móveis) Código 2FA + Meu limite de upload recente + Limite máximo Incapaz de exibir mais de 500. + Definir o limite de carregamento recente Dois fatores de autenticação não são suportados. Quer realmente sair ? + Logotipo do Commons + Imagem de fundo + Falha na imagem de mídia + Nenhuma imagem encontrada + Enviar Imagem + Mount Zao + Llamas + Ponte de Arco-Íris + Tulipa + Sem Selfies + Imagem proprietária + Bem-vindo à Wikipédia + Direitos de autor são bem vindo + Ópera de Sydney Cancelar Abrir Fechar @@ -166,4 +188,10 @@ Configurações Comentários Sair + Tutorial + Os locais próximos não podem ser exibidos sem permissões de localização + Nenhuma descrição encontrada + Página de arquivo do Commons + Item do Wikidata + Erro durante o cache de imagens diff --git a/app/src/main/res/values-qq/strings.xml b/app/src/main/res/values-qq/strings.xml index a32d64b55..4d891fe3f 100644 --- a/app/src/main/res/values-qq/strings.xml +++ b/app/src/main/res/values-qq/strings.xml @@ -49,8 +49,7 @@ This message is followed by a list of the categories.\n{{Identical|Search category}} Hint text on menu item to save selected categories.\n{{Identical|Save}} {{Identical|Refresh}} - {{Identical|Upload}} - Message shown to the user when no category matching what they searched for was found. %1$s represents the category name + Message shown to the user when no category matching what they searched for was found. %1$s represents the category name Text explaining to users why and how to add categories to images. Users can also tap this message to skip adding categories. Title for the activity where Categories are being selected to add to the Image.\n{{Identical|Category}} Text for preference that enables the user to enable or disable collection of data about the user\'s usage patterns. @@ -58,7 +57,7 @@ {{Identical|Settings}} {{Identical|Sign up}} {{Identical|About}} - {{doc-important|The name \"Wikimedia Commons\" is a trademark in English, and in most cases you should not translate that. You should only translate \"Wikimedia Commons\" here, however, if you agree that your translation of \"Wikimedia Commons\" is also registered as trademark in countries which your language is commonly used. This means that, for example, by translating \"Wikimedia Commons\" to Macedonian \"Фондацијата Викимедија\", you agree that \"Фондацијата Викимедија\" is also a trademark in the Republic of Macedonia.}}\n\nLicense and legal notice. + License and legal notice. %1$s is {{msg-wm|Commons-android-strings-trademarked name}} {{doc-important|Please make sure that your translation of \"source\" means \"source code\", not \"reference source\".}}\nSource and Bugs HTML fragment linking to Wikimedia\'s privacy policy. Note: avoid percent-encoding in the URL, as this causes problems with Android\'s resource compiler. Use accented/non-ASCII characters \"as is\" if possible. (We can fix it manually, so don\'t worry too much about it.)\n{{Identical|Privacy policy}} {{Identical|Credit}} @@ -97,6 +96,9 @@ {{Identical|No}} {{Identical|Title}} {{Identical|Description}} + {{Identical|License}} + {{Identical|Coordinate}} + Describes \"coordinates\". This is a mountain between Yamagata and Miyagi Prefectures in Japan, see [[d:Q167951]] for details. An animal. See [[:d:Q42569|Wikidata item Q42569]] for a list of possible translations. A bridge in Japan. See [[:d:Q1046736|Wikidata item Q1046736]] for a list of possible translations. diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 8c9939039..a4fd3f49f 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -79,7 +79,7 @@ Настройки Зарегистрироваться О приложении - Приложение с открытым исходным кодом, выпущено по лицензии <a href=\"https://github.com/commons-app/apps-android-commons/blob/master/COPYING\">Apache License v2</a>. Викисклад и его логотип являются товарными знаками Фонда Викимедиа и используются с разрешения Фонда Викимедиа. Мы не поддерживаемся и не связаны с Фондом Викимедиа. + Приложение с открытым исходным кодом, выпущено по лицензии <a href=\"https://github.com/commons-app/apps-android-commons/blob/master/COPYING\">Apache License v2</a>. %1$s и его логотип являются товарными знаками Фонда Викимедиа и используются с разрешения Фонда Викимедиа. Мы не поддерживаемся и не связаны с Фондом Викимедиа. <a href=\"https://github.com/commons-app/apps-android-commons\">Исходный код</a> и <a href=\"https://commons-app.github.io/\">сайт</a> на GitHub. Создайте новый <a href=\"https://github.com/commons-app/apps-android-commons/issues\">запрос на GitHub</a>, чтоб сообщить об ошибке или внести предложение. <a href=\"https://wikimediafoundation.org/wiki/Privacy_policy/ru\">Политика конфиденциальности</a> <a href=\"https://github.com/commons-app/apps-android-commons/blob/master/CREDITS\">Благодарности</a> @@ -153,6 +153,8 @@ Описание Здесь располагается описание носителя информации. Оно потенциально может быть весьма длинным и даже располагаться в несколько строк. Однако мы надеемся, что это выглядит симпатично Дата загрузки + Лицензия + Координаты Стать бета-тестером Подпишитесь на наш канал бета-версии на Google Play и получите ранний доступ к новым функциям и исправлениям ошибок Использовать Викиданные @@ -191,7 +193,7 @@ Руководство Ближайшие места не могут быть отображены без разрешения на геолокацию описание не найдено - Статья на Викискладе + Страница файла на Викискладе Элемент Викиданных Ошибка при кэшировании картинок diff --git a/app/src/main/res/values-sr/strings.xml b/app/src/main/res/values-sr/strings.xml index e59d87719..4d161d896 100644 --- a/app/src/main/res/values-sr/strings.xml +++ b/app/src/main/res/values-sr/strings.xml @@ -75,7 +75,7 @@ Поставке Отвори налог О апликацији - Софтвер отвореног кода доступан под лиценцом <a href=\"https://github.com/commons-app/apps-android-commons/blob/master/COPYING\">Apache вер. 2</a> Викимедијина Остава и њен лого су заштитни знаци Викимедијине Фондације и користе се са дозволом Викимедијине Фондацине. Ми не одобравамо или подржавмо Викимедијину Фондацију. + Софтвер отвореног кода доступан под лиценцом <a href=\"https://github.com/commons-app/apps-android-commons/blob/master/COPYING\">Apache вер. 2</a> Викимедијина Остава и њен лого су заштитни знаци Викимедијине Фондације и користе се са дозволом Викимедијине Фондацине. Ми не одобравамо или подржавмо Викимедијину Фондацију. <a href=\"https://github.com/commons-app/apps-android-commons\">Изворни кôд</a> и <a href=\"https://commons-app.github.io/\">веб-сајт</a> на GitHub-у. Направите нови <a href=\"https://github.com/commons-app/apps-android-commons/issues\">захтев на GitHub-у</a> да бисте пријавили грешке или дали предлоге. <a href=\"https://wikimediafoundation.org/wiki/Privacy_policy\">Политика приватности</a> <a href=\"https://github.com/commons-app/apps-android-commons/blob/master/CREDITS\">Заслуге</a> @@ -184,6 +184,6 @@ Подешавања Повратне информације Одјави ме - Чланак на Остави + Чланак на Остави Чланак на Википодацима diff --git a/app/src/main/res/values-su/strings.xml b/app/src/main/res/values-su/strings.xml index 13e0b0931..fc9da0a9d 100644 --- a/app/src/main/res/values-su/strings.xml +++ b/app/src/main/res/values-su/strings.xml @@ -75,7 +75,7 @@ Séting Daptar Ngeunaan - Pakakas lemes kodeu nembrak dirilis di handapeun <a href=\"https://github.com/commons-app/apps-android-commons/blob/master/COPYING\">Lisénsi Apache v2</a>. Wikimedia Commons sarta logona téh mérk dagang anu Yayasan Wikimédia ogé dipakéna kudu meunang widi ti Yayasan Wikimédia. Kami teu disatujuan ku atawa digawé bareng jeung Yayasan Wikimédia. + Pakakas lemes kodeu nembrak dirilis di handapeun <a href=\"https://github.com/commons-app/apps-android-commons/blob/master/COPYING\">Lisénsi Apache v2</a>. Wikimedia Commons sarta logona téh mérk dagang anu Yayasan Wikimédia ogé dipakéna kudu meunang widi ti Yayasan Wikimédia. Kami teu disatujuan ku atawa digawé bareng jeung Yayasan Wikimédia. <a href=\"https://github.com/commons-app/apps-android-commons\">Sumber</a> sarta <a href=\"https://commons-app.github.io/\">situ wéb</a> dina GitHub. Jieun anyar <a href=\"https://github.com/commons-app/apps-android-commons/issues\">perkara GitHub</a> pikeun saran jeung laporan kutu. <a href=\"https://wikimediafoundation.org/wiki/Privacy_policy\">Kawijakan privasi</a> <a href=\"https://github.com/commons-app/apps-android-commons/blob/master/CREDITS\">Pangajén</a> @@ -187,7 +187,7 @@ Pituduh Tempat sabudeureun teu bisa ditémbongkeun tanpa idin lokasi teu manggihan pedaran - Artikel Common + Artikel Common item Wikidata Kasalahan nalika muat gambar diff --git a/app/src/main/res/values-sv/strings.xml b/app/src/main/res/values-sv/strings.xml index e033133bc..20716949d 100644 --- a/app/src/main/res/values-sv/strings.xml +++ b/app/src/main/res/values-sv/strings.xml @@ -75,7 +75,7 @@ Inställningar Registrera Om - Programvara med öppen källkod släppt under <a href=\"https://github.com/commons-app/apps-android-commons/blob/master/COPYING\">licensen Apache v2</a>. Wikimedia Commons och dess logotyp är varumärken av Wikimedia Foundation och används med tillstånd från Wikimedia Foundation. Vi varken stöds eller är kopplade med Wikimedia Foundation. + Programvara med öppen källkod släppt under <a href=\"https://github.com/commons-app/apps-android-commons/blob/master/COPYING\">licensen Apache v2</a>. %1$s och dess logotyp är varumärken av Wikimedia Foundation och används med tillstånd från Wikimedia Foundation. Vi varken stöds eller är kopplade med Wikimedia Foundation. <a href=\"https://github.com/commons-app/apps-android-commons\">Källkoden</a> och <a href=\"https://commons-app.github.io/\">webbplatsen</a> på GitHub. Skapa ett nytt <a href=\"https://github.com/commons-app/apps-android-commons/issues\">GitHub-ärende</a> för att rapportera buggar och förslag. <a href=\"https://wikimediafoundation.org/wiki/Privacy_policy\">Integritetspolicy</a> <a href=\"https://github.com/commons-app/apps-android-commons/blob/master/CREDITS\">Erkännande</a> @@ -88,6 +88,7 @@ Försök igen Avbryt Denna bild kommer att licensieras under %1$s + Genom att skicka in denna bild intygar jag att detta är mitt eget verk, som inte innehåller upphovsrättsskyddat material eller selfies samt annars följer <a href=\"https://commons.wikimedia.org/wiki/Commons:Policies_and_guidelines\">Wikimedia Commons-policys</a>. Ladda ned Licens Använd föregående titel/beskrivning @@ -149,6 +150,9 @@ Beskrivning Beskrivningen för mediafilen ska vara här. Den kan vara riktig lång och kommer att behöva sträcka sig över flera rader. Vi hoppas i alla fall att det kommer se bra ut. Uppladdningsdatum + Licens + Koordinater + Inte angivet Bli en betatestare Registrera dig på våra betakanal på Google Play och få tidig åtkomst till nya funktioner och buggfixar Använd Wikidata @@ -187,7 +191,7 @@ Guide Platser i närheten kan inte visas utan platsbehörigheter ingen beskrivning hittades - Commons-artikel + Commons-filsida Wikidata-objekt Fel uppstod när bilder cachelagras diff --git a/app/src/main/res/values-tcy/strings.xml b/app/src/main/res/values-tcy/strings.xml index 376ff1034..4ece0c348 100644 --- a/app/src/main/res/values-tcy/strings.xml +++ b/app/src/main/res/values-tcy/strings.xml @@ -1,5 +1,6 @@ + ಕಾಮನ್ಸ್ ಸಂಯೋಜನೆಲು ಸದಸ್ಯೆರ್ನ ಪುದರ್ ಪ್ರವೇಸೊ ಪದೊ @@ -23,7 +24,7 @@ %d ಕಡತ ಅಪ್ಲೊಡ್ ಆವೊಂದುಂಡು %d ಕಡತೊಲು ಅಪ್ಲೋಡ್ ಆವೊಂದುಂಡು - ಎನ್ನ ದಿಂಜಯೀನಾ ವಿಚಾರೊಳು + ಎನ್ನ ದಿಂಜಯೀನಾ ವಿಚಾರೊಳು ದಿಂಜೊಂತುಂಡು ದಿಂಜಿಜಿ %1$d%% ಮುಗಿಂಡ್ @@ -48,6 +49,7 @@ ಎಂಕ್ಲೆನ ಬಗ್ಗೆ ನನೊರ ಪ್ರಯತ್ನ ಮಾನ್ಪುಲೇ ವಜಾ ಮಲ್ಪುಲೆ + ಡೌನ್‍ಲೋಡ್ ಪರವಾನಗಿ ಕತ್ತಲೆದ ಕ್ರಮೊ CC0 @@ -63,6 +65,7 @@ CC BY 3.0 CC BY-SA 4.0 CC BY 4.0 + CC Zero ಅಂದ್! ವರ್ಗೊಲು ದಿಂಜಾವೊಂದುಂಡು…… @@ -73,4 +76,16 @@ ಅಂದ್ ಅತ್ತ್ ತರೆಬರವು + ವಿವರಣೆ + ಪರವಾನಿಗೆ + ವಜಾ ಮಲ್ಪುಲೆ + ತೋಜಾಲೇ + ಮುಚ್ಚಿಲೆ + ಮುಖ್ಯಪುಟೊ + ದಿಂಜಾಲೆ + ಕೈತಲ್‍ದ + ಎಂಕ್ಲೆನ ಬಗ್ಗೆ + ಸಂಯೋಜನೆಲು + ಅಬಿಪ್ರಾಯೊ + ನಿರ್ಗಮಿಸಾಲೆ diff --git a/app/src/main/res/values-th/error.xml b/app/src/main/res/values-th/error.xml new file mode 100644 index 000000000..bdacb80a8 --- /dev/null +++ b/app/src/main/res/values-th/error.xml @@ -0,0 +1,7 @@ + + + คอมมอนส์หยุดทำงาน + อ๊ะ มีบางอย่างผิดพลาดไป! + บอกให้เราทราบว่าคุณกำลังทำอะไรอยู่ แล้วแบ่งปันให้เราผ่านทางอีเมล จะได้ช่วยเราแก้ไขได้! + ขอบคุณ! + diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml index 5c92238f7..d7229008e 100644 --- a/app/src/main/res/values-tr/strings.xml +++ b/app/src/main/res/values-tr/strings.xml @@ -107,4 +107,6 @@ Açıklama yok Bilinmeyen lisans Yenile + Lisans + Koordinatlar diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml index 57a64218f..b6d7d46f3 100644 --- a/app/src/main/res/values-uk/strings.xml +++ b/app/src/main/res/values-uk/strings.xml @@ -83,7 +83,7 @@ Налаштування Зареєструватися Про програму - Програмне забезпечення з відкритим кодом випущено під <a href=\"https://github.com/commons-app/apps-android-commons/blob/master/COPYING\">ліцензією Apache в.2</a>. Вікісховище і його логотип є товарними знаками Фонду Вікімедіа і використовуються за дозволом Фонду Вікімедіа. Ми не користуємось підтримкою Фонду Вікімедіа і не є його афіліатом. + Програмне забезпечення з відкритим кодом випущено під <a href=\"https://github.com/commons-app/apps-android-commons/blob/master/COPYING\">ліцензією Apache в.2</a>. Вікісховище і його логотип є товарними знаками Фонду Вікімедіа і використовуються за дозволом Фонду Вікімедіа. Ми не користуємось підтримкою Фонду Вікімедіа і не є його афіліатом. <a href=\"https://github.com/commons-app/apps-android-commons\">Вихідний код</a> і <a href=\"https://commons-app.github.io/\">веб-сайт</a> на GitHub. Створіть нове <a href=\"https://github.com/commons-app/apps-android-commons/issues\">завдання на GitHub</a> для повідомлення про баги або для висловлення пропозицій. <a href=\"https://wikimediafoundation.org/wiki/Privacy_policy\">Політика приватності</a> <a href=\"https://github.com/commons-app/apps-android-commons/blob/master/CREDITS\">Автори</a> @@ -157,6 +157,9 @@ Опис Сюди потрапляє опис медіафайлу. Він потенційно може бути досить довгим і розтягнутися на декілька рядків. Однак ми сподіваємось, що він виглядатиме гарно. Дата завантаження + Ліцензія + Координати + Не передбачено Станьте бета-тестером Увійдіть на наш бета-канал на Google Play і отримайте ранній доступ до нових функцій та виправлень багів Використати Вікідані @@ -195,6 +198,6 @@ Посібник Місця поблизу неможливо показати без дозволу на визначення місця розташування. опис не знайдено - Стаття на Вікісховищі + Стаття на Вікісховищі Елемент Вікіданих diff --git a/app/src/main/res/values-vi/strings.xml b/app/src/main/res/values-vi/strings.xml index 494e094f7..197f88c26 100644 --- a/app/src/main/res/values-vi/strings.xml +++ b/app/src/main/res/values-vi/strings.xml @@ -20,7 +20,6 @@ Đang hoàn thành việc tải lên tập tin %1$s Tải lên tập tin %1$s thất bại Chạm để xem - %d tập tin đang được tải lên Tập tin do tôi tải lên Đang chờ Thất bại @@ -51,8 +50,6 @@ Chưa tải lên tập tin %d tập tin tải lên - Đang bắt đầu tải lên %d tập tin - %d tập tin tải lên Không tìm thấy thể loại khớp với %1$s Xếp các hình ảnh vào thể loại để cho chúng dễ tìm kiếm hơn trên Wikimedia Commons.\n\nHãy bắt đầu nhập tên thể loại để tìm kiếm.\nChạm vào thông điệp này (hoặc bấm Quay lại) để bỏ qua bước này. Thể loại @@ -61,7 +58,7 @@ Cài đặt Mở tài khoản Giới thiệu - Phần mềm mã nguồn mở được phát hành theo <a href=\"https://github.com/commons-app/apps-android-commons/blob/master/COPYING\">Giấy phép Apache v2</a>. Wikimedia Commons và biểu trưng của nó là nhãn hiệu của Quỹ Wikimedia và được sử dụng do Quỹ Wikimedia cho phép. Chúng tôi không được Quỹ Wikimedia ủng hộ hoặc nhận làm chi nhánh. + Phần mềm mã nguồn mở được phát hành theo <a href=\"https://github.com/commons-app/apps-android-commons/blob/master/COPYING\">Giấy phép Apache v2</a>. Wikimedia Commons và biểu trưng của nó là nhãn hiệu của Quỹ Wikimedia và được sử dụng do Quỹ Wikimedia cho phép. Chúng tôi không được Quỹ Wikimedia ủng hộ hoặc nhận làm chi nhánh. <a href=\"https://github.com/commons-app/apps-android-commons\">Mã nguồn</a> và <a href=\"https://commons-app.github.io/\">trang chủ</a> tại GitHub. <a href=\"https://github.com/commons-app/apps-android-commons/issues\">Tạo vấn đề GitHub mới</a> để báo cáo lỗi hoặc gợi ý thay đổi. <a href=\"https://github.com/commons-app/apps-android-commons/blob/master/CREDITS\">CÔNG TRẠNG</a> diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index a0c245ccf..55c983886 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -75,7 +75,7 @@ 設定 註冊 關於 - 以<a href=\"https://github.com/commons-app/apps-android-commons/blob/master/COPYING\">Apache許可證 v2</a>釋放的開放源碼軟體。Wikimedia Commons和其標誌圖像是維基媒體基金會的標記;並在維基媒體基金會的許可下使用。我們並非由維基媒體基金會所認可、也不隸屬於維基媒體基金會。 + 以<a href=\"https://github.com/commons-app/apps-android-commons/blob/master/COPYING\">Apache許可證 v2</a>釋放的開放源碼軟體。%1$s和其標誌圖像是維基媒體基金會的標記;並在維基媒體基金會的許可下使用。我們並非由維基媒體基金會所認可、也不隸屬於維基媒體基金會。 <a href=\"https://github.com/commons-app/apps-android-commons\">原始碼</a>和<a href=\"https://commons-app.github.io/\">網站</a>位於GitHub上。建立一個新的<a href=\"https://github.com/commons-app/apps-android-commons/issues\">GitHub問題</a>來回報問題和提出建議。 <a href=\"https://meta.wikimedia.org/wiki/Privacy_policy/zh\">隱私政策</a> <a href=\"https://github.com/commons-app/apps-android-commons/blob/master/CREDITS\">製作群</a> @@ -88,6 +88,7 @@ 重試 取消 此圖片會按 %1$s 協議授權上載 + 透過提交此圖片,我宣佈這是我個人創作的成品,且不包含受版權保護或自拍內容,並除此之外遵守<a href=\"https://commons.wikimedia.org/wiki/Commons:Policies_and_guidelines\">維基媒體共享資源方針</a>。 下載 協議授權 使用先前標題/描述 @@ -149,6 +150,9 @@ 描述 描述使用在此的媒體。若內容可能會很長的話,請斷開換行。我們希望這樣可以讓內容看起來較好些。 上傳日期 + 授權協議 + 座標 + 未提供 成為測試人員 選擇加入我們在 Google Play 上的 beta channel 來早期獲得新功能並修正程式臭蟲 使用維基數據 @@ -187,7 +191,7 @@ 教程 附近地點需要位置權限才可顯示 找不到描述 - 共享資源條目 + 共享資源檔案頁面 維基數據項目 在快取圖片時發生錯誤 diff --git a/app/src/main/res/values-zh/strings.xml b/app/src/main/res/values-zh/strings.xml index bb4a5ac8d..0d03da14f 100644 --- a/app/src/main/res/values-zh/strings.xml +++ b/app/src/main/res/values-zh/strings.xml @@ -75,7 +75,7 @@ 设置 注册 关于 - 本开源软件采用<a href=\"https://github.com/commons-app/apps-android-commons/blob/master/COPYING\">Apache许可证第二版</a>授权。Wikimedia Commons及其标志是维基媒体基金会的商标,并在维基媒体基金会的许可下使用。我们并不被维基媒体基金会认可,也不与基金会有任何联系。 + 本开源软件采用<a href=\"https://github.com/commons-app/apps-android-commons/blob/master/COPYING\">Apache许可证第二版</a>授权。%1$s及其标志是维基媒体基金会的商标,并在维基媒体基金会的许可下使用。我们并不被维基媒体基金会认可,也不与基金会有任何联系。 <a href=\"https://github.com/commons-app/apps-android-commons\">源代码</a>和<a href=\"https://commons-app.github.io/\">网站</a>位于GitHub。创建新的<a href=\"https://github.com/commons-app/apps-android-commons/issues\">GitHub问题</a>以发送错误报告和建议。 <a href=\"https://wikimediafoundation.org/wiki/Privacy_policy\">隐私政策</a> <a href=\"https://github.com/commons-app/apps-android-commons/blob/master/CREDITS\">制作人员</a> @@ -88,6 +88,7 @@ 重试 取消 该图像会采用%1$s授权 + 通过提交该图片,我声明这是我自己的作品,其不包含受版权保护的材料或自拍像,并遵循<a href=\"https://commons.wikimedia.org/wiki/Commons:Policies_and_guidelines\">维基共享资源</a>方针。 下载 许可协议 使用之前的标题/描述 @@ -149,6 +150,9 @@ 说明 在此填写媒体的说明。这可能会相当长,并将需要包裹在多行中。我们希望它看起来很好。 上传日期 + 许可协议 + 坐标 + 未提供 成为测试版的测试者 加入我们在Google Play上的测试频道,并更早获取新功能以及错误修复 使用维基数据 @@ -187,7 +191,7 @@ 教程 附近地点不能在没有位置权限的情况下显示 找不到描述 - 共享资源条目 + 共享资源文件页面 维基数据项 缓存图片时出错 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 3b5b8307e..811d59e65 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -79,7 +79,8 @@ Tap this message (or hit back) to skip this step. Settings Sign Up About - Open Source software released under the <a href=\"https://github.com/commons-app/apps-android-commons/blob/master/COPYING\">Apache License v2</a>. Wikimedia Commons and its logo are trademarks of the Wikimedia Foundation and are used with the permission of the Wikimedia Foundation. We are not endorsed by or affiliated with the Wikimedia Foundation. + Open Source software released under the <a href=\"https://github.com/commons-app/apps-android-commons/blob/master/COPYING\">Apache License v2</a>. %1$s and its logo are trademarks of the Wikimedia Foundation and are used with the permission of the Wikimedia Foundation. We are not endorsed by or affiliated with the Wikimedia Foundation. + Wikimedia Commons <a href=\"https://github.com/commons-app/apps-android-commons\">Source</a> and <a href=\"https://commons-app.github.io/\">website</a> on GitHub. Create a new <a href=\"https://github.com/commons-app/apps-android-commons/issues\">GitHub issue</a> for bug reports and suggestions. <a href=\"https://wikimediafoundation.org/wiki/Privacy_policy\">Privacy policy</a> <a href=\"https://github.com/commons-app/apps-android-commons/blob/master/CREDITS\">Credits</a> @@ -92,6 +93,7 @@ Tap this message (or hit back) to skip this step. Retry Cancel This image will be licensed under %1$s + By submitting this picture, I declare that this is my own work, that it does not contain copyrighted material or selfies, and otherwise adheres to <a href=\"https://commons.wikimedia.org/wiki/Commons:Policies_and_guidelines\">Wikimedia Commons policies</a>. Download License Use previous title/description @@ -196,11 +198,17 @@ Tap this message (or hit back) to skip this step. Feedback Logout Tutorial + Developer plans Nearby places cannot be displayed without location permissions no description found - Commons Article + Commons file page Wikidata item - Error while caching pictures + Error while caching pictures + Feedback wanted + We are planning several new features and improvements for the app! Would you like to review them and provide feedback? \n\n(You can always access this by selecting "Developer plans" in the navigation drawer) + No thanks + Sure, take me there! + https://meta.wikimedia.org/wiki/Grants:Project/Improve_\'Upload_to_Commons\'_Android_App/Renewal/User_feedback diff --git a/app/src/test/java/fr/free/nrw/commons/LatLngTests.java b/app/src/test/java/fr/free/nrw/commons/LatLngTests.java index aed97c58c..c2fb1b159 100644 --- a/app/src/test/java/fr/free/nrw/commons/LatLngTests.java +++ b/app/src/test/java/fr/free/nrw/commons/LatLngTests.java @@ -1,12 +1,12 @@ package fr.free.nrw.commons; -import static org.hamcrest.CoreMatchers.is; - -import fr.free.nrw.commons.location.LatLng; - import org.junit.Assert; import org.junit.Test; +import fr.free.nrw.commons.location.LatLng; + +import static org.hamcrest.CoreMatchers.is; + public class LatLngTests { @Test public void testZeroZero() { LatLng place = new LatLng(0, 0, 0); diff --git a/app/src/test/java/fr/free/nrw/commons/LengthUtilsTest.java b/app/src/test/java/fr/free/nrw/commons/LengthUtilsTest.java index 3fdeafc40..561f3f0e6 100644 --- a/app/src/test/java/fr/free/nrw/commons/LengthUtilsTest.java +++ b/app/src/test/java/fr/free/nrw/commons/LengthUtilsTest.java @@ -1,12 +1,12 @@ package fr.free.nrw.commons; -import static org.hamcrest.CoreMatchers.is; +import org.junit.Assert; +import org.junit.Test; import fr.free.nrw.commons.location.LatLng; import fr.free.nrw.commons.utils.LengthUtils; -import org.junit.Assert; -import org.junit.Test; +import static org.hamcrest.CoreMatchers.is; public class LengthUtilsTest { @Test public void testZeroDistance() { diff --git a/app/src/test/java/fr/free/nrw/commons/UtilsFixExtensionTest.java b/app/src/test/java/fr/free/nrw/commons/UtilsFixExtensionTest.java index de0a90f4b..186f30df9 100644 --- a/app/src/test/java/fr/free/nrw/commons/UtilsFixExtensionTest.java +++ b/app/src/test/java/fr/free/nrw/commons/UtilsFixExtensionTest.java @@ -1,10 +1,10 @@ package fr.free.nrw.commons; -import static org.hamcrest.CoreMatchers.is; - import org.junit.Assert; import org.junit.Test; +import static org.hamcrest.CoreMatchers.is; + public class UtilsFixExtensionTest { @Test public void jpegResultsInJpg() { diff --git a/app/src/test/java/fr/free/nrw/commons/nearby/NearbyAdapterFactoryTest.java b/app/src/test/java/fr/free/nrw/commons/nearby/NearbyAdapterFactoryTest.java index 0ef58f873..76125aa43 100644 --- a/app/src/test/java/fr/free/nrw/commons/nearby/NearbyAdapterFactoryTest.java +++ b/app/src/test/java/fr/free/nrw/commons/nearby/NearbyAdapterFactoryTest.java @@ -22,10 +22,11 @@ import fr.free.nrw.commons.BuildConfig; import fr.free.nrw.commons.R; import fr.free.nrw.commons.location.LatLng; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; @RunWith(RobolectricTestRunner.class) -@Config(constants = BuildConfig.class) +@Config(constants = BuildConfig.class, sdk = 21) public class NearbyAdapterFactoryTest { private static final Place PLACE = new Place("name", Place.Description.AIRPORT, @@ -112,14 +113,6 @@ public class NearbyAdapterFactoryTest { assertEquals(PLACE, clickedPlace); } - @Test - public void clickViewHandlesMisconfiguredListener() { - NearbyAdapterFactory testObject = new NearbyAdapterFactory(null); - RVRendererAdapter result = testObject.create(Collections.singletonList(PLACE)); - RendererViewHolder viewHolder = renderComponent(result); - viewHolder.itemView.performClick(); - } - @NonNull private RendererViewHolder renderComponent(RVRendererAdapter result) { FrameLayout viewGroup = new FrameLayout(RuntimeEnvironment.application); diff --git a/build.gradle b/build.gradle index 4929fec36..ebdb2fa23 100644 --- a/build.gradle +++ b/build.gradle @@ -8,6 +8,7 @@ buildscript { classpath "com.android.tools.build:gradle:${project.gradleVersion}" classpath 'com.dicedmelon.gradle:jacoco-android:0.1.1' classpath 'com.getkeepsafe.dexcount:dexcount-gradle-plugin:0.7.1' + classpath 'me.tatarka:gradle-retrolambda:3.6.1' } } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 05ef575b0..7d2af2435 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index c8d3575db..4dde7c991 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,5 @@ - distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.0-rc-1-all.zip \ No newline at end of file +distributionUrl=https\://services.gradle.org/distributions/gradle-4.0.1-bin.zip diff --git a/gradlew b/gradlew index 9d82f7891..cccdd3d51 100755 --- a/gradlew +++ b/gradlew @@ -1,4 +1,4 @@ -#!/usr/bin/env bash +#!/usr/bin/env sh ############################################################################## ## @@ -6,42 +6,6 @@ ## ############################################################################## -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS="" - -APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` - -# Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" - -warn ( ) { - echo "$*" -} - -die ( ) { - echo - echo "$*" - echo - exit 1 -} - -# OS specific support (must be 'true' or 'false'). -cygwin=false -msys=false -darwin=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MINGW* ) - msys=true - ;; -esac - # Attempt to set APP_HOME # Resolve links: $0 may be a link PRG="$0" @@ -60,6 +24,46 @@ cd "`dirname \"$PRG\"`/" >/dev/null APP_HOME="`pwd -P`" cd "$SAVED" >/dev/null +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar # Determine the Java command to use to start the JVM. @@ -85,7 +89,7 @@ location of your Java installation." fi # Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then MAX_FD_LIMIT=`ulimit -H -n` if [ $? -eq 0 ] ; then if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then @@ -150,11 +154,19 @@ if $cygwin ; then esac fi -# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules -function splitJvmOpts() { - JVM_OPTS=("$@") +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " } -eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS -JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" +APP_ARGS=$(save "$@") -exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong +if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then + cd "$(dirname "$0")" +fi + +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat index aec99730b..e95643d6a 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -8,14 +8,14 @@ @rem Set local scope for the variables with windows NT shell if "%OS%"=="Windows_NT" setlocal -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS= - set DIRNAME=%~dp0 if "%DIRNAME%" == "" set DIRNAME=. set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + @rem Find java.exe if defined JAVA_HOME goto findJavaFromJavaHome @@ -46,10 +46,9 @@ echo location of your Java installation. goto fail :init -@rem Get command-line arguments, handling Windowz variants +@rem Get command-line arguments, handling Windows variants if not "%OS%" == "Windows_NT" goto win9xME_args -if "%@eval[2+2]" == "4" goto 4NT_args :win9xME_args @rem Slurp the command line arguments. @@ -60,11 +59,6 @@ set _SKIP=2 if "x%~1" == "x" goto execute set CMD_LINE_ARGS=%* -goto execute - -:4NT_args -@rem Get arguments from the 4NT Shell from JP Software -set CMD_LINE_ARGS=%$ :execute @rem Setup the command line