From efc6fa6211607e352f8a9639746409e84e57dab5 Mon Sep 17 00:00:00 2001 From: Madhur Gupta <30932899+madhurgupta10@users.noreply.github.com> Date: Fri, 20 Mar 2020 14:30:28 +0100 Subject: [PATCH 1/3] Fixes #3473 Changed Names and Order or Theme Options (#3556) --- app/src/main/res/values/arrays.xml | 8 ++++---- app/src/main/res/values/strings.xml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml index c4b8a2318..17365a5a5 100644 --- a/app/src/main/res/values/arrays.xml +++ b/app/src/main/res/values/arrays.xml @@ -36,14 +36,14 @@ - @string/theme_default_name - @string/theme_dark_name @string/theme_light_name + @string/theme_dark_name + @string/theme_default_name - 0 - 1 2 + 1 + 0 \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 541155d6b..515669225 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -598,7 +598,7 @@ Upload your first media by tapping on the add button. Something went wrong. Could not set the wallpaper Set as Wallpaper Setting Wallpaper. Please wait… - Default + Follow system Dark Light From fb51fc618a41e146708ee27d0e6f5309b4534365 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Se=C3=A1n=20Mac=20Gillicuddy?= Date: Fri, 20 Mar 2020 14:18:14 +0000 Subject: [PATCH 2/3] #3408 Refactoring the FileProcessor and GPSExtractor classes (#3543) * #3408 Refactoring the FileProcessor and GPSExtractor classes - refactor FileProcessor * #3408 Refactoring the FileProcessor and GPSExtractor classes - refactor and rename GpsExtractor * #3408 Refactoring the FileProcessor and GPSExtractor classes - convert ImageCoordinates to kotlin * #3408 Refactoring the FileProcessor and GPSExtractor classes - convert FileProcessor to kotlin * #3408 Refactoring the FileProcessor and GPSExtractor classes - minor reformatting * #3408 Refactoring the FileProcessor and GPSExtractor classes - fix compilation and naming issues * #3408 Refactoring the FileProcessor and GPSExtractor classes - remove empty test * #3408 Refactoring the FileProcessor and GPSExtractor classes - set coordinates for upload item if user chooses it --- .../commons/di/CommonsApplicationModule.java | 38 +-- .../repository/UploadRemoteDataSource.java | 5 + .../commons/repository/UploadRepository.java | 5 + .../nrw/commons/upload/FileProcessor.java | 245 ------------------ .../free/nrw/commons/upload/FileProcessor.kt | 191 ++++++++++++++ .../fr/free/nrw/commons/upload/FileUtils.java | 8 +- .../free/nrw/commons/upload/GPSExtractor.java | 152 ----------- .../nrw/commons/upload/ImageCoordinates.kt | 74 ++++++ .../upload/SimilarImageDialogFragment.java | 10 +- .../commons/upload/SimilarImageInterface.java | 3 +- .../free/nrw/commons/upload/UploadModel.java | 103 ++------ .../UploadMediaDetailFragment.java | 41 ++- .../UploadMediaDetailsContract.java | 4 + .../mediaDetails/UploadMediaPresenter.java | 44 ++-- .../nrw/commons/upload/FileProcessorTest.kt | 89 ------- .../upload/UploadMediaPresenterTest.kt | 140 +++++----- .../nrw/commons/upload/UploadModelTest.kt | 132 ---------- 17 files changed, 450 insertions(+), 834 deletions(-) delete mode 100644 app/src/main/java/fr/free/nrw/commons/upload/FileProcessor.java create mode 100644 app/src/main/java/fr/free/nrw/commons/upload/FileProcessor.kt delete mode 100644 app/src/main/java/fr/free/nrw/commons/upload/GPSExtractor.java create mode 100644 app/src/main/java/fr/free/nrw/commons/upload/ImageCoordinates.kt delete mode 100644 app/src/test/kotlin/fr/free/nrw/commons/upload/FileProcessorTest.kt delete mode 100644 app/src/test/kotlin/fr/free/nrw/commons/upload/UploadModelTest.kt diff --git a/app/src/main/java/fr/free/nrw/commons/di/CommonsApplicationModule.java b/app/src/main/java/fr/free/nrw/commons/di/CommonsApplicationModule.java index 4e8e50fe1..8ed13d4df 100644 --- a/app/src/main/java/fr/free/nrw/commons/di/CommonsApplicationModule.java +++ b/app/src/main/java/fr/free/nrw/commons/di/CommonsApplicationModule.java @@ -2,26 +2,13 @@ package fr.free.nrw.commons.di; import android.app.Activity; import android.content.ContentProviderClient; +import android.content.ContentResolver; import android.content.Context; import android.view.inputmethod.InputMethodManager; - import androidx.collection.LruCache; import androidx.room.Room; - import com.github.varunpant.quadtree.QuadTree; import com.google.gson.Gson; - -import org.wikipedia.AppAdapter; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; - -import javax.inject.Named; -import javax.inject.Singleton; - import dagger.Module; import dagger.Provides; import fr.free.nrw.commons.BuildConfig; @@ -41,10 +28,18 @@ import fr.free.nrw.commons.wikidata.WikidataEditListenerImpl; import io.reactivex.Scheduler; import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.schedulers.Schedulers; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import javax.inject.Named; +import javax.inject.Singleton; +import org.wikipedia.AppAdapter; /** - * The Dependency Provider class for Commons Android. - * + * The Dependency Provider class for Commons Android. + * * Provides all sorts of ContentProviderClients used by the app * along with the Liscences, AccountUtility, UploadController, Logged User, * Location manager etc @@ -101,7 +96,7 @@ public class CommonsApplicationModule { } /** - * Provides an instance of CategoryContentProviderClient i.e. the categories + * Provides an instance of CategoryContentProviderClient i.e. the categories * that are there in local storage */ @Provides @@ -203,7 +198,7 @@ public class CommonsApplicationModule { /** * Provide JavaRx IO scheduler which manages IO operations - * across various Threads + * across various Threads */ @Named(IO_THREAD) @Provides @@ -244,4 +239,9 @@ public class CommonsApplicationModule { public ContributionDao providesContributionsDao() { return appDatabase.getContributionDao(); } -} \ No newline at end of file + + @Provides + public ContentResolver providesContentResolver(Context context){ + return context.getContentResolver(); + } +} diff --git a/app/src/main/java/fr/free/nrw/commons/repository/UploadRemoteDataSource.java b/app/src/main/java/fr/free/nrw/commons/repository/UploadRemoteDataSource.java index 2263eb5f3..cf5aa9c05 100644 --- a/app/src/main/java/fr/free/nrw/commons/repository/UploadRemoteDataSource.java +++ b/app/src/main/java/fr/free/nrw/commons/repository/UploadRemoteDataSource.java @@ -1,5 +1,6 @@ package fr.free.nrw.commons.repository; +import fr.free.nrw.commons.upload.ImageCoordinates; import java.io.IOException; import java.util.Comparator; import java.util.List; @@ -202,4 +203,8 @@ public class UploadRemoteDataSource { return null; } } + + public void useSimilarPictureCoordinates(ImageCoordinates imageCoordinates, int uploadItemIndex) { + uploadModel.useSimilarPictureCoordinates(imageCoordinates, uploadItemIndex); + } } diff --git a/app/src/main/java/fr/free/nrw/commons/repository/UploadRepository.java b/app/src/main/java/fr/free/nrw/commons/repository/UploadRepository.java index 877327c14..3d08a48bb 100644 --- a/app/src/main/java/fr/free/nrw/commons/repository/UploadRepository.java +++ b/app/src/main/java/fr/free/nrw/commons/repository/UploadRepository.java @@ -1,5 +1,6 @@ package fr.free.nrw.commons.repository; +import fr.free.nrw.commons.upload.ImageCoordinates; import java.util.Comparator; import java.util.List; @@ -271,4 +272,8 @@ public class UploadRepository { public Place checkNearbyPlaces(double decLatitude, double decLongitude) { return remoteDataSource.getNearbyPlaces(decLatitude, decLongitude); } + + public void useSimilarPictureCoordinates(ImageCoordinates imageCoordinates, int uploadItemIndex) { + remoteDataSource.useSimilarPictureCoordinates(imageCoordinates, uploadItemIndex); + } } diff --git a/app/src/main/java/fr/free/nrw/commons/upload/FileProcessor.java b/app/src/main/java/fr/free/nrw/commons/upload/FileProcessor.java deleted file mode 100644 index 361ecf0ad..000000000 --- a/app/src/main/java/fr/free/nrw/commons/upload/FileProcessor.java +++ /dev/null @@ -1,245 +0,0 @@ -package fr.free.nrw.commons.upload; - -import android.annotation.SuppressLint; -import android.content.ContentResolver; -import android.content.Context; -import android.net.Uri; - -import androidx.annotation.NonNull; -import androidx.exifinterface.media.ExifInterface; - -import com.google.gson.reflect.TypeToken; - -import java.io.File; -import java.io.IOException; -import java.lang.reflect.Type; -import java.util.Arrays; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -import javax.inject.Inject; -import javax.inject.Named; -import javax.inject.Singleton; - -import fr.free.nrw.commons.R; -import fr.free.nrw.commons.caching.CacheController; -import fr.free.nrw.commons.kvstore.JsonKvStore; -import fr.free.nrw.commons.mwapi.CategoryApi; -import fr.free.nrw.commons.settings.Prefs; -import fr.free.nrw.commons.upload.SimilarImageDialogFragment.Callback; -import io.reactivex.Observable; -import io.reactivex.disposables.CompositeDisposable; -import io.reactivex.disposables.Disposable; -import io.reactivex.schedulers.Schedulers; -import timber.log.Timber; - -/** - * Processing of the image filePath that is about to be uploaded via ShareActivity is done here - */ -@Singleton -public class FileProcessor implements Callback { - - @Inject - CacheController cacheController; - @Inject - GpsCategoryModel gpsCategoryModel; - @Inject - CategoryApi apiCall; - @Inject - @Named("default_preferences") - JsonKvStore defaultKvStore; - private String filePath; - private ContentResolver contentResolver; - private GPSExtractor imageObj; - private String decimalCoords; - private ExifInterface exifInterface; - private boolean haveCheckedForOtherImages = false; - private GPSExtractor tempImageObj; - private CompositeDisposable compositeDisposable = new CompositeDisposable(); - - @Inject - public FileProcessor() { - } - - public void cleanup() { - compositeDisposable.clear(); - } - - void initFileDetails(@NonNull String filePath, ContentResolver contentResolver) { - this.filePath = filePath; - this.contentResolver = contentResolver; - try { - exifInterface = new ExifInterface(filePath); - } catch (IOException e) { - Timber.e(e); - } - } - - /** - * Processes filePath coordinates, either from EXIF data or user location - */ - GPSExtractor processFileCoordinates(SimilarImageInterface similarImageInterface, Context context) { - // Redact EXIF data as indicated in preferences. - redactExifTags(exifInterface, getExifTagsToRedact(context)); - - Timber.d("Calling GPSExtractor"); - imageObj = new GPSExtractor(exifInterface); - decimalCoords = imageObj.getCoords(); - if (decimalCoords == null || !imageObj.imageCoordsExists) { - //Find other photos taken around the same time which has gps coordinates - if (!haveCheckedForOtherImages) - findOtherImages(similarImageInterface);// Do not do repeat the process - } else { - useImageCoords(); - } - - return imageObj; - } - - /** - * Gets EXIF Tags from preferences to be redacted. - * - * @param context application context - * @return tags to be redacted - */ - private Set getExifTagsToRedact(Context context) { - Type setType = new TypeToken>() {}.getType(); - Set prefManageEXIFTags = defaultKvStore.getStringSet(Prefs.MANAGED_EXIF_TAGS); - - Set redactTags = new HashSet<>(Arrays.asList( - context.getResources().getStringArray(R.array.pref_exifTag_values))); - Timber.d(redactTags.toString()); - - if (prefManageEXIFTags != null) redactTags.removeAll(prefManageEXIFTags); - - return redactTags; - } - - /** - * Redacts EXIF metadata as indicated in preferences. - * - * @param exifInterface ExifInterface object - * @param redactTags tags to be redacted - */ - public static void redactExifTags(ExifInterface exifInterface, Set redactTags) { - if(redactTags.isEmpty()) return; - - Disposable disposable = Observable.fromIterable(redactTags) - .flatMap(tag -> Observable.fromArray(FileMetadataUtils.getTagsFromPref(tag))) - .forEach(tag -> { - Timber.d("Checking for tag: %s", tag); - String oldValue = exifInterface.getAttribute(tag); - if (oldValue != null && !oldValue.isEmpty()) { - Timber.d("Exif tag %s with value %s redacted.", tag, oldValue); - exifInterface.setAttribute(tag, null); - } - }); - CompositeDisposable disposables = new CompositeDisposable(); - disposables.add(disposable); - disposables.clear(); - - try { - exifInterface.saveAttributes(); - } catch (IOException e) { - Timber.w("EXIF redaction failed: %s", e.toString()); - } - } - - /** - * Find other images around the same location that were taken within the last 20 sec - * @param similarImageInterface - */ - private void findOtherImages(SimilarImageInterface similarImageInterface) { - Timber.d("filePath" + filePath); - - long timeOfCreation = new File(filePath).lastModified();//Time when the original image was created - File folder = new File(filePath.substring(0, filePath.lastIndexOf('/'))); - File[] files = folder.listFiles(); - Timber.d("folderTime Number:" + files.length); - - - for (File file : files) { - if (file.lastModified() - timeOfCreation <= (120 * 1000) && file.lastModified() - timeOfCreation >= -(120 * 1000)) { - //Make sure the photos were taken within 20seconds - Timber.d("fild date:" + file.lastModified() + " time of creation" + timeOfCreation); - tempImageObj = null;//Temporary GPSExtractor to extract coords from these photos - try { - tempImageObj = new GPSExtractor(contentResolver.openInputStream(Uri.fromFile(file))); - } catch (Exception e) { - e.printStackTrace(); - } - if (tempImageObj != null) { - tempImageObj = new GPSExtractor(file.getAbsolutePath()); - } - if (tempImageObj != null) { - Timber.d("not null fild EXIF" + tempImageObj.imageCoordsExists + " coords" + tempImageObj.getCoords()); - if (tempImageObj.getCoords() != null && tempImageObj.imageCoordsExists) { - // Current image has gps coordinates and it's not current gps locaiton - Timber.d("This filePath has image coords:" + file.getAbsolutePath()); - similarImageInterface.showSimilarImageFragment(filePath, file.getAbsolutePath()); - break; - } - } - } - } - haveCheckedForOtherImages = true; //Finished checking for other images - } - - /** - * Initiates retrieval of image coordinates or user coordinates, and caching of coordinates. - * Then initiates the calls to MediaWiki API through an instance of CategoryApi. - */ - @SuppressLint("CheckResult") - private void useImageCoords() { - if (decimalCoords != null) { - Timber.d("Decimal coords of image: %s", decimalCoords); - Timber.d("is EXIF data present:" + imageObj.imageCoordsExists + " from findOther image"); - - // Only set cache for this point if image has coords - if (imageObj.imageCoordsExists) { - double decLongitude = imageObj.getDecLongitude(); - double decLatitude = imageObj.getDecLatitude(); - cacheController.setQtPoint(decLongitude, decLatitude); - } - - List displayCatList = cacheController.findCategory(); - boolean catListEmpty = displayCatList.isEmpty(); - - - // If no categories found in cache, call MediaWiki API to match image coords with nearby Commons categories - if (catListEmpty) { - compositeDisposable.add(apiCall.request(decimalCoords) - .subscribeOn(Schedulers.io()) - .observeOn(Schedulers.io()) - .subscribe( - gpsCategoryModel::setCategoryList, - throwable -> { - Timber.e(throwable); - gpsCategoryModel.clear(); - } - )); - Timber.d("displayCatList size 0, calling MWAPI %s", displayCatList); - } else { - Timber.d("Cache found, setting categoryList in model to %s", displayCatList); - gpsCategoryModel.setCategoryList(displayCatList); - } - } else { - Timber.d("EXIF: no coords"); - } - } - - @Override - public void onPositiveResponse() { - imageObj = tempImageObj; - decimalCoords = imageObj.getCoords();// Not necessary to use gps as image already ha EXIF data - Timber.d("EXIF from tempImageObj"); - useImageCoords(); - } - - @Override - public void onNegativeResponse() { - Timber.d("EXIF from imageObj"); - useImageCoords(); - } -} \ No newline at end of file diff --git a/app/src/main/java/fr/free/nrw/commons/upload/FileProcessor.kt b/app/src/main/java/fr/free/nrw/commons/upload/FileProcessor.kt new file mode 100644 index 000000000..1d9931701 --- /dev/null +++ b/app/src/main/java/fr/free/nrw/commons/upload/FileProcessor.kt @@ -0,0 +1,191 @@ +package fr.free.nrw.commons.upload + +import android.content.ContentResolver +import android.content.Context +import android.net.Uri +import androidx.exifinterface.media.ExifInterface +import fr.free.nrw.commons.R +import fr.free.nrw.commons.caching.CacheController +import fr.free.nrw.commons.kvstore.JsonKvStore +import fr.free.nrw.commons.mwapi.CategoryApi +import fr.free.nrw.commons.settings.Prefs +import io.reactivex.Observable +import io.reactivex.disposables.CompositeDisposable +import io.reactivex.schedulers.Schedulers +import timber.log.Timber +import java.io.File +import java.io.IOException +import javax.inject.Inject +import javax.inject.Named + +/** + * Processing of the image filePath that is about to be uploaded via ShareActivity is done here + */ +class FileProcessor @Inject constructor( + private val context: Context, + private val contentResolver: ContentResolver, + private val cacheController: CacheController, + private val gpsCategoryModel: GpsCategoryModel, + @param:Named("default_preferences") private val defaultKvStore: JsonKvStore, + private val apiCall: CategoryApi +) { + private val compositeDisposable = CompositeDisposable() + + fun cleanup() { + compositeDisposable.clear() + } + + /** + * Processes filePath coordinates, either from EXIF data or user location + */ + fun processFileCoordinates(similarImageInterface: SimilarImageInterface, filePath: String?) + : ImageCoordinates { + val exifInterface: ExifInterface? = try { + ExifInterface(filePath!!) + } catch (e: IOException) { + Timber.e(e) + null + } + // Redact EXIF data as indicated in preferences. + redactExifTags(exifInterface, getExifTagsToRedact()) + Timber.d("Calling GPSExtractor") + val originalImageCoordinates = ImageCoordinates(exifInterface) + if (originalImageCoordinates.decimalCoords == null) { + //Find other photos taken around the same time which has gps coordinates + findOtherImages( + File(filePath), + similarImageInterface + ) + } else { + useImageCoords(originalImageCoordinates) + } + return originalImageCoordinates + } + + /** + * Gets EXIF Tags from preferences to be redacted. + * + * @return tags to be redacted + */ + private fun getExifTagsToRedact(): Set { + val prefManageEXIFTags = + defaultKvStore.getStringSet(Prefs.MANAGED_EXIF_TAGS) ?: emptySet() + val redactTags: Set = + context.resources.getStringArray(R.array.pref_exifTag_values).toSet() + return redactTags - prefManageEXIFTags + } + + /** + * Redacts EXIF metadata as indicated in preferences. + * + * @param exifInterface ExifInterface object + * @param redactTags tags to be redacted + */ + private fun redactExifTags(exifInterface: ExifInterface?, redactTags: Set) { + compositeDisposable.add( + Observable.fromIterable(redactTags) + .flatMap { Observable.fromArray(*FileMetadataUtils.getTagsFromPref(it)) } + .subscribe( + { redactTag(exifInterface, it) }, + { Timber.d(it) }, + { save(exifInterface) } + ) + ) + } + + private fun save(exifInterface: ExifInterface?) { + try { + exifInterface?.saveAttributes() + } catch (e: IOException) { + Timber.w("EXIF redaction failed: %s", e.toString()) + } + } + + private fun redactTag(exifInterface: ExifInterface?, tag: String) { + Timber.d("Checking for tag: %s", tag) + exifInterface?.getAttribute(tag) + ?.takeIf { it.isNotEmpty() } + ?.let { + exifInterface.setAttribute(tag, null).also { + Timber.d("Exif tag $tag with value $it redacted.") + } + } + } + + /** + * Find other images around the same location that were taken within the last 20 sec + * + * @param originalImageCoordinates + * @param fileBeingProcessed + * @param similarImageInterface + */ + private fun findOtherImages( + fileBeingProcessed: File, + similarImageInterface: SimilarImageInterface + ) { + val oneHundredAndTwentySeconds = 120 * 1000L + //Time when the original image was created + val timeOfCreation = fileBeingProcessed.lastModified() + LongRange + val timeOfCreationRange = + timeOfCreation - oneHundredAndTwentySeconds..timeOfCreation + oneHundredAndTwentySeconds + fileBeingProcessed.parentFile + .listFiles() + .asSequence() + .filter { it.lastModified() in timeOfCreationRange } + .map { Pair(it, readImageCoordinates(it)) } + .firstOrNull { it.second?.decimalCoords != null } + ?.let { fileCoordinatesPair -> + similarImageInterface.showSimilarImageFragment( + fileBeingProcessed.path, + fileCoordinatesPair.first.absolutePath, + fileCoordinatesPair.second + ) + } + } + + private fun readImageCoordinates(file: File) = + try { + ImageCoordinates(contentResolver.openInputStream(Uri.fromFile(file))) + } catch (e: IOException) { + Timber.e(e) + try { + ImageCoordinates(file.absolutePath) + } catch (ex: IOException) { + Timber.e(ex) + null + } + } + + /** + * Initiates retrieval of image coordinates or user coordinates, and caching of coordinates. Then + * initiates the calls to MediaWiki API through an instance of CategoryApi. + * + * @param imageCoordinates + */ + fun useImageCoords(imageCoordinates: ImageCoordinates) { + requireNotNull(imageCoordinates.decimalCoords) + cacheController.setQtPoint(imageCoordinates.decLongitude, imageCoordinates.decLatitude) + val displayCatList = cacheController.findCategory() + + // If no categories found in cache, call MediaWiki API to match image coords with nearby Commons categories + if (displayCatList.isEmpty()) { + compositeDisposable.add( + apiCall.request(imageCoordinates.decimalCoords) + .subscribeOn(Schedulers.io()) + .observeOn(Schedulers.io()) + .subscribe( + { gpsCategoryModel.categoryList = it }, + { + Timber.e(it) + gpsCategoryModel.clear() + } + ) + ) + Timber.d("displayCatList size 0, calling MWAPI %s", displayCatList) + } else { + Timber.d("Cache found, setting categoryList in model to %s", displayCatList) + gpsCategoryModel.categoryList = displayCatList + } + } +} 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 72158f221..10e157705 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 @@ -68,9 +68,9 @@ public class FileUtils { try { ExifInterface exifInterface = new ExifInterface(filePath); - GPSExtractor imageObj = new GPSExtractor(exifInterface); - if (imageObj.imageCoordsExists) { // If image has geolocation information in its EXIF - return imageObj.getCoords(); + ImageCoordinates imageObj = new ImageCoordinates(exifInterface); + if (imageObj.getDecimalCoords() != null) { // If image has geolocation information in its EXIF + return imageObj.getDecimalCoords(); } else { return ""; } @@ -178,4 +178,4 @@ public class FileUtils { return false; } } -} \ No newline at end of file +} diff --git a/app/src/main/java/fr/free/nrw/commons/upload/GPSExtractor.java b/app/src/main/java/fr/free/nrw/commons/upload/GPSExtractor.java deleted file mode 100644 index f602f4ff7..000000000 --- a/app/src/main/java/fr/free/nrw/commons/upload/GPSExtractor.java +++ /dev/null @@ -1,152 +0,0 @@ -package fr.free.nrw.commons.upload; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.exifinterface.media.ExifInterface; - -import java.io.IOException; -import java.io.InputStream; - -import timber.log.Timber; - -/** - * Extracts geolocation to be passed to API for category suggestions. If a picture with geolocation - * is uploaded, extract latitude and longitude from EXIF data of image. - */ -public class GPSExtractor { - - static final GPSExtractor DUMMY= new GPSExtractor(); - private double decLatitude; - private double decLongitude; - public boolean imageCoordsExists; - private String latitude; - private String longitude; - private String latitudeRef; - private String longitudeRef; - private String decimalCoords; - - /** - * Dummy constructor. - */ - private GPSExtractor(){ - - } - /** - * Construct from a stream. - */ - GPSExtractor(@NonNull InputStream stream) throws IOException { - ExifInterface exif = new ExifInterface(stream); - processCoords(exif); - } - - /** - * Construct from the file path of the image. - * @param path file path of the image - * - */ - GPSExtractor(@NonNull String path) { - try { - ExifInterface exif = new ExifInterface(path); - processCoords(exif); - } catch (IOException | IllegalArgumentException e) { - Timber.w(e); - } - } - - /** - * Construct from the file path of the image. - * @param exif exif interface of the image - * - */ - GPSExtractor(@NonNull ExifInterface exif){ - processCoords(exif); - } - - private void processCoords(ExifInterface exif){ - //If image has no EXIF data and user has enabled GPS setting, get user's location - //Always return null as a temporary fix for #1599 - if (exif != null && exif.getAttribute(ExifInterface.TAG_GPS_LATITUDE) != null) { - //If image has EXIF data, extract image coords - imageCoordsExists = true; - Timber.d("EXIF data has location info"); - - latitude = exif.getAttribute(ExifInterface.TAG_GPS_LATITUDE); - latitudeRef = exif.getAttribute(ExifInterface.TAG_GPS_LATITUDE_REF); - longitude = exif.getAttribute(ExifInterface.TAG_GPS_LONGITUDE); - longitudeRef = exif.getAttribute(ExifInterface.TAG_GPS_LONGITUDE_REF); - } - } - - /** - * Extracts geolocation (either of image from EXIF data, or of user) - * @return coordinates as string (needs to be passed as a String in API query) - */ - @Nullable - String getCoords() { - if(decimalCoords!=null){ - return decimalCoords; - }else if (latitude!=null && latitudeRef!=null && longitude!=null && longitudeRef!=null) { - Timber.d("Latitude: %s %s", latitude, latitudeRef); - Timber.d("Longitude: %s %s", longitude, longitudeRef); - - decimalCoords = getDecimalCoords(latitude, latitudeRef, longitude, longitudeRef); - return decimalCoords; - } else { - return null; - } - } - - public double getDecLatitude() { - return decLatitude; - } - - public double getDecLongitude() { - return decLongitude; - } - - /** - * Converts format of geolocation into decimal coordinates as required by MediaWiki API - * @return the coordinates in decimals - */ - private String getDecimalCoords(String latitude, String latitude_ref, String longitude, String longitude_ref) { - - if (latitude_ref.equals("N")) { - decLatitude = convertToDegree(latitude); - } else { - decLatitude = 0 - convertToDegree(latitude); - } - - if (longitude_ref.equals("E")) { - decLongitude = convertToDegree(longitude); - } else { - decLongitude = 0 - convertToDegree(longitude); - } - - String decimalCoords = decLatitude + "|" + decLongitude; - Timber.d("Latitude and Longitude are %s", decimalCoords); - return decimalCoords; - } - - private double convertToDegree(String stringDMS) { - double result; - String[] DMS = stringDMS.split(",", 3); - - String[] stringD = DMS[0].split("/", 2); - double d0 = Double.parseDouble(stringD[0]); - double d1 = Double.parseDouble(stringD[1]); - double degrees = d0/d1; - - String[] stringM = DMS[1].split("/", 2); - double m0 = Double.parseDouble(stringM[0]); - double m1 = Double.parseDouble(stringM[1]); - double minutes = m0/m1; - - String[] stringS = DMS[2].split("/", 2); - double s0 = Double.parseDouble(stringS[0]); - double s1 = Double.parseDouble(stringS[1]); - double seconds = s0/s1; - - result = degrees + (minutes/60) + (seconds/3600); - return result; - } -} diff --git a/app/src/main/java/fr/free/nrw/commons/upload/ImageCoordinates.kt b/app/src/main/java/fr/free/nrw/commons/upload/ImageCoordinates.kt new file mode 100644 index 000000000..dc79f1673 --- /dev/null +++ b/app/src/main/java/fr/free/nrw/commons/upload/ImageCoordinates.kt @@ -0,0 +1,74 @@ +package fr.free.nrw.commons.upload + +import androidx.exifinterface.media.ExifInterface +import timber.log.Timber +import java.io.IOException +import java.io.InputStream + +/** + * Extracts geolocation to be passed to API for category suggestions. If a picture with geolocation + * is uploaded, extract latitude and longitude from EXIF data of image. + */ +class ImageCoordinates internal constructor(exif: ExifInterface?) { + var decLatitude = 0.0 + var decLongitude = 0.0 + var imageCoordsExists = false + /** + * @return string of `"[decLatitude]|[decLongitude]"` or null if coordinates do not exist + */ + var decimalCoords: String? = null + + /** + * Construct from a stream. + */ + internal constructor(stream: InputStream) : this(ExifInterface(stream)) + + /** + * Construct from the file path of the image. + * @param path file path of the image + */ + @Throws(IOException::class) + internal constructor(path: String) : this(ExifInterface(path)) + + + + init { + //If image has no EXIF data and user has enabled GPS setting, get user's location + //Always return null as a temporary fix for #1599 + if (exif != null) { + val latitude = exif.getAttribute(ExifInterface.TAG_GPS_LATITUDE) + val latitudeRef = exif.getAttribute(ExifInterface.TAG_GPS_LATITUDE_REF) + val longitude = exif.getAttribute(ExifInterface.TAG_GPS_LONGITUDE) + val longitudeRef = exif.getAttribute(ExifInterface.TAG_GPS_LONGITUDE_REF) + if (latitude != null && longitude != null && latitudeRef != null && longitudeRef != null) { + //If image has EXIF data, extract image coords + imageCoordsExists = true + Timber.d("EXIF data has location info") + decLatitude = + if (ExifInterface.LATITUDE_NORTH == latitudeRef) convertToDegree(latitude) + else 0 - convertToDegree(latitude) + decLongitude = + if (ExifInterface.LONGITUDE_EAST == longitudeRef) convertToDegree(longitude) + else 0 - convertToDegree(longitude) + decimalCoords = "$decLatitude|$decLongitude" + } + } + } + + /** + * Convert a string to an accurate Degree + * + * @param degreeMinuteSecondString - template string "a/b,c/d,e/f" where the letters represent numbers + * @return the degree accurate to the second + */ + private fun convertToDegree(degreeMinuteSecondString: String) = + degreeMinuteSecondString.split(",").let { + val degrees = evaluateExpression(it[0]) + val minutes = evaluateExpression(it[1]) + val seconds = evaluateExpression(it[2]) + degrees + minutes / 60 + seconds / 3600 + } + + private fun evaluateExpression(dm: String) = + dm.split("/").let { it[0].toDouble() / it[1].toDouble() } +} diff --git a/app/src/main/java/fr/free/nrw/commons/upload/SimilarImageDialogFragment.java b/app/src/main/java/fr/free/nrw/commons/upload/SimilarImageDialogFragment.java index 84b5b1081..2491fad2b 100644 --- a/app/src/main/java/fr/free/nrw/commons/upload/SimilarImageDialogFragment.java +++ b/app/src/main/java/fr/free/nrw/commons/upload/SimilarImageDialogFragment.java @@ -9,20 +9,16 @@ import android.view.View; import android.view.ViewGroup; import android.view.Window; import android.widget.Button; - import androidx.annotation.Nullable; import androidx.fragment.app.DialogFragment; import androidx.vectordrawable.graphics.drawable.VectorDrawableCompat; - -import com.facebook.drawee.generic.GenericDraweeHierarchyBuilder; -import com.facebook.drawee.view.SimpleDraweeView; - -import java.io.File; - import butterknife.BindView; import butterknife.ButterKnife; import butterknife.OnClick; +import com.facebook.drawee.generic.GenericDraweeHierarchyBuilder; +import com.facebook.drawee.view.SimpleDraweeView; import fr.free.nrw.commons.R; +import java.io.File; /** * Created by harisanker on 14/2/18. diff --git a/app/src/main/java/fr/free/nrw/commons/upload/SimilarImageInterface.java b/app/src/main/java/fr/free/nrw/commons/upload/SimilarImageInterface.java index 6436f621b..50e6e5f27 100644 --- a/app/src/main/java/fr/free/nrw/commons/upload/SimilarImageInterface.java +++ b/app/src/main/java/fr/free/nrw/commons/upload/SimilarImageInterface.java @@ -1,5 +1,6 @@ package fr.free.nrw.commons.upload; public interface SimilarImageInterface { - void showSimilarImageFragment(String originalFilePath, String possibleFilePath); + void showSimilarImageFragment(String originalFilePath, String possibleFilePath, + ImageCoordinates similarImageCoordinates); } diff --git a/app/src/main/java/fr/free/nrw/commons/upload/UploadModel.java b/app/src/main/java/fr/free/nrw/commons/upload/UploadModel.java index f92f5bfa6..e17436101 100644 --- a/app/src/main/java/fr/free/nrw/commons/upload/UploadModel.java +++ b/app/src/main/java/fr/free/nrw/commons/upload/UploadModel.java @@ -3,20 +3,7 @@ package fr.free.nrw.commons.upload; import android.annotation.SuppressLint; import android.content.Context; import android.net.Uri; - import androidx.annotation.Nullable; - -import java.util.ArrayList; -import java.util.Date; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Objects; - -import javax.inject.Inject; -import javax.inject.Named; -import javax.inject.Singleton; - import fr.free.nrw.commons.CommonsApplication; import fr.free.nrw.commons.Utils; import fr.free.nrw.commons.auth.SessionManager; @@ -31,26 +18,25 @@ import io.reactivex.Observable; import io.reactivex.Single; import io.reactivex.disposables.CompositeDisposable; import io.reactivex.subjects.BehaviorSubject; +import java.util.ArrayList; +import java.util.Date; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import javax.inject.Inject; +import javax.inject.Named; +import javax.inject.Singleton; import timber.log.Timber; @Singleton public class UploadModel { - private static UploadItem DUMMY = new UploadItem( - Uri.EMPTY, Uri.EMPTY, - "", - "", - GPSExtractor.DUMMY, - null, - -1L, "") { - }; private final JsonKvStore store; private final List licenses; private final Context context; private String license; private final Map licensesByName; private List items = new ArrayList<>(); - private int currentStepIndex = 0; private CompositeDisposable compositeDisposable = new CompositeDisposable(); private SessionManager sessionManager; @@ -95,19 +81,6 @@ public class UploadModel { this.selectedCategories = selectedCategories; } - /** - * pre process a list of items - */ - @SuppressLint("CheckResult") - Observable preProcessImages(List uploadableFiles, - Place place, - String source, - SimilarImageInterface similarImageInterface) { - return Observable.fromIterable(uploadableFiles) - .map(uploadableFile -> getUploadItem(uploadableFile, place, source, - similarImageInterface)); - } - /** * pre process a one item at a time @@ -127,8 +100,6 @@ public class UploadModel { Place place, String source, SimilarImageInterface similarImageInterface) { - fileProcessor.initFileDetails(Objects.requireNonNull(uploadableFile.getFilePath()), - context.getContentResolver()); UploadableFile.DateTimeWithSource dateTimeWithSource = uploadableFile .getFileCreatedDate(context); long fileCreatedDate = -1; @@ -138,11 +109,11 @@ public class UploadModel { createdTimestampSource = dateTimeWithSource.getSource(); } Timber.d("File created date is %d", fileCreatedDate); - GPSExtractor gpsExtractor = fileProcessor - .processFileCoordinates(similarImageInterface, context); + ImageCoordinates imageCoordinates = fileProcessor + .processFileCoordinates(similarImageInterface, uploadableFile.getFilePath()); UploadItem uploadItem = new UploadItem(uploadableFile.getContentUri(), Uri.parse(uploadableFile.getFilePath()), - uploadableFile.getMimeType(context), source, gpsExtractor, place, fileCreatedDate, + uploadableFile.getMimeType(context), source, imageCoordinates, place, fileCreatedDate, createdTimestampSource); if (place != null) { uploadItem.title.setTitleText(place.name); @@ -158,14 +129,6 @@ public class UploadModel { return uploadItem; } - int getCurrentStep() { - return currentStepIndex + 1; - } - - int getStepCount() { - return items.size() + 2; - } - public int getCount() { return items.size(); } @@ -194,7 +157,7 @@ public class UploadModel { item.getFileName(), Description.formatList(item.descriptions), -1, null, null, sessionManager.getAuthorName(), - CommonsApplication.DEFAULT_EDIT_SUMMARY, item.gpsCoords.getCoords()); + CommonsApplication.DEFAULT_EDIT_SUMMARY, item.gpsCoords.getDecimalCoords()); if (item.place != null) { contribution.setWikiDataEntityId(item.place.getWikiDataEntityId()); // If item already has an image, we need to know it. We don't want to override existing image later @@ -244,6 +207,11 @@ public class UploadModel { uploadItem1.setTitle(uploadItem.title); } + public void useSimilarPictureCoordinates(ImageCoordinates imageCoordinates, int uploadItemIndex) { + fileProcessor.useImageCoords(imageCoordinates); + items.get(uploadItemIndex).setGpsCoords(imageCoordinates); + } + @SuppressWarnings("WeakerAccess") public static class UploadItem { @@ -251,22 +219,22 @@ public class UploadModel { private final Uri mediaUri; private final String mimeType; private final String source; - private final GPSExtractor gpsCoords; + private ImageCoordinates gpsCoords; + + public void setGpsCoords(ImageCoordinates gpsCoords) { + this.gpsCoords = gpsCoords; + } - private boolean selected = false; - private boolean first = false; private Title title; private List descriptions; private Place place; - private boolean visited; - private boolean error; private long createdTimestamp; private String createdTimestampSource; private BehaviorSubject imageQuality; @SuppressLint("CheckResult") UploadItem(Uri originalContentUri, - Uri mediaUri, String mimeType, String source, GPSExtractor gpsCoords, + Uri mediaUri, String mimeType, String source, ImageCoordinates gpsCoords, Place place, long createdTimestamp, String createdTimestampSource) { @@ -287,38 +255,18 @@ public class UploadModel { return createdTimestampSource; } - public String getMimeType() { - return mimeType; - } - public String getSource() { return source; } - public GPSExtractor getGpsCoords() { + public ImageCoordinates getGpsCoords() { return gpsCoords; } - public boolean isSelected() { - return selected; - } - - public boolean isFirst() { - return first; - } - public List getDescriptions() { return descriptions; } - public boolean isVisited() { - return visited; - } - - public boolean isError() { - return error; - } - public long getCreatedTimestamp() { return createdTimestamp; } @@ -373,10 +321,9 @@ public class UploadModel { } - //Travis is complaining :P @Override public int hashCode() { - return super.hashCode(); + return mediaUri.hashCode(); } } diff --git a/app/src/main/java/fr/free/nrw/commons/upload/mediaDetails/UploadMediaDetailFragment.java b/app/src/main/java/fr/free/nrw/commons/upload/mediaDetails/UploadMediaDetailFragment.java index 8a3c5837c..146806300 100644 --- a/app/src/main/java/fr/free/nrw/commons/upload/mediaDetails/UploadMediaDetailFragment.java +++ b/app/src/main/java/fr/free/nrw/commons/upload/mediaDetails/UploadMediaDetailFragment.java @@ -1,5 +1,7 @@ package fr.free.nrw.commons.upload.mediaDetails; +import static fr.free.nrw.commons.utils.ImageUtils.getErrorMessageForResult; + import android.annotation.SuppressLint; import android.content.Context; import android.os.Bundle; @@ -12,30 +14,17 @@ import android.view.ViewGroup; import android.widget.EditText; import android.widget.LinearLayout; import android.widget.TextView; - import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.appcompat.widget.AppCompatButton; import androidx.appcompat.widget.AppCompatImageButton; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; - -import com.github.chrisbanes.photoview.PhotoView; -import com.jakewharton.rxbinding2.widget.RxTextView; - -import org.apache.commons.lang3.StringUtils; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Locale; - -import javax.inject.Inject; -import javax.inject.Named; - import butterknife.BindView; import butterknife.ButterKnife; import butterknife.OnClick; +import com.github.chrisbanes.photoview.PhotoView; +import com.jakewharton.rxbinding2.widget.RxTextView; import fr.free.nrw.commons.R; import fr.free.nrw.commons.Utils; import fr.free.nrw.commons.filepicker.UploadableFile; @@ -45,6 +34,7 @@ import fr.free.nrw.commons.nearby.Place; import fr.free.nrw.commons.settings.Prefs; import fr.free.nrw.commons.upload.Description; import fr.free.nrw.commons.upload.DescriptionsAdapter; +import fr.free.nrw.commons.upload.ImageCoordinates; import fr.free.nrw.commons.upload.SimilarImageDialogFragment; import fr.free.nrw.commons.upload.Title; import fr.free.nrw.commons.upload.UploadBaseFragment; @@ -54,10 +44,15 @@ import fr.free.nrw.commons.utils.DialogUtil; import fr.free.nrw.commons.utils.ImageUtils; import fr.free.nrw.commons.utils.ViewUtil; import io.reactivex.disposables.Disposable; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Locale; +import javax.inject.Inject; +import javax.inject.Named; +import org.apache.commons.lang3.StringUtils; import timber.log.Timber; -import static fr.free.nrw.commons.utils.ImageUtils.getErrorMessageForResult; - public class UploadMediaDetailFragment extends UploadBaseFragment implements UploadMediaDetailsContract.View { @@ -231,14 +226,6 @@ public class UploadMediaDetailFragment extends UploadBaseFragment implements rvDescriptions.setAdapter(descriptionsAdapter); } - /** - * returns the default locale value of the user's device - * @return - */ - private String getUserDefaultLocale() { - return getContext().getResources().getConfiguration().locale.getLanguage(); - } - /** * show dialog with info * @param titleStringID @@ -267,12 +254,14 @@ public class UploadMediaDetailFragment extends UploadBaseFragment implements } @Override - public void showSimilarImageFragment(String originalFilePath, String possibleFilePath) { + public void showSimilarImageFragment(String originalFilePath, String possibleFilePath, + ImageCoordinates similarImageCoordinates) { SimilarImageDialogFragment newFragment = new SimilarImageDialogFragment(); newFragment.setCallback(new SimilarImageDialogFragment.Callback() { @Override public void onPositiveResponse() { Timber.d("positive response from similar image fragment"); + presenter.useSimilarPictureCoordinates(similarImageCoordinates, callback.getIndexInViewFlipper(UploadMediaDetailFragment.this)); } @Override diff --git a/app/src/main/java/fr/free/nrw/commons/upload/mediaDetails/UploadMediaDetailsContract.java b/app/src/main/java/fr/free/nrw/commons/upload/mediaDetails/UploadMediaDetailsContract.java index 280128999..a04bcae32 100644 --- a/app/src/main/java/fr/free/nrw/commons/upload/mediaDetails/UploadMediaDetailsContract.java +++ b/app/src/main/java/fr/free/nrw/commons/upload/mediaDetails/UploadMediaDetailsContract.java @@ -1,5 +1,6 @@ package fr.free.nrw.commons.upload.mediaDetails; +import fr.free.nrw.commons.upload.ImageCoordinates; import java.util.List; import fr.free.nrw.commons.BasePresenter; @@ -48,6 +49,9 @@ public interface UploadMediaDetailsContract { void setUploadItem(int index, UploadItem uploadItem); void fetchPreviousTitleAndDescription(int indexInViewFlipper); + + void useSimilarPictureCoordinates(ImageCoordinates imageCoordinates, int uploadItemIndex); + } } diff --git a/app/src/main/java/fr/free/nrw/commons/upload/mediaDetails/UploadMediaPresenter.java b/app/src/main/java/fr/free/nrw/commons/upload/mediaDetails/UploadMediaPresenter.java index a468ee15e..c36d1b781 100644 --- a/app/src/main/java/fr/free/nrw/commons/upload/mediaDetails/UploadMediaPresenter.java +++ b/app/src/main/java/fr/free/nrw/commons/upload/mediaDetails/UploadMediaPresenter.java @@ -1,15 +1,17 @@ package fr.free.nrw.commons.upload.mediaDetails; -import java.lang.reflect.Proxy; - -import javax.inject.Inject; -import javax.inject.Named; +import static fr.free.nrw.commons.di.CommonsApplicationModule.IO_THREAD; +import static fr.free.nrw.commons.di.CommonsApplicationModule.MAIN_THREAD; +import static fr.free.nrw.commons.utils.ImageUtils.EMPTY_TITLE; +import static fr.free.nrw.commons.utils.ImageUtils.FILE_NAME_EXISTS; +import static fr.free.nrw.commons.utils.ImageUtils.IMAGE_KEEP; +import static fr.free.nrw.commons.utils.ImageUtils.IMAGE_OK; import fr.free.nrw.commons.R; import fr.free.nrw.commons.filepicker.UploadableFile; import fr.free.nrw.commons.nearby.Place; import fr.free.nrw.commons.repository.UploadRepository; -import fr.free.nrw.commons.upload.GPSExtractor; +import fr.free.nrw.commons.upload.ImageCoordinates; import fr.free.nrw.commons.upload.SimilarImageInterface; import fr.free.nrw.commons.upload.UploadModel.UploadItem; import fr.free.nrw.commons.upload.mediaDetails.UploadMediaDetailsContract.UserActionListener; @@ -18,15 +20,11 @@ import io.reactivex.Observable; import io.reactivex.Scheduler; import io.reactivex.disposables.CompositeDisposable; import io.reactivex.disposables.Disposable; +import java.lang.reflect.Proxy; +import javax.inject.Inject; +import javax.inject.Named; import timber.log.Timber; -import static fr.free.nrw.commons.di.CommonsApplicationModule.IO_THREAD; -import static fr.free.nrw.commons.di.CommonsApplicationModule.MAIN_THREAD; -import static fr.free.nrw.commons.utils.ImageUtils.EMPTY_TITLE; -import static fr.free.nrw.commons.utils.ImageUtils.FILE_NAME_EXISTS; -import static fr.free.nrw.commons.utils.ImageUtils.IMAGE_KEEP; -import static fr.free.nrw.commons.utils.ImageUtils.IMAGE_OK; - public class UploadMediaPresenter implements UserActionListener, SimilarImageInterface { private static final UploadMediaDetailsContract.View DUMMY = (UploadMediaDetailsContract.View) Proxy @@ -81,10 +79,10 @@ public class UploadMediaPresenter implements UserActionListener, SimilarImageInt .subscribe(uploadItem -> { view.onImageProcessed(uploadItem, place); - GPSExtractor gpsCoords = uploadItem.getGpsCoords(); - view.showMapWithImageCoordinates(gpsCoords != null && gpsCoords.imageCoordsExists); + ImageCoordinates gpsCoords = uploadItem.getGpsCoords(); + view.showMapWithImageCoordinates(gpsCoords != null && gpsCoords.getImageCoordsExists()); view.showProgress(false); - if (gpsCoords != null && gpsCoords.imageCoordsExists) { + if (gpsCoords != null && gpsCoords.getImageCoordsExists()) { checkNearbyPlaces(uploadItem); } }, @@ -159,7 +157,12 @@ public class UploadMediaPresenter implements UserActionListener, SimilarImageInt } } - /** + @Override + public void useSimilarPictureCoordinates(ImageCoordinates imageCoordinates, int uploadItemIndex) { + repository.useSimilarPictureCoordinates(imageCoordinates, uploadItemIndex); + } + + /** * handles image quality verifications * * @param imageResult @@ -200,12 +203,15 @@ public class UploadMediaPresenter implements UserActionListener, SimilarImageInt /** * notifies the user that a similar image exists - * * @param originalFilePath * @param possibleFilePath + * @param similarImageCoordinates */ @Override - public void showSimilarImageFragment(String originalFilePath, String possibleFilePath) { - view.showSimilarImageFragment(originalFilePath, possibleFilePath); + public void showSimilarImageFragment(String originalFilePath, String possibleFilePath, + ImageCoordinates similarImageCoordinates) { + view.showSimilarImageFragment(originalFilePath, possibleFilePath, + similarImageCoordinates + ); } } diff --git a/app/src/test/kotlin/fr/free/nrw/commons/upload/FileProcessorTest.kt b/app/src/test/kotlin/fr/free/nrw/commons/upload/FileProcessorTest.kt deleted file mode 100644 index 98f6a2e22..000000000 --- a/app/src/test/kotlin/fr/free/nrw/commons/upload/FileProcessorTest.kt +++ /dev/null @@ -1,89 +0,0 @@ -package fr.free.nrw.commons.upload - -import android.content.SharedPreferences -import androidx.exifinterface.media.ExifInterface -import fr.free.nrw.commons.caching.CacheController -import fr.free.nrw.commons.mwapi.CategoryApi -import org.junit.Before -import org.junit.Test -import org.mockito.InjectMocks -import org.mockito.Mock -import org.mockito.MockitoAnnotations -import javax.inject.Inject -import javax.inject.Named - -import java.io.FileInputStream -import java.io.FileOutputStream - -class FileProcessorTest { - - @Mock - internal var cacheController: CacheController? = null - @Mock - internal var gpsCategoryModel: GpsCategoryModel? = null - @Mock - internal var apiCall: CategoryApi? = null - @Mock - @field:[Inject Named("default_preferences")] - internal var prefs: SharedPreferences? = null - - @InjectMocks - var fileProcessor: FileProcessor? = null - - @Before - fun setup() { - MockitoAnnotations.initMocks(this) - } - - @Test - fun processFileCoordinates() { - - } - - /** - * Test method to verify redaction Exif metadata - */ - @Test - fun redactExifTags() { - /* - val filePathRef: String? = "src/test/data/exif_redact_sample.jpg" - val filePathTmp: String? = "" + System.getProperty("java.io.tmpdir") + "exif_redact_sample_tmp.jpg" - - val inStream = FileInputStream(filePathRef) - val outStream = FileOutputStream(filePathTmp) - val inChannel = inStream.getChannel() - val outChannel = outStream.getChannel() - inChannel.transferTo(0, inChannel.size(), outChannel) - inStream.close() - outStream.close() - - val redactTags = mutableSetOf("Author", "Copyright", "Location", "Camera Model", - "Lens Model", "Serial Numbers", "Software") - - val exifInterface : ExifInterface? = ExifInterface(filePathTmp.toString()) - - var nonEmptyTag = false - for (redactTag in redactTags) { - for (tag in FileMetadataUtils.getTagsFromPref(redactTag)) { - val tagValue = exifInterface?.getAttribute(tag) - if(tagValue != null) { - nonEmptyTag = true - break - } - } - if (nonEmptyTag) break - } - // all tags are empty, can't test redaction - assert(nonEmptyTag) - - FileProcessor.redactExifTags(exifInterface, redactTags) - - for (redactTag in redactTags) { - for (tag in FileMetadataUtils.getTagsFromPref(redactTag)) { - val oldValue = exifInterface?.getAttribute(tag) - assert(oldValue == null) - } - } - */ - } -} \ No newline at end of file diff --git a/app/src/test/kotlin/fr/free/nrw/commons/upload/UploadMediaPresenterTest.kt b/app/src/test/kotlin/fr/free/nrw/commons/upload/UploadMediaPresenterTest.kt index a16af59bb..68bef84fd 100644 --- a/app/src/test/kotlin/fr/free/nrw/commons/upload/UploadMediaPresenterTest.kt +++ b/app/src/test/kotlin/fr/free/nrw/commons/upload/UploadMediaPresenterTest.kt @@ -1,5 +1,7 @@ package fr.free.nrw.commons.upload +import com.nhaarman.mockitokotlin2.mock +import com.nhaarman.mockitokotlin2.whenever import fr.free.nrw.commons.filepicker.UploadableFile import fr.free.nrw.commons.nearby.Place import fr.free.nrw.commons.repository.UploadRepository @@ -14,7 +16,6 @@ import org.junit.Test import org.mockito.ArgumentMatchers import org.mockito.ArgumentMatchers.eq import org.mockito.Mock -import org.mockito.Mockito import org.mockito.Mockito.verify import org.mockito.MockitoAnnotations @@ -24,31 +25,32 @@ import org.mockito.MockitoAnnotations */ class UploadMediaPresenterTest { @Mock - internal var repository: UploadRepository? = null - @Mock - internal var view: UploadMediaDetailsContract.View? = null - - private var uploadMediaPresenter: UploadMediaPresenter? = null + internal lateinit var repository: UploadRepository @Mock - private var uploadableFile: UploadableFile? = null + internal lateinit var view: UploadMediaDetailsContract.View + + private lateinit var uploadMediaPresenter: UploadMediaPresenter @Mock - private var place: Place? = null + private lateinit var uploadableFile: UploadableFile @Mock - private var uploadItem: UploadModel.UploadItem? = null + private lateinit var place: Place @Mock - private var title: Title? = null + private lateinit var uploadItem: UploadModel.UploadItem @Mock - private var descriptions: List? = null + private lateinit var title: Title - private var testObservableUploadItem: Observable? = null - private var testSingleImageResult: Single? = null + @Mock + private lateinit var descriptions: List - private var testScheduler: TestScheduler? = null + private lateinit var testObservableUploadItem: Observable + private lateinit var testSingleImageResult: Single + + private lateinit var testScheduler: TestScheduler /** * initial setup unit test environment @@ -61,7 +63,7 @@ class UploadMediaPresenterTest { testSingleImageResult = Single.just(1) testScheduler = TestScheduler() uploadMediaPresenter = UploadMediaPresenter(repository, testScheduler, testScheduler) - uploadMediaPresenter?.onAttachView(view) + uploadMediaPresenter.onAttachView(view) } /** @@ -69,12 +71,22 @@ class UploadMediaPresenterTest { */ @Test fun receiveImageTest() { - Mockito.`when`(repository?.preProcessImage(ArgumentMatchers.any(UploadableFile::class.java), ArgumentMatchers.any(Place::class.java), ArgumentMatchers.anyString(), ArgumentMatchers.any(UploadMediaPresenter::class.java))).thenReturn(testObservableUploadItem) - uploadMediaPresenter?.receiveImage(uploadableFile, ArgumentMatchers.anyString(), place) - verify(view)?.showProgress(true) - testScheduler?.triggerActions() - verify(view)?.onImageProcessed(ArgumentMatchers.any(UploadModel.UploadItem::class.java), ArgumentMatchers.any(Place::class.java)) - verify(view)?.showProgress(false) + whenever( + repository.preProcessImage( + ArgumentMatchers.any(UploadableFile::class.java), + ArgumentMatchers.any(Place::class.java), + ArgumentMatchers.anyString(), + ArgumentMatchers.any(UploadMediaPresenter::class.java) + ) + ).thenReturn(testObservableUploadItem) + uploadMediaPresenter.receiveImage(uploadableFile, ArgumentMatchers.anyString(), place) + verify(view).showProgress(true) + testScheduler.triggerActions() + verify(view).onImageProcessed( + ArgumentMatchers.any(UploadModel.UploadItem::class.java), + ArgumentMatchers.any(Place::class.java) + ) + verify(view).showProgress(false) } /** @@ -82,12 +94,13 @@ class UploadMediaPresenterTest { */ @Test fun verifyImageQualityTest() { - Mockito.`when`(repository?.getImageQuality(ArgumentMatchers.any(UploadModel.UploadItem::class.java))).thenReturn(testSingleImageResult) - Mockito.`when`(uploadItem?.imageQuality).thenReturn(ArgumentMatchers.anyInt()) - uploadMediaPresenter?.verifyImageQuality(uploadItem) - verify(view)?.showProgress(true) - testScheduler?.triggerActions() - verify(view)?.showProgress(false) + whenever(repository.getImageQuality(ArgumentMatchers.any(UploadModel.UploadItem::class.java))) + .thenReturn(testSingleImageResult) + whenever(uploadItem.imageQuality).thenReturn(ArgumentMatchers.anyInt()) + uploadMediaPresenter.verifyImageQuality(uploadItem) + verify(view).showProgress(true) + testScheduler.triggerActions() + verify(view).showProgress(false) } /** @@ -96,21 +109,21 @@ class UploadMediaPresenterTest { @Test fun handleImageResult() { //Positive case test - uploadMediaPresenter?.handleImageResult(IMAGE_KEEP) - verify(view)?.onImageValidationSuccess() + uploadMediaPresenter.handleImageResult(IMAGE_KEEP) + verify(view).onImageValidationSuccess() //Duplicate file name - uploadMediaPresenter?.handleImageResult(FILE_NAME_EXISTS) - verify(view)?.showDuplicatePicturePopup() + uploadMediaPresenter.handleImageResult(FILE_NAME_EXISTS) + verify(view).showDuplicatePicturePopup() //Empty Title test - uploadMediaPresenter?.handleImageResult(EMPTY_TITLE) - verify(view)?.showMessage(ArgumentMatchers.anyInt(), ArgumentMatchers.anyInt()) + uploadMediaPresenter.handleImageResult(EMPTY_TITLE) + verify(view).showMessage(ArgumentMatchers.anyInt(), ArgumentMatchers.anyInt()) //Bad Picture test //Empty Title test - uploadMediaPresenter?.handleImageResult(-7) - verify(view)?.showBadImagePopup(ArgumentMatchers.anyInt()) + uploadMediaPresenter.handleImageResult(-7) + verify(view).showBadImagePopup(ArgumentMatchers.anyInt()) } @@ -118,52 +131,54 @@ class UploadMediaPresenterTest { * Test fetch previous image title when there was one */ @Test - fun fetchPreviousImageAndTitleTestPositive(){ - Mockito.`when`(repository?.getPreviousUploadItem(ArgumentMatchers.anyInt())).thenReturn(uploadItem) - Mockito.`when`(uploadItem?.descriptions).thenReturn(descriptions) - Mockito.`when`(uploadItem?.title).thenReturn(title) - Mockito.`when`(title?.getTitleText()).thenReturn(ArgumentMatchers.anyString()) + fun fetchPreviousImageAndTitleTestPositive() { + whenever(repository.getPreviousUploadItem(ArgumentMatchers.anyInt())) + .thenReturn(uploadItem) + whenever(uploadItem.descriptions).thenReturn(descriptions) + whenever(uploadItem.title).thenReturn(title) + whenever(title.getTitleText()).thenReturn(ArgumentMatchers.anyString()) - uploadMediaPresenter?.fetchPreviousTitleAndDescription(0) - verify(view)?.setTitleAndDescription(ArgumentMatchers.anyString(),ArgumentMatchers.any()) + uploadMediaPresenter.fetchPreviousTitleAndDescription(0) + verify(view).setTitleAndDescription(ArgumentMatchers.anyString(), ArgumentMatchers.any()) } /** * Test fetch previous image title when there was none */ @Test - fun fetchPreviousImageAndTitleTestNegative(){ - Mockito.`when`(repository?.getPreviousUploadItem(ArgumentMatchers.anyInt())).thenReturn(null) - uploadMediaPresenter?.fetchPreviousTitleAndDescription(0) - verify(view)?.showMessage(ArgumentMatchers.anyInt(),ArgumentMatchers.anyInt()) + fun fetchPreviousImageAndTitleTestNegative() { + whenever(repository.getPreviousUploadItem(ArgumentMatchers.anyInt())) + .thenReturn(null) + uploadMediaPresenter.fetchPreviousTitleAndDescription(0) + verify(view).showMessage(ArgumentMatchers.anyInt(), ArgumentMatchers.anyInt()) } /** * Test bad image invalid location */ @Test - fun handleBadImageBaseTestInvalidLocation(){ - uploadMediaPresenter?.handleBadImage(8) - verify(repository)?.saveValue(ArgumentMatchers.anyString(),eq(false)) - verify(view)?.showBadImagePopup(8) + fun handleBadImageBaseTestInvalidLocation() { + uploadMediaPresenter.handleBadImage(8) + verify(repository).saveValue(ArgumentMatchers.anyString(), eq(false)) + verify(view).showBadImagePopup(8) } /** * Test bad image empty title */ @Test - fun handleBadImageBaseTestEmptyTitle(){ - uploadMediaPresenter?.handleBadImage(-3) - verify(view)?.showMessage(ArgumentMatchers.anyInt(),ArgumentMatchers.anyInt()) + fun handleBadImageBaseTestEmptyTitle() { + uploadMediaPresenter.handleBadImage(-3) + verify(view).showMessage(ArgumentMatchers.anyInt(), ArgumentMatchers.anyInt()) } /** * Teste show file already exists */ @Test - fun handleBadImageBaseTestFileNameExists(){ - uploadMediaPresenter?.handleBadImage(-4) - verify(view)?.showDuplicatePicturePopup() + fun handleBadImageBaseTestFileNameExists() { + uploadMediaPresenter.handleBadImage(-4) + verify(view).showDuplicatePicturePopup() } @@ -171,18 +186,19 @@ class UploadMediaPresenterTest { * Test show SimilarImageFragment */ @Test - fun showSimilarImageFragmentTest(){ - uploadMediaPresenter?.showSimilarImageFragment(ArgumentMatchers.anyString(),ArgumentMatchers.anyString()) - verify(view)?.showSimilarImageFragment(ArgumentMatchers.anyString(),ArgumentMatchers.anyString()) + fun showSimilarImageFragmentTest() { + val similar: ImageCoordinates = mock() + uploadMediaPresenter.showSimilarImageFragment("original", "possible", similar) + verify(view).showSimilarImageFragment("original", "possible", similar) } /** * Test set upload item */ @Test - fun setUploadItemTest(){ - uploadMediaPresenter?.setUploadItem(0,uploadItem) - verify(repository)?.updateUploadItem(0,uploadItem) + fun setUploadItemTest() { + uploadMediaPresenter.setUploadItem(0, uploadItem) + verify(repository).updateUploadItem(0, uploadItem) } } diff --git a/app/src/test/kotlin/fr/free/nrw/commons/upload/UploadModelTest.kt b/app/src/test/kotlin/fr/free/nrw/commons/upload/UploadModelTest.kt deleted file mode 100644 index 764c0a447..000000000 --- a/app/src/test/kotlin/fr/free/nrw/commons/upload/UploadModelTest.kt +++ /dev/null @@ -1,132 +0,0 @@ -package fr.free.nrw.commons.upload - -import android.app.Application -import android.content.Context -import fr.free.nrw.commons.auth.SessionManager -import fr.free.nrw.commons.filepicker.UploadableFile -import fr.free.nrw.commons.kvstore.JsonKvStore -import fr.free.nrw.commons.nearby.Place -import fr.free.nrw.commons.utils.ImageUtils.IMAGE_OK -import io.reactivex.Single -import org.junit.After -import org.junit.Assert.assertTrue -import org.junit.Before -import org.junit.Test -import org.mockito.ArgumentMatchers.* -import org.mockito.InjectMocks -import org.mockito.Mock -import org.mockito.Mockito.`when` -import org.mockito.Mockito.mock -import org.mockito.MockitoAnnotations -import java.io.FileInputStream -import java.io.InputStream -import java.util.* -import javax.inject.Inject -import javax.inject.Named - - -class UploadModelTest { - - @Mock - @field:[Inject Named("licenses")] - internal var licenses: List? = null - @Mock - @field:[Inject Named("default_preferences")] - internal var prefs: JsonKvStore? = null - @Mock - @field:[Inject Named("licenses_by_name")] - internal var licensesByName: Map? = null - @Mock - internal var context: Context? = null - @Mock - internal var sessionManage: SessionManager? = null - @Mock - internal var fileUtilsWrapper: FileUtilsWrapper? = null - @Mock - internal var fileProcessor: FileProcessor? = null - @Mock - internal var imageProcessingService: ImageProcessingService? = null - - @InjectMocks - var uploadModel: UploadModel? = null - - @Before - @Throws(Exception::class) - fun setUp() { - MockitoAnnotations.initMocks(this) - - `when`(context!!.applicationContext) - .thenReturn(mock(Application::class.java)) - `when`(fileUtilsWrapper!!.getFileExt(anyString())) - .thenReturn("jpg") - `when`(fileUtilsWrapper!!.getSHA1(any(InputStream::class.java))) - .thenReturn("sha") - `when`(fileUtilsWrapper!!.getFileInputStream(anyString())) - .thenReturn(mock(FileInputStream::class.java)) - `when`(fileUtilsWrapper!!.getGeolocationOfFile(anyString())) - .thenReturn("") - `when`(imageProcessingService!!.validateImage(any(UploadModel.UploadItem::class.java))) - .thenReturn(Single.just(IMAGE_OK)) - - } - - @After - @Throws(Exception::class) - fun tearDown() { - } - - @Test - fun receive() { - val preProcessImages = uploadModel!!.preProcessImages(getMediaList(), mock(Place::class.java), "external") { _, _ -> } - preProcessImages.doOnComplete { - assertTrue(uploadModel!!.items.size == 2) - } - } - - @Test - fun getCurrentStep() { - uploadModel!!.preProcessImages(getMediaList(), mock(Place::class.java), "external") { _, _ -> } - assertTrue(uploadModel!!.currentStep == 1) - } - - @Test - fun getStepCount() { - val preProcessImages = uploadModel!!.preProcessImages(getMediaList(), mock(Place::class.java), "external") { _, _ -> } - preProcessImages.doOnComplete { - assertTrue(uploadModel!!.stepCount == 4) - } - } - - @Test - fun getCount() { - val preProcessImages = uploadModel!!.preProcessImages(getMediaList(), mock(Place::class.java), "external") { _, _ -> } - preProcessImages.doOnComplete { - assertTrue(uploadModel!!.count == 2) - } - } - - @Test - fun getUploads() { - val preProcessImages = uploadModel!!.preProcessImages(getMediaList(), mock(Place::class.java), "external") { _, _ -> } - preProcessImages.doOnComplete { - assertTrue(uploadModel!!.uploads.size == 2) - } - } - - private fun getMediaList(): List { - val element = getElement() - val element2 = getElement() - var uriList: List = mutableListOf(element, element2) - return uriList - } - - private fun getElement(): UploadableFile { - val mock = mock(UploadableFile::class.java) - `when`(mock.filePath).thenReturn(UUID.randomUUID().toString() + "/filePath.jpg") - return mock - } - - @Test - fun buildContributions() { - } -} From a63a3580ded9e9078259596f7b7505b44161a8d2 Mon Sep 17 00:00:00 2001 From: Anmol Gupta <44764339+6point022@users.noreply.github.com> Date: Fri, 20 Mar 2020 19:50:20 +0530 Subject: [PATCH 3/3] Change "Archived" notifications to "Read" notifications (#3554) * Change archived to read * Change string names --- .../nrw/commons/notification/NotificationActivity.java | 8 ++++---- app/src/main/res/menu/menu_notifications.xml | 2 +- app/src/main/res/values-af/strings.xml | 2 +- app/src/main/res/values-ar/strings.xml | 6 +++--- app/src/main/res/values-ast/strings.xml | 6 +++--- app/src/main/res/values-bg/strings.xml | 6 +++--- app/src/main/res/values-br/strings.xml | 2 +- app/src/main/res/values-ca/strings.xml | 6 +++--- app/src/main/res/values-cs/strings.xml | 6 +++--- app/src/main/res/values-da/strings.xml | 2 +- app/src/main/res/values-de/strings.xml | 6 +++--- app/src/main/res/values-diq/strings.xml | 6 +++--- app/src/main/res/values-el/strings.xml | 2 +- app/src/main/res/values-eo/strings.xml | 6 +++--- app/src/main/res/values-es/strings.xml | 6 +++--- app/src/main/res/values-fa/strings.xml | 6 +++--- app/src/main/res/values-fi/strings.xml | 4 ++-- app/src/main/res/values-fr/strings.xml | 6 +++--- app/src/main/res/values-gl/strings.xml | 6 +++--- app/src/main/res/values-hi/strings.xml | 6 +++--- app/src/main/res/values-hu/strings.xml | 6 +++--- app/src/main/res/values-in/strings.xml | 4 ++-- app/src/main/res/values-is/strings.xml | 4 ++-- app/src/main/res/values-it/strings.xml | 6 +++--- app/src/main/res/values-iw/strings.xml | 6 +++--- app/src/main/res/values-ja/strings.xml | 6 +++--- app/src/main/res/values-ka/strings.xml | 2 +- app/src/main/res/values-ko/strings.xml | 6 +++--- app/src/main/res/values-lb/strings.xml | 2 +- app/src/main/res/values-lv/strings.xml | 2 +- app/src/main/res/values-mk/strings.xml | 6 +++--- app/src/main/res/values-my/strings.xml | 4 ++-- app/src/main/res/values-nb/strings.xml | 6 +++--- app/src/main/res/values-ne/strings.xml | 2 +- app/src/main/res/values-nl/strings.xml | 6 +++--- app/src/main/res/values-pms/strings.xml | 6 +++--- app/src/main/res/values-pt-rBR/strings.xml | 6 +++--- app/src/main/res/values-pt/strings.xml | 6 +++--- app/src/main/res/values-ro/strings.xml | 2 +- app/src/main/res/values-ru/strings.xml | 6 +++--- app/src/main/res/values-sk/strings.xml | 6 +++--- app/src/main/res/values-sr/strings.xml | 6 +++--- app/src/main/res/values-su/strings.xml | 6 +++--- app/src/main/res/values-sv/strings.xml | 6 +++--- app/src/main/res/values-tcy/strings.xml | 6 +++--- app/src/main/res/values-te/strings.xml | 6 +++--- app/src/main/res/values-tr/strings.xml | 6 +++--- app/src/main/res/values-uk/strings.xml | 6 +++--- app/src/main/res/values-zh-rTW/strings.xml | 6 +++--- app/src/main/res/values-zh/strings.xml | 6 +++--- app/src/main/res/values/strings.xml | 6 +++--- 51 files changed, 130 insertions(+), 130 deletions(-) diff --git a/app/src/main/java/fr/free/nrw/commons/notification/NotificationActivity.java b/app/src/main/java/fr/free/nrw/commons/notification/NotificationActivity.java index 8bf60ddd9..69319e677 100644 --- a/app/src/main/java/fr/free/nrw/commons/notification/NotificationActivity.java +++ b/app/src/main/java/fr/free/nrw/commons/notification/NotificationActivity.java @@ -186,7 +186,7 @@ public class NotificationActivity extends NavigationBaseActivity { // Handle item selection switch (item.getItemId()) { case R.id.archived: - if (item.getTitle().equals(getString(R.string.menu_option_archived))) { + if (item.getTitle().equals(getString(R.string.menu_option_read))) { NotificationActivity.startYourself(NotificationActivity.this, "read"); }else if (item.getTitle().equals(getString(R.string.menu_option_unread))) { onBackPressed(); @@ -252,7 +252,7 @@ public class NotificationActivity extends NavigationBaseActivity { private void setPageTitle() { if (getSupportActionBar() != null) { if (getIntent().getStringExtra("title").equals("read")) { - getSupportActionBar().setTitle(R.string.archived_notifications); + getSupportActionBar().setTitle(R.string.read_notifications); } else { getSupportActionBar().setTitle(R.string.notifications); } @@ -261,7 +261,7 @@ public class NotificationActivity extends NavigationBaseActivity { private void setEmptyView() { if (getIntent().getStringExtra("title").equals("read")) { - noNotificationText.setText(R.string.no_archived_notification); + noNotificationText.setText(R.string.no_read_notification); }else { noNotificationText.setText(R.string.no_notification); } @@ -272,7 +272,7 @@ public class NotificationActivity extends NavigationBaseActivity { notificationMenuItem.setTitle(R.string.menu_option_unread); }else { - notificationMenuItem.setTitle(R.string.menu_option_archived); + notificationMenuItem.setTitle(R.string.menu_option_read); } } diff --git a/app/src/main/res/menu/menu_notifications.xml b/app/src/main/res/menu/menu_notifications.xml index b037dd760..69c503ea2 100644 --- a/app/src/main/res/menu/menu_notifications.xml +++ b/app/src/main/res/menu/menu_notifications.xml @@ -6,5 +6,5 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:icon="@drawable/ic_more_vert_white_24dp" - android:title="@string/menu_option_archived" /> + android:title="@string/menu_option_read" /> \ No newline at end of file diff --git a/app/src/main/res/values-af/strings.xml b/app/src/main/res/values-af/strings.xml index f63c78ba7..1b52b2343 100644 --- a/app/src/main/res/values-af/strings.xml +++ b/app/src/main/res/values-af/strings.xml @@ -372,7 +372,7 @@ bydraes Naby Kennisgewings - Kennisgewings (geargiveer) + Kennisgewings (geargiveer) Vertoon kennisgewing in die buurt Tik hier om die naaste plek te sien waar u foto\'s benodig Geen nabygeleë plekke gevind nie diff --git a/app/src/main/res/values-ar/strings.xml b/app/src/main/res/values-ar/strings.xml index cec512c81..a57f25d32 100644 --- a/app/src/main/res/values-ar/strings.xml +++ b/app/src/main/res/values-ar/strings.xml @@ -390,7 +390,7 @@ مساهمات مجاور الإشعارات - الإخطارات (مؤرشفة) + الإخطارات (مؤرشفة) عرض الإخطار القريب انقر هنا لرؤية أقرب مكان يحتاج إلى صور لم يتم العثور على أماكن قريبة بالقرب منك @@ -504,9 +504,9 @@ لم يتم إرجاع أية صور لا توجد صور مرفوعة ليست لديك إشعارات غير مقروءة - ليست لديك إشعارات مؤرشفة + ليست لديك إشعارات مؤرشفة مشاركة السجلات باستخدام - عرض المؤرشفة + عرض المؤرشفة عرض غير المقروءة حدث خطأ أثناء التقاط الصور اختيار الصور للرفع diff --git a/app/src/main/res/values-ast/strings.xml b/app/src/main/res/values-ast/strings.xml index 4c81d8ecd..d14525b39 100644 --- a/app/src/main/res/values-ast/strings.xml +++ b/app/src/main/res/values-ast/strings.xml @@ -379,7 +379,7 @@ Collaboraciones Cercanu Avisos - Avisos (archivaos) + Avisos (archivaos) Amosar notificaciones de cercanía Toca equí para ver el llugar más cercanu que precisa semeyes Nun s\'atoparon llugares cercanos nos alredores @@ -492,9 +492,9 @@ Nun se revertió nenguna imaxe Nun se xubió nenguna imaxe Nun tienes avisos ensin lleer - Nun tienes avisos archivaos + Nun tienes avisos archivaos Compartir rexistros usando - Ver los archivaos + Ver los archivaos Ver los nun lleíos Asocedió un error al escoyer les imaxes Escueyi les imaxes pa xubir diff --git a/app/src/main/res/values-bg/strings.xml b/app/src/main/res/values-bg/strings.xml index 6c80025b7..7cdbda210 100644 --- a/app/src/main/res/values-bg/strings.xml +++ b/app/src/main/res/values-bg/strings.xml @@ -214,7 +214,7 @@ Използване на персонализирано авторско име При качването използвайте персонализирано авторско име вместо потребителското си име Персонализирано авторско име - Известия (архивирани) + Известия (архивирани) Списък Следваща Изпращане @@ -244,9 +244,9 @@ Няма върнати изображения Няма качени изображения Нямате непрочетени известия - Нямате архивирани известия + Нямате архивирани известия Споделяне на дневници, използвайки - Преглеждане на архивирани + Преглеждане на архивирани Преглеждане на непрочетени Възникна грешка при избирането на изображенията Изберете изображения за качване diff --git a/app/src/main/res/values-br/strings.xml b/app/src/main/res/values-br/strings.xml index 89256ca19..267e38ba7 100644 --- a/app/src/main/res/values-br/strings.xml +++ b/app/src/main/res/values-br/strings.xml @@ -319,7 +319,7 @@ Ur fazi zo bet ! Implijit un anv aozer personelaet Nepell - Kemennoù(diellaouet) + Kemennoù(diellaouet) War-lerc\'h Kent Kas diff --git a/app/src/main/res/values-ca/strings.xml b/app/src/main/res/values-ca/strings.xml index 4f8e1ccfd..b91648bc4 100644 --- a/app/src/main/res/values-ca/strings.xml +++ b/app/src/main/res/values-ca/strings.xml @@ -356,7 +356,7 @@ Contribucions A prop Notificacions - Notificacions (arxivades) + Notificacions (arxivades) Mostra notificacions properes Feu un toc aquí per a veure el lloc més proper que necessiti fotos No s\'han trobat llocs propers prop vostre @@ -437,9 +437,9 @@ No s\'ha revertit cap imatge No s\'ha carregat cap imatge No teniu cap notificació sense llegir - No teniu cap notificació arxivada + No teniu cap notificació arxivada Comparteix els registres utilitzant - Mostra els arxivats + Mostra els arxivats Mostra aquelles per llegir S\'ha produït un error en escollir les imatges Trieu les imatges per carregar diff --git a/app/src/main/res/values-cs/strings.xml b/app/src/main/res/values-cs/strings.xml index 3d0cf5ac3..5fd413a74 100644 --- a/app/src/main/res/values-cs/strings.xml +++ b/app/src/main/res/values-cs/strings.xml @@ -395,7 +395,7 @@ Příspěvky Poblíž Upozornění - Upozornění (přečtená) + Upozornění (přečtená) Zobrazit upozornění v okolí Klepnutím sem zobrazíte nejbližší místo, které potřebuje obrázky Nebyla nalezena žádná místa v okolí @@ -508,9 +508,9 @@ Žádné revertované obrázky Žádné nahrané obrázky Nemáte žádná nepřečtená upozornění - Nemáte nepřečtená upozornění + Nemáte nepřečtená upozornění Sdílet logy pomocí - Zobrazit přečtené + Zobrazit přečtené Zobrazit nepřečtené Nastala chyba při vybírání obrázků Vyberte obrázky, které chcete nahrát diff --git a/app/src/main/res/values-da/strings.xml b/app/src/main/res/values-da/strings.xml index e07baae86..b45e75058 100644 --- a/app/src/main/res/values-da/strings.xml +++ b/app/src/main/res/values-da/strings.xml @@ -366,7 +366,7 @@ Næste billede Ingen billeder brugt Del logs ved hjælp af - Vis arkiverede + Vis arkiverede Vis ulæste Der opstod en fejl under udvælgelse af billeder Vent venligst… diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index b2e33835f..87bbe2cc9 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -388,7 +388,7 @@ Beiträge In der Nähe Benachrichtigungen - Benachrichtigungen (archiviert) + Benachrichtigungen (archiviert) Benachrichtigungen in der Nähe anzeigen Hier tippen, um Orte in der Nähe anzusehen, die Bilder benötigen. Keine Orte in deiner Umgebung gefunden. @@ -501,9 +501,9 @@ Keine Bilder zurückgesetzt Keine Bilder hochgeladen Du hast keine ungelesenen Benachrichtigungen - Du hast keine archivierten Benachrichtigungen + Du hast keine archivierten Benachrichtigungen Lognutzung teilen - Archivierte ansehen + Archivierte ansehen Ungelesene ansehen Beim Auswählen der Bilder ist ein Fehler aufgetreten Hochzuladende Bilder auswählen diff --git a/app/src/main/res/values-diq/strings.xml b/app/src/main/res/values-diq/strings.xml index 4acecf4f5..68f32e868 100644 --- a/app/src/main/res/values-diq/strings.xml +++ b/app/src/main/res/values-diq/strings.xml @@ -232,7 +232,7 @@ Nameyê nuştekariyo xısusiyi bıgurene Nameyê nuştekariyo xısusi İştıraki - Xeberi (arşifkerdeyi) + Xeberi (arşifkerdeyi) Liste Bahdoyên Verên @@ -256,8 +256,8 @@ Temam Eya, çıra mebo Beyanatên şımayê nêwendeyi çıniyê - Beyanatên şımayê arçivkerdeyi çıniyê - Arşivkerdeyan bıvêne + Beyanatên şımayê arçivkerdeyi çıniyê + Arşivkerdeyan bıvêne Nêwendeyan bıvêne Kerem kerên, bıpawên... NÊ RESIMİ RAVİYARNE diff --git a/app/src/main/res/values-el/strings.xml b/app/src/main/res/values-el/strings.xml index c38732446..cb4a83a76 100644 --- a/app/src/main/res/values-el/strings.xml +++ b/app/src/main/res/values-el/strings.xml @@ -406,7 +406,7 @@ Δεν χρησιμοποιούνται εικόνες Δεν έχουν ανεβεί εικόνες Δεν έχετε αδιάβαστες ενημερώσεις - Δεν έχετε αρχειοθετημένες ενημερώσεις + Δεν έχετε αρχειοθετημένες ενημερώσεις Παρακαλούμε περιμένετε… Δημιουργός Πνευματικά δικαιώματα diff --git a/app/src/main/res/values-eo/strings.xml b/app/src/main/res/values-eo/strings.xml index 958a01c68..34fd2d4de 100644 --- a/app/src/main/res/values-eo/strings.xml +++ b/app/src/main/res/values-eo/strings.xml @@ -381,7 +381,7 @@ Kontribuoj Apude Sciigoj - Sciigoj (enarkivigitaj) + Sciigoj (enarkivigitaj) Montri sciigojn pri apudaĵoj Tuŝetu ĉi tie por vidi apudan lokon kiu bezonas bildojn Neniu proksima loko trovita ĉe vi. @@ -494,9 +494,9 @@ Neniu bildo estis malfarita Neniu alŝutita bildo Vi ne havas nelegitajn sciigojn - Vi ne havas enarkivigitajn sciigojn + Vi ne havas enarkivigitajn sciigojn Konigi protokolojn per - Vidi enarkivigitojn + Vidi enarkivigitojn Vidi nelegitojn Eraro okazis dum elektado de bildoj Elekti alŝutotajn bildojn diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 4e06b93de..2e44e407e 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -404,7 +404,7 @@ Contribuciones Cercanos Notificaciones - Notificaciones (archivadas) + Notificaciones (archivadas) Mostrar notificaciones de cercanía Toca aquí para ver el lugar más cercano que necesita fotos No se encontraron lugares cercanos cerca de ti @@ -517,9 +517,9 @@ Ninguna imagen revertida Ninguna imagen subida No tienes notificaciones sin leer - No tienes notificaciones archivadas + No tienes notificaciones archivadas Compartir registros usando - Ver archivados + Ver archivados Ver no leidas Ocurrió un error mientras se elegían imagenes Elige imágenes para cargar diff --git a/app/src/main/res/values-fa/strings.xml b/app/src/main/res/values-fa/strings.xml index a87059e05..700bcda3b 100644 --- a/app/src/main/res/values-fa/strings.xml +++ b/app/src/main/res/values-fa/strings.xml @@ -376,7 +376,7 @@ مشارکت‌ها در نزدیکی آگاه‌سازی‌ها - اعلان‌ها (بایگانی‌شده) + اعلان‌ها (بایگانی‌شده) نمایش اعلان اطراف هیچ‌ مکان نزدیکی به شما یافته نشد فهرست @@ -453,8 +453,8 @@ تصویر برگردانده نشد هیچ تصویری بارگذاری نشد شما هیچ اعلان خوانده‌نشده‌ای ندارید - شما هیچ پیغام بایگانی شده‌ای ندارید - نمایش بایگانی‌شده + شما هیچ پیغام بایگانی شده‌ای ندارید + نمایش بایگانی‌شده مشاهده خوانده نشده ها انتخاب تصویر برای بارگذاری لطفاً صبر کنید... diff --git a/app/src/main/res/values-fi/strings.xml b/app/src/main/res/values-fi/strings.xml index b02bb3cbd..09398f233 100644 --- a/app/src/main/res/values-fi/strings.xml +++ b/app/src/main/res/values-fi/strings.xml @@ -366,7 +366,7 @@ Muokkaukset Lähistöllä Ilmoitukset - Ilmoitukset (arkistoidut) + Ilmoitukset (arkistoidut) Näytä lähistöllä-ilmoitus Lista Vaihe %1$d/%2$d @@ -420,7 +420,7 @@ Näyttää hyvälle Kyllä, miksi ei Seuraava kuva - Näytä arkistoidut + Näytä arkistoidut Näytä lukemattomat Valitse tallennettavat tiedostot Odota… diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index a3be5f3ad..15c3ea831 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -403,7 +403,7 @@ Contributions Proche Notifications - Notifications (archivées) + Notifications (archivées) Afficher la notification de proximité Taper ici pour voir l’endroit le plus proche qui a besoin d’images Aucun endroit à proximité trouvé près de chez vous @@ -517,9 +517,9 @@ Aucune image retournée Aucune image téléversée Vous n\'avez aucune notification non lue - Vous n’avez pas de notification archivée + Vous n’avez pas de notification archivée Partager les journaux en utilisant - Afficher les archivés + Afficher les archivés Afficher les non lus Erreur lors de la sélection des images Choisir les images à téléverser diff --git a/app/src/main/res/values-gl/strings.xml b/app/src/main/res/values-gl/strings.xml index fd3b45f8d..8ba7c1df1 100644 --- a/app/src/main/res/values-gl/strings.xml +++ b/app/src/main/res/values-gl/strings.xml @@ -385,7 +385,7 @@ Contribucións Preto Notificacións - Notificacións (arquivadas) + Notificacións (arquivadas) Amosar notificacións de proximidade Prema aquí para ver o lugar máis preto que necesita fotos Non se atoparon lugares preto de ti @@ -482,9 +482,9 @@ Ningunha imaxe revertida Ningunha imaxe subida Non ten ningunha notificación sen ler - Non ten notificacións arquivadas + Non ten notificacións arquivadas Compartir os rexistros usando - Ver arquivadas + Ver arquivadas Ver as non lidas Houbo un erro ó escoller as imaxes Escoller imaxes a subir diff --git a/app/src/main/res/values-hi/strings.xml b/app/src/main/res/values-hi/strings.xml index d103114a7..50fa9bd3a 100644 --- a/app/src/main/res/values-hi/strings.xml +++ b/app/src/main/res/values-hi/strings.xml @@ -351,7 +351,7 @@ योगदान निकट सूचनायें - सूचनाएँ (पुरालेखित) + सूचनाएँ (पुरालेखित) सूची स्टोरेज अनुमति अगला @@ -395,7 +395,7 @@ कोई चित्र वापस नहीं लाया कोई चित्र अपलोड नहीं किया आपके पास कोई अपठित सूचना नहीं है - आपकी कोई सूचना पुरालेखित नहीं है - पुरालेखित देखें + आपकी कोई सूचना पुरालेखित नहीं है + पुरालेखित देखें अपठित देखें diff --git a/app/src/main/res/values-hu/strings.xml b/app/src/main/res/values-hu/strings.xml index 319f0d5dd..374d36ae9 100644 --- a/app/src/main/res/values-hu/strings.xml +++ b/app/src/main/res/values-hu/strings.xml @@ -385,7 +385,7 @@ Közreműködések Közelben Értesítések - Archivált értesítések + Archivált értesítések Közeli értesítések megjelenítése Nem található közeli hely Lista @@ -494,8 +494,8 @@ Nincs visszavont kép Nincs feltöltött kép Nincs olvasatlan üzenet - Nincs archivált üzenet - Archiváltak megtekintése + Nincs archivált üzenet + Archiváltak megtekintése Olvasatlanok megtekintése Hiba történt a képek betöltése során Feltöltendő képek kiválasztása diff --git a/app/src/main/res/values-in/strings.xml b/app/src/main/res/values-in/strings.xml index 99310cce5..6845b996e 100644 --- a/app/src/main/res/values-in/strings.xml +++ b/app/src/main/res/values-in/strings.xml @@ -377,7 +377,7 @@ Kontribusi Sekitar Pemberitahuan - Pemberitahuan (diarsipkan) + Pemberitahuan (diarsipkan) Tampilkan pemberitahuan sekitar Tekan di sini untuk melihat tempat terdekat yang membutuhkan gambar Tidak ada tempat sekitaran yang ditemukan di dekat Anda @@ -430,7 +430,7 @@ Jangan pernah menanyakan ini lagi Tampilkan izin lokasi Sinahang penyobyahan - Lihat arsip + Lihat arsip Lihat yang belum terbaca Terjadi kesalahan ketika memilih gambar Pilih Gambar untuk diunggah diff --git a/app/src/main/res/values-is/strings.xml b/app/src/main/res/values-is/strings.xml index 09eac819c..ada0a186f 100644 --- a/app/src/main/res/values-is/strings.xml +++ b/app/src/main/res/values-is/strings.xml @@ -372,7 +372,7 @@ Framlög Nálægt Tilkynningar - Tilkynningar (í geymslu) + Tilkynningar (í geymslu) Birta tilkynningu um nágrenni Ýttu hér til að sjá nálægasta staðinn sem þarfnast mynda Engir staðir fundust í nágrenninu @@ -448,7 +448,7 @@ Engar myndir endurstilltar Engar myndir sendar inn Þú ert ekki með neinar ólesnar tilkynningar - Skoða í geymslu + Skoða í geymslu Skoða ólesið Villa kom upp við að velja myndir Veldu myndir til að senda inn diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index 6c5ec5970..943553530 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -384,7 +384,7 @@ Contributi Nelle vicinanze Notifiche - Notifiche (archiviate) + Notifiche (archiviate) Mostra notifica nelle vicinanze Tocca qui per vedere il luogo più vicino che ha bisogno di immagini Nessun posto nelle vicinanze trovato vicino a te @@ -464,9 +464,9 @@ Nessuna immagine ripristinata Nessuna immagine caricata Non hai alcuna notifica non letta - Non hai notifiche archiviate + Non hai notifiche archiviate Condividi i registri usando - Vedi archiviate + Vedi archiviate Vedi non lette Si è verificato un errore durante la selezione delle immagini Scegli le immagini da caricare diff --git a/app/src/main/res/values-iw/strings.xml b/app/src/main/res/values-iw/strings.xml index 67398761d..c84b191d4 100644 --- a/app/src/main/res/values-iw/strings.xml +++ b/app/src/main/res/values-iw/strings.xml @@ -393,7 +393,7 @@ תרומות בסביבה התראות - התראות (בארכיון) + התראות (בארכיון) הצגת התראות סמוכות יש לגעת כאן כדי לצפות במקום הקרוב ביותר שדורש תמונות לא נמצאו מקומות בסביבתך @@ -507,9 +507,9 @@ לא שוחזרו תמונות לא הועלו תמונות אין לך התראות שלא נקראו - אין לך התראות בארכיון + אין לך התראות בארכיון שיתוף יומנים בעזרת - הצגת ארכיון + הצגת ארכיון הצגת התראות שלא נקראו אירעה שגיאה בעת בחירת תמונות נא לבחור תמונות להעלאה diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml index 40ca17def..7c0d262bd 100644 --- a/app/src/main/res/values-ja/strings.xml +++ b/app/src/main/res/values-ja/strings.xml @@ -389,7 +389,7 @@ 投稿記録 付近 お知らせ - お知らせ(過去ログ) + お知らせ(過去ログ) 近くの場所のお知らせを表示する ここをタップして、近くで画像を募集中の場所を表示 現在地の近くに該当する場所が見つかりません @@ -501,9 +501,9 @@ 却下された画像はありません 投稿した画像はありません 未読のお知らせはありません - 過去ログ化したお知らせはありません + 過去ログ化したお知らせはありません ログの共有に使うアプリ - アーカイブ済みを表示 + アーカイブ済みを表示 未読を見る 画像の選択中にエラーが発生しました アップロードする画像を選ぶ diff --git a/app/src/main/res/values-ka/strings.xml b/app/src/main/res/values-ka/strings.xml index 5dcc15e52..7fb96c551 100644 --- a/app/src/main/res/values-ka/strings.xml +++ b/app/src/main/res/values-ka/strings.xml @@ -306,7 +306,7 @@ წვლილი ახლოს შეტყობინებები - შეტყობინებები (არქივი) + შეტყობინებები (არქივი) სია მეხსიერების ნებართვა ნაბიჯი %1$d %2$d-დან diff --git a/app/src/main/res/values-ko/strings.xml b/app/src/main/res/values-ko/strings.xml index d90b86a79..bde49a67c 100644 --- a/app/src/main/res/values-ko/strings.xml +++ b/app/src/main/res/values-ko/strings.xml @@ -374,7 +374,7 @@ 기여 근처 알림 - 알림 (보관됨) + 알림 (보관됨) 주변 알림 표시 사진이 필요한 주변 장소를 보려면 여기를 탭하세요 당신에게 가까운 주변 장소를 찾지 못했습니다 @@ -446,8 +446,8 @@ 이 버튼을 클릭하면 위키미디어 공용으로부터 최근 업로드된 다른 이미지를 제공합니다 이미지를 검토하고 위키미디어 공용의 품질을 개선할 수 있습니다.\n 4가지 검토 변수가 있습니다:\n - 이 이미지가 범위 내에 있는가? \n - 이 이미지가 저작권 규정을 준수하고 있는가? \n - 이 이미지가 올바르게 분류되어 있는가? \n - 모든 것이 문제 없다면 기여자에게 감사를 표할 수도 있습니다. 읽지 않은 알림이 없습니다 - 보관된 알림이 없습니다 - 보관한 항목 보기 + 보관된 알림이 없습니다 + 보관한 항목 보기 읽지 않은 항목 보기 이미지 선택 도중 오류가 발생했습니다 업로드할 이미지 선택 diff --git a/app/src/main/res/values-lb/strings.xml b/app/src/main/res/values-lb/strings.xml index 83049c8f1..9693868e8 100644 --- a/app/src/main/res/values-lb/strings.xml +++ b/app/src/main/res/values-lb/strings.xml @@ -337,7 +337,7 @@ Nächst BILD Keng Biller benotzt Keng Biller eropgelueden - Dir hutt keng archivéier Notifikatiounen + Dir hutt keng archivéier Notifikatiounen Feeler beim Eraussiche vun de Biller Sicht Biller eraus fir eropzelueden Waart wgl. ... diff --git a/app/src/main/res/values-lv/strings.xml b/app/src/main/res/values-lv/strings.xml index b84a9da37..cf441d6ce 100644 --- a/app/src/main/res/values-lv/strings.xml +++ b/app/src/main/res/values-lv/strings.xml @@ -188,7 +188,7 @@ Sūta pateicību Sūta pateicību Nākamais attēls - Skatīt arhivētos + Skatīt arhivētos Skatīt nelasītos Lūdzu, uzgaidiet... Izlaist šo attēlu diff --git a/app/src/main/res/values-mk/strings.xml b/app/src/main/res/values-mk/strings.xml index 5f2938fe7..cee5bf2a3 100644 --- a/app/src/main/res/values-mk/strings.xml +++ b/app/src/main/res/values-mk/strings.xml @@ -380,7 +380,7 @@ Придонеси Во близина Известувања - Известувања (архивирани) + Известувања (архивирани) Известувај ме за места во близина Допрете тука за да го видите најблиското место без слика Не најдов места во ваша близина @@ -494,9 +494,9 @@ Нема вратени слики Нема подигнати слики Немате непрочитани известувања - Немате архивирани известувања + Немате архивирани известувања Споделувај дневници користејќи - Погл. архивирани + Погл. архивирани Погл. непрочитани Се јави грешка при избирањето на сликите Изберете слики за подигање diff --git a/app/src/main/res/values-my/strings.xml b/app/src/main/res/values-my/strings.xml index 28b90fa2d..a3d088b86 100644 --- a/app/src/main/res/values-my/strings.xml +++ b/app/src/main/res/values-my/strings.xml @@ -287,7 +287,7 @@ ဆောင်ရွက်ချက်များ အနီးအနား အသိပေးချက်များ - အသိပေးချက်များ (မော်ကွန်းတင်ပြီး) + အသိပေးချက်များ (မော်ကွန်းတင်ပြီး) အနီးအနားအသိပေးချက်ကို ပြသရန် စာရင်း သိုလှောင်ခန်း ခွင်ပြုချက် @@ -348,7 +348,7 @@ အဆင်ပြေပုံပေါက်ပါသည် နောက်ရုပ်ပုံ မဖတ်ရသေးသော အသိပေးချက်များ မရှိပါ - မော်ကွန်းတင်ပြီးသော အသိပေးချက်များ မရှိပါ + မော်ကွန်းတင်ပြီးသော အသိပေးချက်များ မရှိပါ ကျေးဇူးပြု၍ ခဏစောင့်ပါ... ယခင် ခေါင်းစဉ်/ဖော်ပြချက် မိတ္တူကူးရန် နမူနာရုပ်ပုံများ အက်ပလုပ်တင်ရန် မဟုတ်ပါ diff --git a/app/src/main/res/values-nb/strings.xml b/app/src/main/res/values-nb/strings.xml index a21aa1d15..864ad351b 100644 --- a/app/src/main/res/values-nb/strings.xml +++ b/app/src/main/res/values-nb/strings.xml @@ -387,7 +387,7 @@ Bidrag I nærheten Varsler - Varsler (arkivert) + Varsler (arkivert) Vis varsel for steder i nærheten Trykk her for å se det nærmeste stedet som trenger bilder Ingen steder funnet i nærheten av deg @@ -500,9 +500,9 @@ Ingen bilder tilbakestilt Ingen bilder lastet opp Du har uleste varsler - Du har ingen arkiverte varsler + Du har ingen arkiverte varsler Del logger ved hjelp av - Vis arkiverte + Vis arkiverte Vis uleste Feil under utvalg av bilder Velg bilder å laste opp diff --git a/app/src/main/res/values-ne/strings.xml b/app/src/main/res/values-ne/strings.xml index 85772b472..2b2ee904b 100644 --- a/app/src/main/res/values-ne/strings.xml +++ b/app/src/main/res/values-ne/strings.xml @@ -254,7 +254,7 @@ योगदानहरू नजिकैको सूचनाहरू - सूचनाहरू (अभिलेख) + सूचनाहरू (अभिलेख) सूची भण्डारण अनुमति अर्को diff --git a/app/src/main/res/values-nl/strings.xml b/app/src/main/res/values-nl/strings.xml index d59fca8f2..2aeb12b5d 100644 --- a/app/src/main/res/values-nl/strings.xml +++ b/app/src/main/res/values-nl/strings.xml @@ -288,7 +288,7 @@ Bijdragen Dichtbij Meldingen - Meldingen (in het archief) + Meldingen (in het archief) Meldingen dichtbij weergeven Lijst Toestemming om op te slaan @@ -305,9 +305,9 @@ Machtiging voor locatie weergeven Naar machtiging voor locatie vragen als dat nodig is voor de functie meldingskaart dichtbij weergeven. Geen afbeeldingen geüpload - U hebt geen gearchiveerde melding + U hebt geen gearchiveerde melding Logboeken delen via - Gearchiveerd bekijken + Gearchiveerd bekijken Ongelezen bekijken Kies de afbeeldingen die u wilt plaatsen Een ogenblik geduld… diff --git a/app/src/main/res/values-pms/strings.xml b/app/src/main/res/values-pms/strings.xml index 01d67012c..5285ce8c6 100644 --- a/app/src/main/res/values-pms/strings.xml +++ b/app/src/main/res/values-pms/strings.xml @@ -378,7 +378,7 @@ Contribussion Davzin Notìfiche - Notìfiche (archivià) + Notìfiche (archivià) Smon-e la notìfica ëd prossimità Sgnaché sì për vëdde ël pòst pi davzin ch\'a l\'ha damanca ëd plance Gnun pòst trovà davzin a chiel @@ -492,9 +492,9 @@ Gnun-e plance anvertìe Gnun-e plance carià A l\'ha gnun-e notìfiche nen lesùe - A l\'ha gnun-e notìfiche archivià + A l\'ha gnun-e notìfiche archivià Partagé j\'argistr dovrand - Vëdde l\'archivi + Vëdde l\'archivi Vëdde lòn ch\'a l\'é ancor nen ëstàit lesù A-i é staje n\'eror an selessionand le plance Serne le plance da carié diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index 679d9ccfd..d0373232c 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -392,7 +392,7 @@ Contribuições Próximo Notificações - Notificações (arquivadas) + Notificações (arquivadas) Exibir notificação próxima Toque aqui para ver o local mais próximo que precisa de fotos Nenhum lugar próximo encontrado perto de você @@ -506,9 +506,9 @@ Nenhuma imagem revertida Nenhuma imagem enviada Não tem nenhuma notificação por ler - Não tem nenhuma notificação arquivada + Não tem nenhuma notificação arquivada Compartilhar registros usando - Ver arquivadas + Ver arquivadas Ver não lidas Ocorreu um erro ao escolher imagens Escolha imagens para fazer o carregamento diff --git a/app/src/main/res/values-pt/strings.xml b/app/src/main/res/values-pt/strings.xml index 0673b8559..1c8724152 100644 --- a/app/src/main/res/values-pt/strings.xml +++ b/app/src/main/res/values-pt/strings.xml @@ -392,7 +392,7 @@ Contribuições Aqui perto Notificações - Notificações (arquivadas) + Notificações (arquivadas) Apresentar notificação de proximidade Toque aqui para ver o local mais próximo que precisa de fotos Não foi encontrado nenhum local próximo @@ -505,9 +505,9 @@ Não foi revertida nenhuma imagem Não foi carregada nenhuma imagem Não tem nenhuma notificação por ler - Não tem nenhuma notificação arquivada + Não tem nenhuma notificação arquivada Partilhar os registos usando - Ver arquivadas + Ver arquivadas Ver não lidas Ocorreu um erro ao escolher imagens Escolher imagens a carregar diff --git a/app/src/main/res/values-ro/strings.xml b/app/src/main/res/values-ro/strings.xml index 4faf769ad..2b5da8d27 100644 --- a/app/src/main/res/values-ro/strings.xml +++ b/app/src/main/res/values-ro/strings.xml @@ -378,7 +378,7 @@ Contribuții În apropiere Notificări - Notificări (arhivate) + Notificări (arhivate) Afișați notificarea din apropiere Apăsați aici pentru a vedea cel mai apropiat loc care are nevoie de imagini Nu există locuri apropiate găsite în apropierea dvs. diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 96772fc79..564737fe8 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -400,7 +400,7 @@ Вклад Поблизости Уведомления - Уведомления (архивированные) + Уведомления (архивированные) Уведомлять меня о местах поблизости Нажмите здесь, чтобы увидеть ближайшее место без изображений Не найдено мест поблизости @@ -515,9 +515,9 @@ Нет откаченых изображений Нет загруженных изображений У вас нет непрочитанных уведомлений - Нет архивированных уведомлений + Нет архивированных уведомлений Поделиться лог-файлами - См. архивированные + См. архивированные См. непрочитанные Произошла ошибка при загрузке изображений Выберите изображения для загрузки diff --git a/app/src/main/res/values-sk/strings.xml b/app/src/main/res/values-sk/strings.xml index b37681efc..1e357b1a9 100644 --- a/app/src/main/res/values-sk/strings.xml +++ b/app/src/main/res/values-sk/strings.xml @@ -381,7 +381,7 @@ Príspevky V okolí Upozornenia - Upozornenia (prečítané) + Upozornenia (prečítané) Zobraziť notifikáciu o miestach v okolí Kliknutím sem sa zobrazí najbližšie miesto, ktoré potrebuje obrázky Vo vašej blízkosti neboli nájdené žiadne miesta @@ -495,9 +495,9 @@ Žiadne revertované obrázky Žiadne nahrané obrázky Nemáte žiadne neprečítané upozornenia - Nemáte žiadne prečítané upozornenia + Nemáte žiadne prečítané upozornenia Zdieľať log pomocou - Zobraziť prečítané + Zobraziť prečítané Zobraziť neprečítané Nastala chyba pri vyberaní obrázkov Vyberte obrázky, ktoré chcete nahrať diff --git a/app/src/main/res/values-sr/strings.xml b/app/src/main/res/values-sr/strings.xml index f201b3aea..2596f6cbf 100644 --- a/app/src/main/res/values-sr/strings.xml +++ b/app/src/main/res/values-sr/strings.xml @@ -379,7 +379,7 @@ Доприноси У близини Обавештења - Обавештења (архивирана) + Обавештења (архивирана) Прикажи обавештење у близини Притисните овде да бисте видели најближе место којем треба слика Нису пронађена места у близини близу вас @@ -475,9 +475,9 @@ Нема враћених слика Нема отпремљених слика Немате непрочитаних обавештења. - Немате архивираних обавештења + Немате архивираних обавештења Подели дневнике користећи - Прикажи архивирано + Прикажи архивирано Прикажи непрочитано Дошло је до грешке при избору слика Одабир слика за отпремање diff --git a/app/src/main/res/values-su/strings.xml b/app/src/main/res/values-su/strings.xml index d7df42583..6d6e74fc4 100644 --- a/app/src/main/res/values-su/strings.xml +++ b/app/src/main/res/values-su/strings.xml @@ -369,7 +369,7 @@ Kontribusi Sabudeureun Iber - Iber (arsip) + Iber (arsip) Témbongkeun iber sabudeureun Taya tempat sabudeureun nu kairong jang anjeun Daptar @@ -445,9 +445,9 @@ Taya gambar nu dibalikkeun Taya gambar diunjal Anjeun teu boga iber nu can dibaca - Anjeun teu boga iber arsip + Anjeun teu boga iber arsip Bagikeun log pamakéan - Tempo arsip + Tempo arsip Tempo nu can dibaca Éror pas keur nyomot gambar Pilih Gambar unjalkeuneun diff --git a/app/src/main/res/values-sv/strings.xml b/app/src/main/res/values-sv/strings.xml index 79c986d35..fc9e1b494 100644 --- a/app/src/main/res/values-sv/strings.xml +++ b/app/src/main/res/values-sv/strings.xml @@ -384,7 +384,7 @@ Bidrag I närheten Aviseringar - Aviseringar (arkiverade) + Aviseringar (arkiverade) Visa avisering för i närheten Tryck här för att se den närmaste platsen som behöver bilder Inga platser i närheten hittades som är nära dig @@ -498,9 +498,9 @@ Inga bilder återställdes Inga bilder laddades upp Du har inga olästa aviseringar - Du har inga arkiverade aviseringar + Du har inga arkiverade aviseringar Dela loggar med - Visa arkiverade + Visa arkiverade Visa olästa Fel uppstod när bilder valdes ut Välj bilder att ladda upp diff --git a/app/src/main/res/values-tcy/strings.xml b/app/src/main/res/values-tcy/strings.xml index d95410a14..b7ebf35fa 100644 --- a/app/src/main/res/values-tcy/strings.xml +++ b/app/src/main/res/values-tcy/strings.xml @@ -365,7 +365,7 @@ ಕಾಣಿಕೆಲು ಕೈತಲ್‍ದ ಅಧಿಸೂಚನೆಲು - ಅಧಿಸೂಚನೆಲು(ಅನುರಕ್ಷಿತ) + ಅಧಿಸೂಚನೆಲು(ಅನುರಕ್ಷಿತ) ಕೈತಲ್ದ ಅಧಿಸೂಚನೆ ತೋಜಾಲೆ ಚಿತ್ರ ಬೋಡಾಯಿನ ಕೈತಲ್ದ ಜಾಗ ತೂವರೆ ಮುಲ್ಪ ತಟ್ಟ್\'ಲೆ ಇರೆನ ಮುಟ್ಟೊಡು ಕೈತಲ್ದ ಜಾಗೊಲು ತಿಕ್ಕುಜಾ. @@ -395,8 +395,8 @@ ಯಾನ್ ಅವೆನ್ ತತ್ತ್\'ದ್ ಮಿತೇರಾಯೆ. ಅವು ಸಾರ್ವತ್ರಿಕವಾದ್ ತೋಜುಂಡು ಇಂದ್ ಎಂಕ್ ಗೊತ್ತಿತ್ತಿಜಿ. ಅವು ಎನ್ನ ಖಾಸಗಿತೆನೊಕು ಹಾಳ್ಂದ್ ಎಂಕ್ ತೆರಿಂಡ್. - ಇರೆಗ್ ಅನುರಕ್ಷಿತ ಅಧಿಸೂಚನೆ ಇಜ್ಜಿ - ಅನುರಕ್ಷಿತ ತೂಲೆ + ಇರೆಗ್ ಅನುರಕ್ಷಿತ ಅಧಿಸೂಚನೆ ಇಜ್ಜಿ + ಅನುರಕ್ಷಿತ ತೂಲೆ ಓದಂದಿನ ತೂಲೆ ಆಕೃತಿಲೆನ್ ಪೆಜ್ಜಿನಗ ದೋಷ ಆಂಡ್ ಮಿತರಾರೆ ಆಕೃತಿಲೆನ್ ಆಯುಲೆ diff --git a/app/src/main/res/values-te/strings.xml b/app/src/main/res/values-te/strings.xml index ef6505cd1..59f1cc03c 100644 --- a/app/src/main/res/values-te/strings.xml +++ b/app/src/main/res/values-te/strings.xml @@ -377,7 +377,7 @@ తోడ్పాటు చుట్టుపక్కల గమనింపులు - గమనింపులు (ఆర్కైవు చేసినవి) + గమనింపులు (ఆర్కైవు చేసినవి) చుట్టుపక్కల గమనింపును చూపించు బొమ్మలు అవసరమైన చుట్టుపక్కల స్థలాన్ని చూసేందుకు ఇక్కడ నొక్కండి మీ చుట్టుపక్కల స్థలాలేమీ కనబడలేదు @@ -490,9 +490,9 @@ బొమ్మలు వేటినీ వెనక్కి తిరక్కొట్టలేదు బొమ్మలేమీ ఎక్కించలేదు మీకు చదవని గమనింపులేమీ లేవు - మీకు ఆర్కైవు చేసిన గమనింపులేమీ లేవు + మీకు ఆర్కైవు చేసిన గమనింపులేమీ లేవు దీన్ని వాడి లాగ్‌లను పంచుకోండి - ఆర్కైవులను చూడండి + ఆర్కైవులను చూడండి చదవని వాటిని చూడండి బొమ్మలను ఎంచుకునేటపుడు లోపం దొర్లింది ఎక్కించేందుకు బొమ్మలను ఎంచుకోండి diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml index 5dd753902..c3d06a349 100644 --- a/app/src/main/res/values-tr/strings.xml +++ b/app/src/main/res/values-tr/strings.xml @@ -396,7 +396,7 @@ Katkılar Yakınındakiler Bildirimler - Bildirimler (arşivlenmiş) + Bildirimler (arşivlenmiş) Yakındaki bildirimi görüntüle Resimlere en yakın yeri görmek için buraya dokunun Size yakın bir yer bulunamadı @@ -510,9 +510,9 @@ Resim döndürülmedi Resim yüklenmedi Okunmamış bildirimleriniz yok - Arşivlenmiş bildiriminiz yok + Arşivlenmiş bildiriminiz yok Kullanarak günlükleri paylaş - Arşivlenmişleri görüntüle + Arşivlenmişleri görüntüle Okunmamışları görüntüle Resimler toplanırken hata oluştu Yüklenecek Görüntüleri Seçin diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml index 09e085aec..2231dfe16 100644 --- a/app/src/main/res/values-uk/strings.xml +++ b/app/src/main/res/values-uk/strings.xml @@ -397,7 +397,7 @@ Внесок Поблизу Сповіщення - Сповіщення (архівовані) + Сповіщення (архівовані) Повідомляти мене про місця поблизу Торкніться тут, щоб побачити найближчі місця, які ще не мають зображень Не знайдено місць поблизу Вас @@ -513,9 +513,9 @@ Відхилених зображень немає Завантажених зображень немає У вас немає непрочитаних сповіщень - Немає архівованих сповіщень + Немає архівованих сповіщень Поширення журналів - Перегляд архівованих + Перегляд архівованих Перегляд непрочитаних Сталася помилка при завантаженні зображень Оберіть зображення для завантаження diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index 221456947..ece9f77e8 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -389,7 +389,7 @@ 貢獻 附近 通知 - 通知(已存檔) + 通知(已存檔) 顯示附近地點通知 在此輕觸來查看缺少圖片的最近地點 查無靠近您的附近地點 @@ -503,9 +503,9 @@ 沒有圖片被還原回復 沒有圖片被上傳 您有尚未讀取的通知 - 您沒有已存檔通知 + 您沒有已存檔通知 分享日誌使用 - 檢視已存檔 + 檢視已存檔 檢視未讀 當挑選圖片時發生錯誤 選擇要上傳的圖片 diff --git a/app/src/main/res/values-zh/strings.xml b/app/src/main/res/values-zh/strings.xml index c94cccfdf..657ad0418 100644 --- a/app/src/main/res/values-zh/strings.xml +++ b/app/src/main/res/values-zh/strings.xml @@ -400,7 +400,7 @@ 贡献 附近 通知 - 通知(已存档) + 通知(已存档) 显示附近通知 点击此处查看最近需要图片的地方 附近找不到靠近您的地方 @@ -513,9 +513,9 @@ 没有被撤回的图片 还没有上传图片 您没有任何未读通知 - 您没有已存档的通知 + 您没有已存档的通知 分享日志于 - 查看已存档 + 查看已存档 查看未读 选择图片时出错 选择要上传的图片 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 515669225..73579f83b 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -393,7 +393,7 @@ Contributions Nearby Notifications - Notifications (archived) + Notifications (read) Display nearby notification Tap here to see the nearest place that needs pictures No nearby places found close to you @@ -521,9 +521,9 @@ Upload your first media by tapping on the add button. No images uploaded You have no unread notifications - You have no archived notifications + You have no read notifications Share logs using - View archived + View read View unread Error occurred while picking images