From 26fc6cf9fe8724e8d68f4f56855088082867e775 Mon Sep 17 00:00:00 2001 From: Suchit Kar Date: Sat, 17 Feb 2018 00:23:36 +0530 Subject: [PATCH 01/48] Fix alignment in category search for right to left language locales --- app/src/main/res/layout/fragment_categorization.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/src/main/res/layout/fragment_categorization.xml b/app/src/main/res/layout/fragment_categorization.xml index fa258768b..e49396b37 100644 --- a/app/src/main/res/layout/fragment_categorization.xml +++ b/app/src/main/res/layout/fragment_categorization.xml @@ -24,6 +24,7 @@ android:layout_width="match_parent" android:hint="@string/categories_search_text_hint" android:maxLines="1" + android:gravity="left" android:inputType="textCapWords" android:imeOptions="flagNoExtractUi" /> @@ -36,7 +37,7 @@ android:indeterminateOnly="true" android:layout_marginRight="@dimen/tiny_gap" android:layout_marginEnd="@dimen/tiny_gap" - android:layout_gravity="center_vertical|right|end" + android:layout_gravity="center_vertical|right" style="?android:progressBarStyleSmall" android:visibility="gone" /> From 88f0e65bcccf8bbf1008199d8e8e4ed76689b862 Mon Sep 17 00:00:00 2001 From: Suchit Kar Date: Tue, 20 Feb 2018 18:35:45 +0530 Subject: [PATCH 02/48] Fix crash while setting Title and Description in RTL languages --- .../commons/upload/SingleUploadFragment.java | 77 +++++++++++++------ 1 file changed, 54 insertions(+), 23 deletions(-) diff --git a/app/src/main/java/fr/free/nrw/commons/upload/SingleUploadFragment.java b/app/src/main/java/fr/free/nrw/commons/upload/SingleUploadFragment.java index 099790495..8343f9861 100644 --- a/app/src/main/java/fr/free/nrw/commons/upload/SingleUploadFragment.java +++ b/app/src/main/java/fr/free/nrw/commons/upload/SingleUploadFragment.java @@ -5,10 +5,12 @@ import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.graphics.Color; +import android.graphics.drawable.Drawable; import android.net.Uri; import android.os.Bundle; import android.preference.PreferenceManager; import android.support.annotation.NonNull; +import android.support.v4.view.ViewCompat; import android.support.v7.app.AlertDialog; import android.text.Editable; import android.text.TextWatcher; @@ -228,35 +230,64 @@ public class SingleUploadFragment extends CommonsDaggerSupportFragment { */ @OnTouch(R.id.titleEdit) boolean titleInfo(View view, MotionEvent motionEvent) { - //Should replace right with end to support different right-to-left languages as well - final int value = titleEdit.getRight() - titleEdit.getCompoundDrawables()[2].getBounds().width(); - - if (motionEvent.getAction() == ACTION_UP && motionEvent.getRawX() >= value) { - new AlertDialog.Builder(getContext()) - .setTitle(R.string.media_detail_title) - .setMessage(R.string.title_info) - .setCancelable(true) - .setNeutralButton(android.R.string.ok, (dialog, id) -> dialog.cancel()) - .create() - .show(); - return true; + final int value; + if (ViewCompat.getLayoutDirection(getView()) == ViewCompat.LAYOUT_DIRECTION_LTR) { + value = titleEdit.getRight() - titleEdit.getCompoundDrawables()[2].getBounds().width(); + if (motionEvent.getAction() == ACTION_UP && motionEvent.getRawX() >= value) { + new AlertDialog.Builder(getContext()) + .setTitle(R.string.media_detail_title) + .setMessage(R.string.title_info) + .setCancelable(true) + .setNeutralButton(android.R.string.ok, (dialog, id) -> dialog.cancel()) + .create() + .show(); + return true; + } + } + else { + value = titleEdit.getLeft() + titleEdit.getCompoundDrawables()[0].getBounds().width(); + if (motionEvent.getAction() == ACTION_UP && motionEvent.getRawX() <= value) { + new AlertDialog.Builder(getContext()) + .setTitle(R.string.media_detail_title) + .setMessage(R.string.title_info) + .setCancelable(true) + .setNeutralButton(android.R.string.ok, (dialog, id) -> dialog.cancel()) + .create() + .show(); + return true; + } } return false; } @OnTouch(R.id.descEdit) boolean descriptionInfo(View view, MotionEvent motionEvent) { - final int value = descEdit.getRight() - descEdit.getCompoundDrawables()[2].getBounds().width(); - - if (motionEvent.getAction() == ACTION_UP && motionEvent.getRawX() >= value) { - new AlertDialog.Builder(getContext()) - .setTitle(R.string.media_detail_description) - .setMessage(R.string.description_info) - .setCancelable(true) - .setNeutralButton(android.R.string.ok, (dialog, id) -> dialog.cancel()) - .create() - .show(); - return true; + final int value; + if (ViewCompat.getLayoutDirection(getView()) == ViewCompat.LAYOUT_DIRECTION_LTR) { + value = descEdit.getRight() - descEdit.getCompoundDrawables()[2].getBounds().width(); + if (motionEvent.getAction() == ACTION_UP && motionEvent.getRawX() >= value) { + new AlertDialog.Builder(getContext()) + .setTitle(R.string.media_detail_description) + .setMessage(R.string.description_info) + .setCancelable(true) + .setNeutralButton(android.R.string.ok, (dialog, id) -> dialog.cancel()) + .create() + .show(); + return true; + } + } + else{ + value = descEdit.getLeft() + descEdit.getCompoundDrawables()[0].getBounds().width(); + if (motionEvent.getAction() == ACTION_UP && motionEvent.getRawX() <= value) { + new AlertDialog.Builder(getContext()) + .setTitle(R.string.media_detail_description) + .setMessage(R.string.description_info) + .setCancelable(true) + .setNeutralButton(android.R.string.ok, (dialog, id) -> dialog.cancel()) + .create() + .show(); + return true; + } } return false; } From 979e4076568489fa7e80bf16c2d5999513a8c8d6 Mon Sep 17 00:00:00 2001 From: hismaeel Date: Tue, 20 Feb 2018 18:14:00 -0500 Subject: [PATCH 03/48] issue #1130 (b) --- .../fr/free/nrw/commons/media/MediaDetailFragment.java | 8 +++++++- app/src/main/res/values/strings.xml | 1 + 2 files changed, 8 insertions(+), 1 deletion(-) 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 ecf3cedb1..70bf281dc 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 @@ -14,6 +14,7 @@ import android.view.ViewTreeObserver; import android.widget.LinearLayout; import android.widget.ScrollView; import android.widget.TextView; +import android.widget.Toast; import java.io.IOException; import java.text.SimpleDateFormat; @@ -273,7 +274,12 @@ public class MediaDetailFragment extends CommonsDaggerSupportFragment { } private void setOnClickListeners(final Media media) { - license.setOnClickListener(v -> openWebBrowser(licenseLink(media))); + if (licenseLink(media) != null) { + license.setOnClickListener(v -> openWebBrowser(licenseLink(media))); + } else { + Toast toast = Toast.makeText(getContext(), getString(R.string.null_url), Toast.LENGTH_SHORT); + toast.show(); + } if (media.getCoordinates() != null) { coordinates.setOnClickListener(v -> openMap(media.getCoordinates())); } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index ceba924e1..e7054b232 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -211,6 +211,7 @@ Send log file Send log file to developers via email Login to your account + Error! URL not found Location has not changed. Location not available. From f284a00de213c0b46612dabbe16d3bf43f63fbc6 Mon Sep 17 00:00:00 2001 From: Vishan Seru Date: Sun, 15 Oct 2017 10:22:01 +0530 Subject: [PATCH 04/48] Made changes to ensure that when attempting to upload multiple images, the GPS data is extracted and attached correctly. --- .../commons/contributions/Contribution.java | 5 ++ .../fr/free/nrw/commons/upload/FileUtils.java | 41 +++++++++- .../commons/upload/MultipleShareActivity.java | 80 +++++++++++++++++-- 3 files changed, 118 insertions(+), 8 deletions(-) diff --git a/app/src/main/java/fr/free/nrw/commons/contributions/Contribution.java b/app/src/main/java/fr/free/nrw/commons/contributions/Contribution.java index 00baac847..7861f96de 100644 --- a/app/src/main/java/fr/free/nrw/commons/contributions/Contribution.java +++ b/app/src/main/java/fr/free/nrw/commons/contributions/Contribution.java @@ -197,6 +197,10 @@ public class Contribution extends Media { this.localUri = localUri; } + public void setDecimalCoords(String decimalCoords) { + this.decimalCoords = decimalCoords; + } + @NonNull private String licenseTemplateFor(String license) { switch (license) { @@ -215,6 +219,7 @@ public class Contribution extends Media { case Prefs.Licenses.CC_BY_SA: return "{{self|cc-by-sa-3.0}}"; } + throw new RuntimeException("Unrecognized license value: " + license); } } diff --git a/app/src/main/java/fr/free/nrw/commons/upload/FileUtils.java b/app/src/main/java/fr/free/nrw/commons/upload/FileUtils.java index 0026a6ce0..3f74dea61 100644 --- a/app/src/main/java/fr/free/nrw/commons/upload/FileUtils.java +++ b/app/src/main/java/fr/free/nrw/commons/upload/FileUtils.java @@ -3,21 +3,27 @@ package fr.free.nrw.commons.upload; import android.annotation.SuppressLint; import android.content.ContentUris; import android.content.Context; +import android.content.SharedPreferences; import android.database.Cursor; import android.net.Uri; import android.os.Build; import android.os.Environment; +import android.os.ParcelFileDescriptor; +import android.preference.PreferenceManager; import android.provider.DocumentsContract; import android.provider.MediaStore; import android.support.annotation.NonNull; import android.support.annotation.Nullable; +import java.io.File; import java.io.FileDescriptor; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.nio.channels.FileChannel; +import java.util.Date; +import fr.free.nrw.commons.CommonsApplication; import timber.log.Timber; public class FileUtils { @@ -85,8 +91,41 @@ public class FileUtils { // File else if ("file".equalsIgnoreCase(uri.getScheme())) { return uri.getPath(); + } else { + //fetching path may fail depending on the source URI and all hope is lost + //so we will create and use a copy of the file, which seems to work + String copyPath = null; + try { + ParcelFileDescriptor descriptor + = context.getContentResolver().openFileDescriptor(uri, "r"); + if (descriptor != null) { + SharedPreferences sharedPref = PreferenceManager + .getDefaultSharedPreferences(CommonsApplication.getInstance()); + boolean useExtStorage = sharedPref.getBoolean("useExternalStorage", true); + if (useExtStorage) { + copyPath = Environment.getExternalStorageDirectory().toString() + + "/CommonsApp/" + new Date().getTime() + ".jpg"; + File newFile = new File(Environment.getExternalStorageDirectory().toString() + "/CommonsApp"); + newFile.mkdir(); + FileUtils.copy( + descriptor.getFileDescriptor(), + copyPath); + Timber.d("Filepath (copied): %s", copyPath); + return copyPath; + } + copyPath = context.getCacheDir().getAbsolutePath() + + "/" + new Date().getTime() + ".jpg"; + FileUtils.copy( + descriptor.getFileDescriptor(), + copyPath); + Timber.d("Filepath (copied): %s", copyPath); + return copyPath; + } + } catch (IOException e) { + Timber.w(e, "Error in file " + copyPath); + return null; + } } - return null; } 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 a41938cf7..ac0afa979 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,7 +11,9 @@ import android.database.DataSetObserver; import android.net.Uri; import android.os.Build; import android.os.Bundle; +import android.os.ParcelFileDescriptor; import android.support.annotation.NonNull; +import android.support.annotation.Nullable; import android.support.v4.app.ActivityCompat; import android.support.v4.app.FragmentManager; import android.support.v4.content.ContextCompat; @@ -21,6 +23,7 @@ import android.view.inputmethod.InputMethodManager; import android.widget.AdapterView; import android.widget.Toast; +import java.io.FileNotFoundException; import java.util.ArrayList; import java.util.List; @@ -51,11 +54,17 @@ public class MultipleShareActivity extends AuthenticatedActivity MultipleUploadListFragment.OnMultipleUploadInitiatedHandler, OnCategoriesSaveHandler { - @Inject MediaWikiApi mwApi; - @Inject SessionManager sessionManager; - @Inject UploadController uploadController; - @Inject ModifierSequenceDao modifierSequenceDao; - @Inject @Named("default_preferences") SharedPreferences prefs; + @Inject + MediaWikiApi mwApi; + @Inject + SessionManager sessionManager; + @Inject + UploadController uploadController; + @Inject + ModifierSequenceDao modifierSequenceDao; + @Inject + @Named("default_preferences") + SharedPreferences prefs; private ArrayList photosList = null; @@ -63,6 +72,8 @@ public class MultipleShareActivity extends AuthenticatedActivity private MediaDetailPagerFragment mediaDetails; private CategorizationFragment categorizationFragment; + private boolean locationPermitted = false; + @Override public Media getMediaAtPosition(int i) { return photosList.get(i); @@ -207,6 +218,14 @@ public class MultipleShareActivity extends AuthenticatedActivity getSupportFragmentManager().addOnBackStackChangedListener(this); requestAuthToken(); + + //TODO: 15/10/17 should location permission be explicitly requested if not provided? + //check if location permission is enabled + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + if (ContextCompat.checkSelfPermission(this,Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) { + locationPermitted = true; + } + } } @Override @@ -240,7 +259,7 @@ public class MultipleShareActivity extends AuthenticatedActivity mwApi.setAuthCookie(authCookie); Intent intent = getIntent(); - if (intent.getAction().equals(Intent.ACTION_SEND_MULTIPLE)) { + if (Intent.ACTION_SEND_MULTIPLE.equals(intent.getAction())) { if (photosList == null) { photosList = new ArrayList<>(); ArrayList urisList = intent.getParcelableArrayListExtra(Intent.EXTRA_STREAM); @@ -252,6 +271,11 @@ public class MultipleShareActivity extends AuthenticatedActivity up.setTag("sequence", i); up.setSource(Contribution.SOURCE_EXTERNAL); up.setMultiple(true); + String imageGpsCoordinates = extractImageGpsData(uri); + if (imageGpsCoordinates != null) { + Timber.d("GPS data for image found!"); + up.setDecimalCoords(imageGpsCoordinates); + } photosList.add(up); } } @@ -278,7 +302,49 @@ public class MultipleShareActivity extends AuthenticatedActivity @Override public void onBackStackChanged() { - getSupportActionBar().setDisplayHomeAsUpEnabled(mediaDetails != null && mediaDetails.isVisible()) ; + getSupportActionBar().setDisplayHomeAsUpEnabled(mediaDetails != null && mediaDetails.isVisible()); } + /** + * Will attempt to extract the gps coordinates using exif data or by using the current + * location if available for the image who's imageUri has been provided. + * @param imageUri The uri of the image who's GPS coordinates data we wish to extract + * @return GPS coordinates as a String as is returned by {@link GPSExtractor} + */ + @Nullable + private String extractImageGpsData(Uri imageUri) { + Timber.d("Entering extractImagesGpsData"); + + if (imageUri == null) { + //now why would you do that??? + return null; + } + + GPSExtractor gpsExtractor = null; + + try { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + ParcelFileDescriptor fd = getContentResolver().openFileDescriptor(imageUri,"r"); + if (fd != null) { + gpsExtractor = new GPSExtractor(fd.getFileDescriptor(),this,prefs); + } + } else { + String filePath = FileUtils.getPath(this,imageUri); + if (filePath != null) { + gpsExtractor = new GPSExtractor(filePath,this,prefs); + } + } + + if (gpsExtractor != null) { + //get image coordinates from exif data or user location + return gpsExtractor.getCoords(locationPermitted); + } + + } catch (FileNotFoundException fnfe) { + Timber.w(fnfe); + return null; + } + + return null; + } } \ No newline at end of file From 370a13b7112c0ecbc4ca604a9cf5d986fe317c20 Mon Sep 17 00:00:00 2001 From: junkiattan Date: Mon, 5 Feb 2018 21:41:10 +0800 Subject: [PATCH 05/48] Resolved xml errors in string tags by inserting false formatted attribute --- .../res/layout/fragment_categorization.xml | 3 +- .../layout/fragment_similar_image_dialog.xml | 57 +++++++++++++++++++ app/src/main/res/values-ast/strings.xml | 4 +- app/src/main/res/values-b+sr+Latn/strings.xml | 2 +- app/src/main/res/values-bn/strings.xml | 2 +- app/src/main/res/values-ca/strings.xml | 2 +- app/src/main/res/values-cs/strings.xml | 4 +- app/src/main/res/values-da/strings.xml | 4 +- app/src/main/res/values-de/strings.xml | 4 +- app/src/main/res/values-el/strings.xml | 4 +- app/src/main/res/values-es/strings.xml | 4 +- app/src/main/res/values-fa/strings.xml | 2 +- app/src/main/res/values-fi/strings.xml | 2 +- app/src/main/res/values-fr/strings.xml | 2 +- app/src/main/res/values-gl/strings.xml | 2 +- app/src/main/res/values-hi/strings.xml | 3 +- app/src/main/res/values-hu/strings.xml | 2 +- app/src/main/res/values-is/strings.xml | 2 +- app/src/main/res/values-iw/strings.xml | 2 +- app/src/main/res/values-ja/strings.xml | 2 +- app/src/main/res/values-kab/strings.xml | 2 +- app/src/main/res/values-ko/strings.xml | 2 +- app/src/main/res/values-lb/strings.xml | 2 +- app/src/main/res/values-mk/strings.xml | 4 +- app/src/main/res/values-mr/strings.xml | 30 +++++----- app/src/main/res/values-nb/strings.xml | 2 +- app/src/main/res/values-pms/strings.xml | 4 +- app/src/main/res/values-pt-rBR/strings.xml | 2 +- app/src/main/res/values-pt/strings.xml | 4 +- app/src/main/res/values-ru/strings.xml | 4 +- app/src/main/res/values-sd/strings.xml | 2 +- app/src/main/res/values-skr/strings.xml | 2 +- app/src/main/res/values-sr/strings.xml | 13 +++-- app/src/main/res/values-su/strings.xml | 2 +- app/src/main/res/values-sv/strings.xml | 2 +- app/src/main/res/values-tr/strings.xml | 2 +- app/src/main/res/values-ug/strings.xml | 12 ++-- app/src/main/res/values-uk/strings.xml | 2 +- app/src/main/res/values-zh-rTW/strings.xml | 4 +- app/src/main/res/values-zh/strings.xml | 4 +- app/src/main/res/values/strings.xml | 4 +- build.gradle | 2 +- 42 files changed, 154 insertions(+), 62 deletions(-) create mode 100644 app/src/main/res/layout/fragment_similar_image_dialog.xml diff --git a/app/src/main/res/layout/fragment_categorization.xml b/app/src/main/res/layout/fragment_categorization.xml index e49396b37..1c7b0a9f7 100644 --- a/app/src/main/res/layout/fragment_categorization.xml +++ b/app/src/main/res/layout/fragment_categorization.xml @@ -24,7 +24,6 @@ android:layout_width="match_parent" android:hint="@string/categories_search_text_hint" android:maxLines="1" - android:gravity="left" android:inputType="textCapWords" android:imeOptions="flagNoExtractUi" /> @@ -37,7 +36,7 @@ android:indeterminateOnly="true" android:layout_marginRight="@dimen/tiny_gap" android:layout_marginEnd="@dimen/tiny_gap" - android:layout_gravity="center_vertical|right" + android:layout_gravity="center_vertical|end" style="?android:progressBarStyleSmall" android:visibility="gone" /> diff --git a/app/src/main/res/layout/fragment_similar_image_dialog.xml b/app/src/main/res/layout/fragment_similar_image_dialog.xml new file mode 100644 index 000000000..90fec6bcf --- /dev/null +++ b/app/src/main/res/layout/fragment_similar_image_dialog.xml @@ -0,0 +1,57 @@ + + + + + + + + + +