diff --git a/app/src/main/java/fr/free/nrw/commons/contributions/Contribution.java b/app/src/main/java/fr/free/nrw/commons/contributions/Contribution.java index 80c378137..99e6c4b45 100644 --- a/app/src/main/java/fr/free/nrw/commons/contributions/Contribution.java +++ b/app/src/main/java/fr/free/nrw/commons/contributions/Contribution.java @@ -6,7 +6,7 @@ import androidx.room.PrimaryKey; import fr.free.nrw.commons.Media; import fr.free.nrw.commons.auth.SessionManager; import fr.free.nrw.commons.upload.UploadMediaDetail; -import fr.free.nrw.commons.upload.UploadModel.UploadItem; +import fr.free.nrw.commons.upload.UploadItem; import fr.free.nrw.commons.upload.WikidataPlace; import fr.free.nrw.commons.upload.structure.depictions.DepictedItem; import java.util.ArrayList; diff --git a/app/src/main/java/fr/free/nrw/commons/repository/UploadLocalDataSource.java b/app/src/main/java/fr/free/nrw/commons/repository/UploadLocalDataSource.java deleted file mode 100644 index e4cd4df91..000000000 --- a/app/src/main/java/fr/free/nrw/commons/repository/UploadLocalDataSource.java +++ /dev/null @@ -1,151 +0,0 @@ -package fr.free.nrw.commons.repository; - -import androidx.annotation.Nullable; - -import java.util.List; - -import javax.inject.Inject; -import javax.inject.Named; -import javax.inject.Singleton; - -import fr.free.nrw.commons.kvstore.JsonKvStore; -import fr.free.nrw.commons.upload.UploadModel; -import fr.free.nrw.commons.upload.UploadModel.UploadItem; - -/** - * The Local Data Source for UploadRepository, fetches and returns data from local db/shared prefernces - */ - -@Singleton -public class UploadLocalDataSource { - - private final UploadModel uploadModel; - private JsonKvStore defaultKVStore; - - @Inject - public UploadLocalDataSource( - @Named("default_preferences") JsonKvStore defaultKVStore, - UploadModel uploadModel) { - this.defaultKVStore = defaultKVStore; - this.uploadModel = uploadModel; - } - - - /** - * Fetches and returns the string list of valid licenses - * - * @return - */ - public List getLicenses() { - return uploadModel.getLicenses(); - } - - /** - * Returns the number of Upload Items - * - * @return - */ - public int getCount() { - return uploadModel.getCount(); - } - - /** - * Fetches and return the selected license for the current upload - * - * @return - */ - public String getSelectedLicense() { - return uploadModel.getSelectedLicense(); - } - - /** - * Set selected license for the current upload - * - * @param licenseName - */ - public void setSelectedLicense(String licenseName) { - uploadModel.setSelectedLicense(licenseName); - } - - /** - * Updates the current upload item - * - * @param index - * @param uploadItem - */ - public void updateUploadItem(int index, UploadItem uploadItem) { - uploadModel.updateUploadItem(index, uploadItem); - } - - /** - * upload is halted, cleanup the acquired resources - */ - public void cleanUp() { - uploadModel.cleanUp(); - } - - /** - * Deletes the upload item at the current index - * - * @param filePath - */ - public void deletePicture(String filePath) { - uploadModel.deletePicture(filePath); - } - - /** - * Fethces and returns the previous upload item, if any, returns null otherwise - * - * @param index - * @return - */ - @Nullable - public UploadItem getPreviousUploadItem(int index) { - if (index - 1 >= 0) { - return uploadModel.getItems().get(index - 1); - } - return null; //There is no previous item to copy details - } - - /** - * saves boolean value in default store - * - * @param key - * @param value - */ - public void saveValue(String key, boolean value) { - defaultKVStore.putBoolean(key, value); - } - - /** - * saves string value in default store - * - * @param key - * @param value - */ - public void saveValue(String key, String value) { - defaultKVStore.putString(key, value); - } - - /** - * Fetches and returns string value from the default store - * - * @param key - * @param defaultValue - * @return - */ - public String getValue(String key, String defaultValue) { - return defaultKVStore.getString(key, defaultValue); - } - - /** - * Fetches and returns boolean value from the default store - * - * @param key - * @param defaultValue - * @return - */ - public boolean getValue(String key, boolean defaultValue) { - return defaultKVStore.getBoolean(key, defaultValue); - } -} 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 deleted file mode 100644 index 61fd61736..000000000 --- a/app/src/main/java/fr/free/nrw/commons/repository/UploadRemoteDataSource.java +++ /dev/null @@ -1,230 +0,0 @@ -package fr.free.nrw.commons.repository; - -import fr.free.nrw.commons.category.CategoriesModel; -import fr.free.nrw.commons.category.CategoryItem; -import fr.free.nrw.commons.contributions.Contribution; -import fr.free.nrw.commons.filepicker.UploadableFile; -import fr.free.nrw.commons.location.LatLng; -import fr.free.nrw.commons.nearby.NearbyPlaces; -import fr.free.nrw.commons.nearby.Place; -import fr.free.nrw.commons.upload.ImageCoordinates; -import fr.free.nrw.commons.upload.SimilarImageInterface; -import fr.free.nrw.commons.upload.UploadController; -import fr.free.nrw.commons.upload.UploadModel; -import fr.free.nrw.commons.upload.UploadModel.UploadItem; -import fr.free.nrw.commons.upload.structure.depictions.DepictModel; -import fr.free.nrw.commons.upload.structure.depictions.DepictedItem; -import io.reactivex.Flowable; -import io.reactivex.Observable; -import io.reactivex.Single; -import java.io.IOException; -import java.util.Comparator; -import java.util.List; -import java.util.Locale; -import javax.inject.Inject; -import javax.inject.Singleton; - -/** - * This class would act as the data source for remote operations for UploadActivity - */ -@Singleton -public class UploadRemoteDataSource { - - private static final double NEARBY_RADIUS_IN_KILO_METERS = 0.1; //100 meters - - private UploadModel uploadModel; - private UploadController uploadController; - private CategoriesModel categoriesModel; - private DepictModel depictModel; - private NearbyPlaces nearbyPlaces; - - @Inject - public UploadRemoteDataSource(UploadModel uploadModel, UploadController uploadController, - CategoriesModel categoriesModel, NearbyPlaces nearbyPlaces, DepictModel depictModel) { - this.uploadModel = uploadModel; - this.uploadController = uploadController; - this.categoriesModel = categoriesModel; - this.nearbyPlaces = nearbyPlaces; - this.depictModel = depictModel; - } - - /** - * asks the UploadModel to build the contributions - * - * @return - */ - public Observable buildContributions() { - return uploadModel.buildContributions(); - } - - /** - * asks the UploadService to star the uplaod for - * - * @param contribution - */ - public void startUpload(Contribution contribution) { - uploadController.startUpload(contribution); - } - - /** - * returns the list of UploadItem from the UploadModel - * - * @return - */ - public List getUploads() { - return uploadModel.getUploads(); - } - - /** - * Prepare the UploadService for the upload - */ - public void prepareService() { - uploadController.prepareService(); - } - - /** - * Clean up the selected categories - */ - public void cleanUp(){ - //This needs further refactoring, this should not be here, right now the structure wont suppoort rhis - categoriesModel.cleanUp(); - depictModel.cleanUp(); - } - - /** - * returnt the list of selected categories - * - * @return - */ - public List getSelectedCategories() { - return categoriesModel.getSelectedCategories(); - } - - /** - * all categories from MWApi - * - * @param query - * @param imageTitleList - * @return - */ - public Observable searchAll(String query, List imageTitleList) { - return categoriesModel.searchAll(query, imageTitleList); - } - - /** - * returns the string list of categories - * - * @return - */ - public List getCategoryStringList() { - return categoriesModel.getCategoryStringList(); - } - - /** - * sets the selected categories in the UploadModel - * - * @param categoryStringList - */ - public void setSelectedCategories(List categoryStringList) { - uploadModel.setSelectedCategories(categoryStringList); - } - - /** - * handles category selection/unselection - * - * @param categoryItem - */ - public void onCategoryClicked(CategoryItem categoryItem) { - categoriesModel.onCategoryItemClicked(categoryItem); - } - - /** - * returns category sorted based on similarity with query - * - * @param query - * @return - */ - public Comparator sortBySimilarity(String query) { - return categoriesModel.sortBySimilarity(query); - } - - /** - * prunes the category list for irrelevant categories see #750 - * - * @param name - * @return - */ - public boolean containsYear(String name) { - return categoriesModel.containsYear(name); - } - - /** - * pre process the UploadableFile - * - * @param uploadableFile - * @param place - * @param similarImageInterface - * @return - */ - public Observable preProcessImage(UploadableFile uploadableFile, Place place, - SimilarImageInterface similarImageInterface) { - return uploadModel.preProcessImage(uploadableFile, place, similarImageInterface); - } - - /** - * ask the UplaodModel for the image quality of the UploadItem - * - * @param uploadItem - * @return - */ - public Single getImageQuality(UploadItem uploadItem) { - return uploadModel.getImageQuality(uploadItem); - } - - /** - * gets nearby places matching with upload item's GPS location - * - * @param latitude - * @param longitude - * @return - */ - public Place getNearbyPlaces(double latitude, double longitude) throws IOException { - List fromWikidataQuery = nearbyPlaces - .getFromWikidataQuery(new LatLng(latitude, longitude, 0.0f), - Locale.getDefault().getLanguage(), - NEARBY_RADIUS_IN_KILO_METERS); - return fromWikidataQuery.size() > 0 ? fromWikidataQuery.get(0) : null; - - } - - /** - * handles category selection/unselection - * @param depictedItem - */ - - public void onDepictedItemClicked(DepictedItem depictedItem) { - uploadModel.onDepictItemClicked(depictedItem); - } - - /** - * returns the list of selected depictions - * @return - */ - - public List getSelectedDepictions() { - return uploadModel.getSelectedDepictions(); - } - - /** - * get all depictions - * @return - */ - - public Flowable> searchAllEntities(String query) { - return depictModel.searchAllEntities(query); - } - - 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 9f4d9497a..5dc9c137a 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,24 +1,28 @@ package fr.free.nrw.commons.repository; -import fr.free.nrw.commons.upload.ImageCoordinates; -import io.reactivex.Flowable; -import java.io.IOException; -import java.util.Comparator; -import java.util.List; - -import javax.inject.Inject; -import javax.inject.Singleton; - +import fr.free.nrw.commons.category.CategoriesModel; import fr.free.nrw.commons.category.CategoryItem; import fr.free.nrw.commons.contributions.Contribution; import fr.free.nrw.commons.filepicker.UploadableFile; +import fr.free.nrw.commons.location.LatLng; +import fr.free.nrw.commons.nearby.NearbyPlaces; import fr.free.nrw.commons.nearby.Place; +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.UploadController; +import fr.free.nrw.commons.upload.UploadItem; +import fr.free.nrw.commons.upload.UploadModel; +import fr.free.nrw.commons.upload.structure.depictions.DepictModel; import fr.free.nrw.commons.upload.structure.depictions.DepictedItem; - +import io.reactivex.Flowable; import io.reactivex.Observable; import io.reactivex.Single; +import java.io.IOException; +import java.util.Comparator; +import java.util.List; +import java.util.Locale; +import javax.inject.Inject; +import javax.inject.Singleton; /** * The repository class for UploadActivity @@ -26,14 +30,25 @@ import io.reactivex.Single; @Singleton public class UploadRepository { - private UploadLocalDataSource localDataSource; - private UploadRemoteDataSource remoteDataSource; + private final UploadModel uploadModel; + private final UploadController uploadController; + private final CategoriesModel categoriesModel; + private final NearbyPlaces nearbyPlaces; + private final DepictModel depictModel; + + private static final double NEARBY_RADIUS_IN_KILO_METERS = 0.1; //100 meters @Inject - public UploadRepository(UploadLocalDataSource localDataSource, - UploadRemoteDataSource remoteDataSource) { - this.localDataSource = localDataSource; - this.remoteDataSource = remoteDataSource; + public UploadRepository(UploadModel uploadModel, + UploadController uploadController, + CategoriesModel categoriesModel, + NearbyPlaces nearbyPlaces, + DepictModel depictModel) { + this.uploadModel = uploadModel; + this.uploadController = uploadController; + this.categoriesModel = categoriesModel; + this.nearbyPlaces = nearbyPlaces; + this.depictModel = depictModel; } /** @@ -42,7 +57,7 @@ public class UploadRepository { * @return */ public Observable buildContributions() { - return remoteDataSource.buildContributions(); + return uploadModel.buildContributions(); } /** @@ -51,7 +66,7 @@ public class UploadRepository { * @param contribution */ public void startUpload(Contribution contribution) { - remoteDataSource.startUpload(contribution); + uploadController.startUpload(contribution); } /** @@ -60,22 +75,24 @@ public class UploadRepository { * @return */ public List getUploads() { - return remoteDataSource.getUploads(); + return uploadModel.getUploads(); } /** * asks the RemoteDataSource to prepare the Upload Service */ public void prepareService() { - remoteDataSource.prepareService(); + uploadController.prepareService(); } /** *Prepare for a fresh upload */ public void cleanup() { - localDataSource.cleanUp(); - remoteDataSource.cleanUp(); + uploadModel.cleanUp(); + //This needs further refactoring, this should not be here, right now the structure wont suppoort rhis + categoriesModel.cleanUp(); + depictModel.cleanUp(); } /** @@ -84,7 +101,7 @@ public class UploadRepository { * @return */ public List getSelectedCategories() { - return remoteDataSource.getSelectedCategories(); + return categoriesModel.getSelectedCategories(); } /** @@ -95,7 +112,7 @@ public class UploadRepository { * @return */ public Observable searchAll(String query, List imageTitleList) { - return remoteDataSource.searchAll(query, imageTitleList); + return categoriesModel.searchAll(query, imageTitleList); } /** @@ -105,7 +122,7 @@ public class UploadRepository { */ public List getCategoryStringList() { - return remoteDataSource.getCategoryStringList(); + return categoriesModel.getCategoryStringList(); } /** @@ -114,7 +131,7 @@ public class UploadRepository { * @param categoryStringList */ public void setSelectedCategories(List categoryStringList) { - remoteDataSource.setSelectedCategories(categoryStringList); + uploadModel.setSelectedCategories(categoryStringList); } /** @@ -123,7 +140,7 @@ public class UploadRepository { * @param categoryItem */ public void onCategoryClicked(CategoryItem categoryItem) { - remoteDataSource.onCategoryClicked(categoryItem); + categoriesModel.onCategoryItemClicked(categoryItem); } /** @@ -133,7 +150,7 @@ public class UploadRepository { * @return */ public Comparator sortBySimilarity(String query) { - return remoteDataSource.sortBySimilarity(query); + return categoriesModel.sortBySimilarity(query); } /** @@ -143,7 +160,7 @@ public class UploadRepository { * @return */ public boolean containsYear(String name) { - return remoteDataSource.containsYear(name); + return categoriesModel.containsYear(name); } /** @@ -152,7 +169,7 @@ public class UploadRepository { * @return */ public List getLicenses() { - return localDataSource.getLicenses(); + return uploadModel.getLicenses(); } /** @@ -161,7 +178,7 @@ public class UploadRepository { * @return */ public String getSelectedLicense() { - return localDataSource.getSelectedLicense(); + return uploadModel.getSelectedLicense(); } /** @@ -170,7 +187,7 @@ public class UploadRepository { * @return */ public int getCount() { - return localDataSource.getCount(); + return uploadModel.getCount(); } /** @@ -183,7 +200,8 @@ public class UploadRepository { */ public Observable preProcessImage(UploadableFile uploadableFile, Place place, SimilarImageInterface similarImageInterface) { - return remoteDataSource.preProcessImage(uploadableFile, place, similarImageInterface); + return uploadModel.preProcessImage(uploadableFile, place, + similarImageInterface); } /** @@ -193,17 +211,7 @@ public class UploadRepository { * @return */ public Single getImageQuality(UploadItem uploadItem) { - return remoteDataSource.getImageQuality(uploadItem); - } - - /** - * asks the LocalDataSource to update the Upload Item - * - * @param index - * @param uploadItem - */ - public void updateUploadItem(int index, UploadItem uploadItem) { - localDataSource.updateUploadItem(index, uploadItem); + return uploadModel.getImageQuality(uploadItem); } /** @@ -212,7 +220,7 @@ public class UploadRepository { * @param filePath */ public void deletePicture(String filePath) { - localDataSource.deletePicture(filePath); + uploadModel.deletePicture(filePath); } /** @@ -222,38 +230,10 @@ public class UploadRepository { * @return */ public UploadItem getPreviousUploadItem(int index) { - return localDataSource.getPreviousUploadItem(index); - } - - /** - * Save boolean value locally - * - * @param key - * @param value - */ - public void saveValue(String key, boolean value) { - localDataSource.saveValue(key, value); - } - - /** - * save string value locally - * - * @param key - * @param value - */ - public void saveValue(String key, String value) { - localDataSource.saveValue(key, value); - } - - /** - * fetch the string value for the associated key - * - * @param key - * @param value - * @return - */ - public String getValue(String key, String value) { - return localDataSource.getValue(key, value); + if (index - 1 >= 0) { + return uploadModel.getItems().get(index - 1); + } + return null; //There is no previous item to copy details } /** @@ -262,11 +242,11 @@ public class UploadRepository { * @param licenseName */ public void setSelectedLicense(String licenseName) { - localDataSource.setSelectedLicense(licenseName); + uploadModel.setSelectedLicense(licenseName); } public void onDepictItemClicked(DepictedItem depictedItem) { - remoteDataSource.onDepictedItemClicked(depictedItem); + uploadModel.onDepictItemClicked(depictedItem); } /** @@ -276,7 +256,7 @@ public class UploadRepository { */ public List getSelectedDepictions() { - return remoteDataSource.getSelectedDepictions(); + return uploadModel.getSelectedDepictions(); } /** @@ -287,7 +267,7 @@ public class UploadRepository { */ public Flowable> searchAllEntities(String query) { - return remoteDataSource.searchAllEntities(query); + return depictModel.searchAllEntities(query); } /** @@ -296,11 +276,19 @@ public class UploadRepository { * @param decLongitude * @return */ - public Place checkNearbyPlaces(double decLatitude, double decLongitude) throws IOException { - return remoteDataSource.getNearbyPlaces(decLatitude, decLongitude); + public Place checkNearbyPlaces(double decLatitude, double decLongitude) { + try { + List fromWikidataQuery = nearbyPlaces.getFromWikidataQuery(new LatLng( + decLatitude, decLongitude, 0.0f), + Locale.getDefault().getLanguage(), + NEARBY_RADIUS_IN_KILO_METERS); + return fromWikidataQuery.size() > 0 ? fromWikidataQuery.get(0) : null; + } catch (IOException e) { + return null; + } } public void useSimilarPictureCoordinates(ImageCoordinates imageCoordinates, int uploadItemIndex) { - remoteDataSource.useSimilarPictureCoordinates(imageCoordinates, uploadItemIndex); + uploadModel.useSimilarPictureCoordinates(imageCoordinates, uploadItemIndex); } } diff --git a/app/src/main/java/fr/free/nrw/commons/upload/ImageProcessingService.java b/app/src/main/java/fr/free/nrw/commons/upload/ImageProcessingService.java index 7bcec4fb0..e04afe979 100644 --- a/app/src/main/java/fr/free/nrw/commons/upload/ImageProcessingService.java +++ b/app/src/main/java/fr/free/nrw/commons/upload/ImageProcessingService.java @@ -45,7 +45,7 @@ public class ImageProcessingService { * Check image quality before upload - checks duplicate image - checks dark image - checks * geolocation for image - check for valid title */ - Single validateImage(UploadModel.UploadItem uploadItem) { + Single validateImage(UploadItem uploadItem) { int currentImageQuality = uploadItem.getImageQuality(); Timber.d("Current image quality is %d", currentImageQuality); if (currentImageQuality == ImageUtils.IMAGE_KEEP) { @@ -97,7 +97,7 @@ public class ImageProcessingService { * @param uploadItem * @return */ - private Single validateItemTitle(UploadModel.UploadItem uploadItem) { + private Single validateItemTitle(UploadItem uploadItem) { Timber.d("Checking for image title %s", uploadItem.getUploadMediaDetails()); List captions = uploadItem.getUploadMediaDetails(); if (captions.isEmpty()) { diff --git a/app/src/main/java/fr/free/nrw/commons/upload/UploadItem.java b/app/src/main/java/fr/free/nrw/commons/upload/UploadItem.java new file mode 100644 index 000000000..140edad24 --- /dev/null +++ b/app/src/main/java/fr/free/nrw/commons/upload/UploadItem.java @@ -0,0 +1,106 @@ +package fr.free.nrw.commons.upload; + +import android.annotation.SuppressLint; +import android.net.Uri; +import androidx.annotation.Nullable; +import fr.free.nrw.commons.Utils; +import fr.free.nrw.commons.filepicker.MimeTypeMapWrapper; +import fr.free.nrw.commons.nearby.Place; +import fr.free.nrw.commons.utils.ImageUtils; +import io.reactivex.subjects.BehaviorSubject; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class UploadItem { + + private final Uri mediaUri; + private final String mimeType; + private ImageCoordinates gpsCoords; + private List uploadMediaDetails; + private final Place place; + private final long createdTimestamp; + private final String createdTimestampSource; + private final BehaviorSubject imageQuality; + + @SuppressLint("CheckResult") + UploadItem(final Uri mediaUri, + final String mimeType, + final ImageCoordinates gpsCoords, + final Place place, + final long createdTimestamp, + final String createdTimestampSource) { + this.createdTimestampSource = createdTimestampSource; + uploadMediaDetails = new ArrayList<>(Collections.singletonList(new UploadMediaDetail())); + this.place = place; + this.mediaUri = mediaUri; + this.mimeType = mimeType; + this.gpsCoords = gpsCoords; + this.createdTimestamp = createdTimestamp; + imageQuality = BehaviorSubject.createDefault(ImageUtils.IMAGE_WAIT); + } + + public String getCreatedTimestampSource() { + return createdTimestampSource; + } + + public ImageCoordinates getGpsCoords() { + return gpsCoords; + } + + public List getUploadMediaDetails() { + return uploadMediaDetails; + } + + public long getCreatedTimestamp() { + return createdTimestamp; + } + + public Uri getMediaUri() { + return mediaUri; + } + + public int getImageQuality() { + return imageQuality.getValue(); + } + + public void setImageQuality(final int imageQuality) { + this.imageQuality.onNext(imageQuality); + } + + public Place getPlace() { + return place; + } + + public void setMediaDetails(final List uploadMediaDetails) { + this.uploadMediaDetails = uploadMediaDetails; + } + + @Override + public boolean equals(@Nullable final Object obj) { + if (!(obj instanceof UploadItem)) { + return false; + } + return mediaUri.toString().contains(((UploadItem) (obj)).mediaUri.toString()); + + } + + @Override + public int hashCode() { + return mediaUri.hashCode(); + } + + /** + * Choose a filename for the media. Currently, the caption is used as a filename. If several + * languages have been entered, the first language is used. + */ + public String getFileName() { + return Utils.fixExtension(uploadMediaDetails.get(0).getCaptionText(), + MimeTypeMapWrapper.getExtensionFromMimeType(mimeType)); + } + + public void setGpsCoords(final ImageCoordinates gpsCoords) { + this.gpsCoords = gpsCoords; + } + +} diff --git a/app/src/main/java/fr/free/nrw/commons/upload/UploadMediaDetail.kt b/app/src/main/java/fr/free/nrw/commons/upload/UploadMediaDetail.kt index 2617ff903..30369f578 100644 --- a/app/src/main/java/fr/free/nrw/commons/upload/UploadMediaDetail.kt +++ b/app/src/main/java/fr/free/nrw/commons/upload/UploadMediaDetail.kt @@ -17,6 +17,8 @@ data class UploadMediaDetail constructor( var descriptionText: String = "", var captionText: String = "" ) { + fun javaCopy() = copy() + constructor(place: Place) : this( Locale.getDefault().language, place.longDescription, 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 061fb8cd8..e94a3df46 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 @@ -1,25 +1,18 @@ package fr.free.nrw.commons.upload; -import android.annotation.SuppressLint; import android.content.Context; import android.net.Uri; -import androidx.annotation.Nullable; -import fr.free.nrw.commons.Utils; import fr.free.nrw.commons.auth.SessionManager; import fr.free.nrw.commons.contributions.Contribution; -import fr.free.nrw.commons.filepicker.MimeTypeMapWrapper; 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.settings.Prefs; import fr.free.nrw.commons.upload.structure.depictions.DepictedItem; -import fr.free.nrw.commons.utils.ImageUtils; 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.Arrays; import java.util.Date; import java.util.Iterator; import java.util.List; @@ -44,8 +37,8 @@ public class UploadModel { private final SessionManager sessionManager; private final FileProcessor fileProcessor; private final ImageProcessingService imageProcessingService; - private List selectedCategories = new ArrayList<>(); - private List selectedDepictions = new ArrayList<>(); + private final List selectedCategories = new ArrayList<>(); + private final List selectedDepictions = new ArrayList<>(); @Inject UploadModel(@Named("licenses") final List licenses, @@ -77,7 +70,8 @@ public class UploadModel { } public void setSelectedCategories(List selectedCategories) { - this.selectedCategories = selectedCategories; + this.selectedCategories.clear(); + this.selectedCategories.addAll(selectedCategories); } /** @@ -150,7 +144,7 @@ public class UploadModel { Timber.d("Created timestamp while building contribution is %s, %s", item.getCreatedTimestamp(), new Date(item.getCreatedTimestamp())); - if (item.createdTimestamp != -1L) { + if (item.getCreatedTimestamp() != -1L) { contribution.setDateCreated(new Date(item.getCreatedTimestamp())); contribution.setDateCreatedSource(item.getCreatedTimestampSource()); //Set the date only if you have it, else the upload service is gonna try it the other way @@ -162,7 +156,7 @@ public class UploadModel { public void deletePicture(final String filePath) { final Iterator iterator = items.iterator(); while (iterator.hasNext()) { - if (iterator.next().mediaUri.toString().contains(filePath)) { + if (iterator.next().getMediaUri().toString().contains(filePath)) { iterator.remove(); break; } @@ -176,11 +170,6 @@ public class UploadModel { return items; } - public void updateUploadItem(final int index, final UploadItem uploadItem) { - final UploadItem uploadItem1 = items.get(index); - uploadItem1.setMediaDetails(uploadItem.uploadMediaDetails); - } - public void onDepictItemClicked(DepictedItem depictedItem) { if (depictedItem.isSelected()) { selectedDepictions.add(depictedItem); @@ -202,97 +191,4 @@ public class UploadModel { public List getSelectedDepictions() { return selectedDepictions; } - - @SuppressWarnings("WeakerAccess") - public static class UploadItem { - - private final Uri mediaUri; - private final String mimeType; - private ImageCoordinates gpsCoords; - private List uploadMediaDetails; - private final Place place; - private final long createdTimestamp; - private final String createdTimestampSource; - private final BehaviorSubject imageQuality; - @SuppressLint("CheckResult") - UploadItem(final Uri mediaUri, - final String mimeType, - final ImageCoordinates gpsCoords, - final Place place, - final long createdTimestamp, - final String createdTimestampSource) { - this.createdTimestampSource = createdTimestampSource; - uploadMediaDetails = new ArrayList<>(Arrays.asList(new UploadMediaDetail())); - this.place = place; - this.mediaUri = mediaUri; - this.mimeType = mimeType; - this.gpsCoords = gpsCoords; - this.createdTimestamp = createdTimestamp; - imageQuality = BehaviorSubject.createDefault(ImageUtils.IMAGE_WAIT); - } - - public String getCreatedTimestampSource() { - return createdTimestampSource; - } - - public ImageCoordinates getGpsCoords() { - return gpsCoords; - } - - public List getUploadMediaDetails() { - return uploadMediaDetails; - } - - public long getCreatedTimestamp() { - return createdTimestamp; - } - - public Uri getMediaUri() { - return mediaUri; - } - - public int getImageQuality() { - return this.imageQuality.getValue(); - } - - public void setImageQuality(final int imageQuality) { - this.imageQuality.onNext(imageQuality); - } - - public Place getPlace() { - return place; - } - - public void setMediaDetails(final List uploadMediaDetails) { - this.uploadMediaDetails = uploadMediaDetails; - } - - @Override - public boolean equals(@Nullable final Object obj) { - if (!(obj instanceof UploadItem)) { - return false; - } - return this.mediaUri.toString().contains(((UploadItem) (obj)).mediaUri.toString()); - - } - - @Override - public int hashCode() { - return mediaUri.hashCode(); - } - - /** - * Choose a filename for the media. - * Currently, the caption is used as a filename. If several languages have been entered, the first language is used. - */ - public String getFileName() { - return Utils.fixExtension(uploadMediaDetails.get(0).getCaptionText(), - MimeTypeMapWrapper.getExtensionFromMimeType(mimeType)); - } - - public void setGpsCoords(final ImageCoordinates gpsCoords) { - this.gpsCoords = gpsCoords; - } - - } } diff --git a/app/src/main/java/fr/free/nrw/commons/upload/UploadView.java b/app/src/main/java/fr/free/nrw/commons/upload/UploadView.java index e9e83784c..83b8fdab3 100644 --- a/app/src/main/java/fr/free/nrw/commons/upload/UploadView.java +++ b/app/src/main/java/fr/free/nrw/commons/upload/UploadView.java @@ -30,7 +30,7 @@ public interface UploadView { boolean checkIfLoggedIn(); - void updateThumbnails(List uploads); + void updateThumbnails(List uploads); void setNextEnabled(boolean available); @@ -54,7 +54,7 @@ public interface UploadView { void updateRightCardContent(boolean gpsPresent); - void updateBottomCardContent(int currentStep, int stepCount, UploadModel.UploadItem uploadItem, boolean isShowingItem); + void updateBottomCardContent(int currentStep, int stepCount, UploadItem uploadItem, boolean isShowingItem); void updateLicenses(List licenses, String selectedLicense); diff --git a/app/src/main/java/fr/free/nrw/commons/upload/categories/CategoriesPresenter.java b/app/src/main/java/fr/free/nrw/commons/upload/categories/CategoriesPresenter.java index aaa52a85c..28a69110b 100644 --- a/app/src/main/java/fr/free/nrw/commons/upload/categories/CategoriesPresenter.java +++ b/app/src/main/java/fr/free/nrw/commons/upload/categories/CategoriesPresenter.java @@ -7,7 +7,7 @@ import android.text.TextUtils; import fr.free.nrw.commons.R; import fr.free.nrw.commons.category.CategoryItem; import fr.free.nrw.commons.repository.UploadRepository; -import fr.free.nrw.commons.upload.UploadModel.UploadItem; +import fr.free.nrw.commons.upload.UploadItem; import io.reactivex.Observable; import io.reactivex.Scheduler; import io.reactivex.disposables.CompositeDisposable; diff --git a/app/src/main/java/fr/free/nrw/commons/upload/license/MediaLicensePresenter.java b/app/src/main/java/fr/free/nrw/commons/upload/license/MediaLicensePresenter.java index 7e84a06df..ca6cd4f04 100644 --- a/app/src/main/java/fr/free/nrw/commons/upload/license/MediaLicensePresenter.java +++ b/app/src/main/java/fr/free/nrw/commons/upload/license/MediaLicensePresenter.java @@ -1,14 +1,14 @@ package fr.free.nrw.commons.upload.license; -import java.lang.reflect.Proxy; -import java.util.List; - -import javax.inject.Inject; - import fr.free.nrw.commons.Utils; +import fr.free.nrw.commons.kvstore.JsonKvStore; import fr.free.nrw.commons.repository.UploadRepository; import fr.free.nrw.commons.settings.Prefs; import fr.free.nrw.commons.upload.license.MediaLicenseContract.View; +import java.lang.reflect.Proxy; +import java.util.List; +import javax.inject.Inject; +import javax.inject.Named; import timber.log.Timber; /** @@ -23,11 +23,14 @@ public class MediaLicensePresenter implements MediaLicenseContract.UserActionLis (proxy, method, methodArgs) -> null); private final UploadRepository repository; + private final JsonKvStore defaultKVStore; private MediaLicenseContract.View view = DUMMY; @Inject - public MediaLicensePresenter(UploadRepository uploadRepository) { + public MediaLicensePresenter(UploadRepository uploadRepository, + @Named("default_preferences") JsonKvStore defaultKVStore) { this.repository = uploadRepository; + this.defaultKVStore = defaultKVStore; } @Override @@ -48,14 +51,14 @@ public class MediaLicensePresenter implements MediaLicenseContract.UserActionLis List licenses = repository.getLicenses(); view.setLicenses(licenses); - String selectedLicense = repository.getValue(Prefs.DEFAULT_LICENSE, + String selectedLicense = defaultKVStore.getString(Prefs.DEFAULT_LICENSE, Prefs.Licenses.CC_BY_SA_4);//CC_BY_SA_4 is the default one used by the commons web app try {//I have to make sure that the stored default license was not one of the deprecated one's Utils.licenseNameFor(selectedLicense); } catch (IllegalStateException exception) { Timber.e(exception.getMessage()); selectedLicense = Prefs.Licenses.CC_BY_SA_4; - repository.saveValue(Prefs.DEFAULT_LICENSE, Prefs.Licenses.CC_BY_SA_4); + defaultKVStore.putString(Prefs.DEFAULT_LICENSE, Prefs.Licenses.CC_BY_SA_4); } view.setSelectedLicense(selectedLicense); 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 a2c3d99d2..6ced3e1b5 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 @@ -31,8 +31,7 @@ import fr.free.nrw.commons.upload.SimilarImageDialogFragment; import fr.free.nrw.commons.upload.UploadBaseFragment; import fr.free.nrw.commons.upload.UploadMediaDetail; import fr.free.nrw.commons.upload.UploadMediaDetailAdapter; -import fr.free.nrw.commons.upload.UploadModel; -import fr.free.nrw.commons.upload.UploadModel.UploadItem; +import fr.free.nrw.commons.upload.UploadItem; import fr.free.nrw.commons.utils.DialogUtil; import fr.free.nrw.commons.utils.ImageUtils; import fr.free.nrw.commons.utils.ViewUtil; @@ -45,8 +44,6 @@ import javax.inject.Named; import org.apache.commons.lang3.StringUtils; import timber.log.Timber; -//import fr.free.nrw.commons.upload.DescriptionsAdapter; - public class UploadMediaDetailFragment extends UploadBaseFragment implements UploadMediaDetailsContract.View, UploadMediaDetailAdapter.EventListener { @@ -70,9 +67,6 @@ public class UploadMediaDetailFragment extends UploadBaseFragment implements @BindView(R.id.btn_copy_prev_title_desc) AppCompatButton btnCopyPreviousTitleDesc; - private UploadModel.UploadItem uploadItem; - private List descriptions; - @Inject UploadMediaDetailsContract.UserActionListener presenter; @@ -181,8 +175,7 @@ public class UploadMediaDetailFragment extends UploadBaseFragment implements @OnClick(R.id.btn_next) public void onNextButtonClicked() { - uploadItem.setMediaDetails(uploadMediaDetailAdapter.getUploadMediaDetails()); - presenter.verifyImageQuality(uploadItem); + presenter.verifyImageQuality(callback.getIndexInViewFlipper(this)); } @OnClick(R.id.btn_previous) @@ -222,10 +215,7 @@ public class UploadMediaDetailFragment extends UploadBaseFragment implements @Override public void onImageProcessed(UploadItem uploadItem, Place place) { - this.uploadItem = uploadItem; - descriptions = uploadItem.getUploadMediaDetails(); photoViewBackgroundImage.setImageURI(uploadItem.getMediaUri()); - setDescriptionsInAdapter(descriptions); } /** @@ -242,8 +232,7 @@ public class UploadMediaDetailFragment extends UploadBaseFragment implements getString(R.string.upload_nearby_place_found_description), place.getName()), () -> { - descriptions = new ArrayList<>(Arrays.asList(new UploadMediaDetail(place))); - setDescriptionsInAdapter(descriptions); + presenter.onUserConfirmedUploadIsOfPlace(place, callback.getIndexInViewFlipper(this)); }, () -> { @@ -257,7 +246,6 @@ public class UploadMediaDetailFragment extends UploadBaseFragment implements @Override public void onImageValidationSuccess() { - presenter.setUploadItem(callback.getIndexInViewFlipper(this), uploadItem); callback.onNextButtonClicked(callback.getIndexInViewFlipper(this)); } @@ -272,7 +260,7 @@ public class UploadMediaDetailFragment extends UploadBaseFragment implements } @Override - public void showDuplicatePicturePopup() { + public void showDuplicatePicturePopup(UploadItem uploadItem) { String uploadTitleFormat = getString(R.string.upload_title_duplicate); DialogUtil.showAlertDialog(getActivity(), getString(R.string.duplicate_image_found), @@ -289,7 +277,8 @@ public class UploadMediaDetailFragment extends UploadBaseFragment implements } @Override - public void showBadImagePopup(Integer errorCode) { + public void showBadImagePopup(Integer errorCode, + UploadItem uploadItem) { String errorMessageForResult = getErrorMessageForResult(getContext(), errorCode); if (!StringUtils.isBlank(errorMessageForResult)) { DialogUtil.showAlertDialog(getActivity(), @@ -312,8 +301,15 @@ public class UploadMediaDetailFragment extends UploadBaseFragment implements } @Override - public void setCaptionsAndDescriptions(List uploadMediaDetails) { - setDescriptionsInAdapter(uploadMediaDetails); + public void showExternalMap(UploadItem uploadItem) { + Utils.handleGeoCoordinates(getContext(), + new LatLng(uploadItem.getGpsCoords().getDecLatitude(), + uploadItem.getGpsCoords().getDecLongitude(), 0.0f)); + } + + @Override + public void updateMediaDetails(List uploadMediaDetails) { + uploadMediaDetailAdapter.setItems(uploadMediaDetails); } private void deleteThisPicture() { @@ -342,9 +338,7 @@ public class UploadMediaDetailFragment extends UploadBaseFragment implements } @OnClick(R.id.ib_map) public void onIbMapClicked() { - Utils.handleGeoCoordinates(getContext(), - new LatLng(uploadItem.getGpsCoords().getDecLatitude(), - uploadItem.getGpsCoords().getDecLongitude(), 0.0f)); + presenter.onMapIconClicked(callback.getIndexInViewFlipper(this)); } @Override @@ -354,7 +348,6 @@ public class UploadMediaDetailFragment extends UploadBaseFragment implements btnNext.setAlpha(isNotEmpty ? 1.0f: 0.5f); } - public interface UploadMediaDetailFragmentCallback extends Callback { void deletePictureAtIndex(int index); @@ -366,7 +359,4 @@ public class UploadMediaDetailFragment extends UploadBaseFragment implements presenter.fetchPreviousTitleAndDescription(callback.getIndexInViewFlipper(this)); } - private void setDescriptionsInAdapter(List uploadMediaDetails){ - uploadMediaDetailAdapter.setItems(uploadMediaDetails); - } } 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 47a807b7e..495a8b40e 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 @@ -6,7 +6,7 @@ import fr.free.nrw.commons.nearby.Place; import fr.free.nrw.commons.upload.ImageCoordinates; import fr.free.nrw.commons.upload.SimilarImageInterface; import fr.free.nrw.commons.upload.UploadMediaDetail; -import fr.free.nrw.commons.upload.UploadModel.UploadItem; +import fr.free.nrw.commons.upload.UploadItem; import java.util.List; /** @@ -28,27 +28,30 @@ public interface UploadMediaDetailsContract { void showMessage(String message, int colorResourceId); - void showDuplicatePicturePopup(); + void showDuplicatePicturePopup(UploadItem uploadItem); - void showBadImagePopup(Integer errorCode); + void showBadImagePopup(Integer errorCode, UploadItem uploadItem); void showMapWithImageCoordinates(boolean shouldShow); - void setCaptionsAndDescriptions(List uploadMediaDetails); + void showExternalMap(UploadItem uploadItem); + + void updateMediaDetails(List uploadMediaDetails); } interface UserActionListener extends BasePresenter { void receiveImage(UploadableFile uploadableFile, Place place); - void verifyImageQuality(UploadItem uploadItem); - - void setUploadItem(int index, UploadItem uploadItem); + void verifyImageQuality(int uploadItemIndex); void fetchPreviousTitleAndDescription(int indexInViewFlipper); void useSimilarPictureCoordinates(ImageCoordinates imageCoordinates, int uploadItemIndex); + void onMapIconClicked(int indexInViewFlipper); + + void onUserConfirmedUploadIsOfPlace(Place place, int uploadItemPosition); } } 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 9f8ed530c..ab1c229e8 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 @@ -9,11 +9,13 @@ 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.kvstore.JsonKvStore; import fr.free.nrw.commons.nearby.Place; import fr.free.nrw.commons.repository.UploadRepository; 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.UploadItem; +import fr.free.nrw.commons.upload.UploadMediaDetail; import fr.free.nrw.commons.upload.mediaDetails.UploadMediaDetailsContract.UserActionListener; import fr.free.nrw.commons.upload.mediaDetails.UploadMediaDetailsContract.View; import io.reactivex.Maybe; @@ -21,8 +23,11 @@ import io.reactivex.Scheduler; import io.reactivex.disposables.CompositeDisposable; import io.reactivex.disposables.Disposable; import java.lang.reflect.Proxy; +import java.util.ArrayList; +import java.util.List; import javax.inject.Inject; import javax.inject.Named; +import org.jetbrains.annotations.NotNull; import timber.log.Timber; public class UploadMediaPresenter implements UserActionListener, SimilarImageInterface { @@ -38,14 +43,17 @@ public class UploadMediaPresenter implements UserActionListener, SimilarImageInt private CompositeDisposable compositeDisposable; + private final JsonKvStore defaultKVStore; private Scheduler ioScheduler; private Scheduler mainThreadScheduler; @Inject public UploadMediaPresenter(UploadRepository uploadRepository, + @Named("default_preferences") JsonKvStore defaultKVStore, @Named(IO_THREAD) Scheduler ioScheduler, @Named(MAIN_THREAD) Scheduler mainThreadScheduler) { this.repository = uploadRepository; + this.defaultKVStore = defaultKVStore; this.ioScheduler = ioScheduler; this.mainThreadScheduler = mainThreadScheduler; compositeDisposable = new CompositeDisposable(); @@ -70,22 +78,25 @@ public class UploadMediaPresenter implements UserActionListener, SimilarImageInt @Override public void receiveImage(UploadableFile uploadableFile, Place place) { view.showProgress(true); - Disposable uploadItemDisposable = repository + compositeDisposable.add( + repository .preProcessImage(uploadableFile, place, this) .subscribeOn(ioScheduler) .observeOn(mainThreadScheduler) .subscribe(uploadItem -> - { - view.onImageProcessed(uploadItem, place); - ImageCoordinates gpsCoords = uploadItem.getGpsCoords(); - view.showMapWithImageCoordinates(gpsCoords != null && gpsCoords.getImageCoordsExists()); - view.showProgress(false); - if (gpsCoords != null && gpsCoords.getImageCoordsExists()) { - checkNearbyPlaces(uploadItem); - } - }, - throwable -> Timber.e(throwable, "Error occurred in pre-processing images")); - compositeDisposable.add(uploadItemDisposable); + { + view.onImageProcessed(uploadItem, place); + view.updateMediaDetails(uploadItem.getUploadMediaDetails()); + ImageCoordinates gpsCoords = uploadItem.getGpsCoords(); + final boolean hasImageCoordinates = + gpsCoords != null && gpsCoords.getImageCoordsExists(); + view.showMapWithImageCoordinates(hasImageCoordinates); + view.showProgress(false); + if (hasImageCoordinates) { + checkNearbyPlaces(uploadItem); + } + }, + throwable -> Timber.e(throwable, "Error occurred in processing images"))); } /** @@ -110,19 +121,20 @@ public class UploadMediaPresenter implements UserActionListener, SimilarImageInt /** * asks the repository to verify image quality * - * @param uploadItem + * @param uploadItemIndex */ @Override - public void verifyImageQuality(UploadItem uploadItem) { + public void verifyImageQuality(int uploadItemIndex) { view.showProgress(true); - compositeDisposable.add( + final UploadItem uploadItem = repository.getUploads().get(uploadItemIndex); + compositeDisposable.add( repository .getImageQuality(uploadItem) .observeOn(mainThreadScheduler) .subscribe(imageResult -> { view.showProgress(false); - handleImageResult(imageResult); + handleImageResult(imageResult, uploadItem); }, throwable -> { view.showProgress(false); @@ -133,16 +145,6 @@ public class UploadMediaPresenter implements UserActionListener, SimilarImageInt ); } - /** - * Adds the corresponding upload item to the repository - * - * @param index - * @param uploadItem - */ - @Override - public void setUploadItem(int index, UploadItem uploadItem) { - repository.updateUploadItem(index, uploadItem); - } /** * Fetches and sets the caption and desctiption of the previous item @@ -152,28 +154,55 @@ public class UploadMediaPresenter implements UserActionListener, SimilarImageInt @Override public void fetchPreviousTitleAndDescription(int indexInViewFlipper) { UploadItem previousUploadItem = repository.getPreviousUploadItem(indexInViewFlipper); - if (null != previousUploadItem) { - view.setCaptionsAndDescriptions(previousUploadItem.getUploadMediaDetails()); + if (null != previousUploadItem) { + final UploadItem currentUploadItem = repository.getUploads().get(indexInViewFlipper); + currentUploadItem.setMediaDetails(deepCopy(previousUploadItem.getUploadMediaDetails())); + view.updateMediaDetails(currentUploadItem.getUploadMediaDetails()); } else { view.showMessage(R.string.previous_image_title_description_not_found, R.color.color_error); } } + @NotNull + private List deepCopy(List uploadMediaDetails) { + final ArrayList newList = new ArrayList<>(); + for (UploadMediaDetail uploadMediaDetail : uploadMediaDetails) { + newList.add(uploadMediaDetail.javaCopy()); + } + return newList; + } + @Override public void useSimilarPictureCoordinates(ImageCoordinates imageCoordinates, int uploadItemIndex) { repository.useSimilarPictureCoordinates(imageCoordinates, uploadItemIndex); } + @Override + public void onMapIconClicked(int indexInViewFlipper) { + view.showExternalMap(repository.getUploads().get(indexInViewFlipper)); + } + + @Override + public void onUserConfirmedUploadIsOfPlace(Place place, int uploadItemPosition) { + final List uploadMediaDetails = repository.getUploads() + .get(uploadItemPosition) + .getUploadMediaDetails(); + uploadMediaDetails.set(0, new UploadMediaDetail(place)); + view.updateMediaDetails(uploadMediaDetails); + } + /** * handles image quality verifications * - * @param imageResult - */ - public void handleImageResult(Integer imageResult) { + * @param imageResult + * @param uploadItem + */ + public void handleImageResult(Integer imageResult, + UploadItem uploadItem) { if (imageResult == IMAGE_KEEP || imageResult == IMAGE_OK) { view.onImageValidationSuccess(); } else { - handleBadImage(imageResult); + handleBadImage(imageResult, uploadItem); } } @@ -181,12 +210,13 @@ public class UploadMediaPresenter implements UserActionListener, SimilarImageInt * Handle images, say empty caption, duplicate file name, bad picture(in all other cases) * * @param errorCode + * @param uploadItem */ - public void handleBadImage(Integer errorCode) { + public void handleBadImage(Integer errorCode, UploadItem uploadItem) { Timber.d("Handle bad picture with error code %d", errorCode); - if (errorCode - >= 8) { // If location of image and nearby does not match, then set shared preferences to disable wikidata edits - repository.saveValue("Picture_Has_Correct_Location", false); + // If location of image and nearby does not match, then set shared preferences to disable wikidata edits + if (errorCode >= 8) { + defaultKVStore.putBoolean("Picture_Has_Correct_Location", false); } switch (errorCode) { @@ -196,10 +226,10 @@ public class UploadMediaPresenter implements UserActionListener, SimilarImageInt break; case FILE_NAME_EXISTS: Timber.d("Trying to show duplicate picture popup"); - view.showDuplicatePicturePopup(); + view.showDuplicatePicturePopup(uploadItem); break; default: - view.showBadImagePopup(errorCode); + view.showBadImagePopup(errorCode, uploadItem); } } diff --git a/app/src/test/kotlin/fr/free/nrw/commons/upload/ImageProcessingServiceTest.kt b/app/src/test/kotlin/fr/free/nrw/commons/upload/ImageProcessingServiceTest.kt index 97026b7e2..5257debf6 100644 --- a/app/src/test/kotlin/fr/free/nrw/commons/upload/ImageProcessingServiceTest.kt +++ b/app/src/test/kotlin/fr/free/nrw/commons/upload/ImageProcessingServiceTest.kt @@ -33,7 +33,7 @@ class u { var imageProcessingService: ImageProcessingService? = null @Mock - internal lateinit var uploadItem: UploadModel.UploadItem + internal lateinit var uploadItem: UploadItem @Before @Throws(Exception::class) diff --git a/app/src/test/kotlin/fr/free/nrw/commons/upload/MediaLicensePresenterTest.kt b/app/src/test/kotlin/fr/free/nrw/commons/upload/MediaLicensePresenterTest.kt index aaae0343a..b45d0175d 100644 --- a/app/src/test/kotlin/fr/free/nrw/commons/upload/MediaLicensePresenterTest.kt +++ b/app/src/test/kotlin/fr/free/nrw/commons/upload/MediaLicensePresenterTest.kt @@ -2,6 +2,7 @@ package fr.free.nrw.commons.upload import com.nhaarman.mockitokotlin2.verify import fr.free.nrw.commons.Utils +import fr.free.nrw.commons.kvstore.JsonKvStore import fr.free.nrw.commons.repository.UploadRepository import fr.free.nrw.commons.upload.license.MediaLicenseContract import fr.free.nrw.commons.upload.license.MediaLicensePresenter @@ -24,13 +25,16 @@ import org.powermock.modules.junit4.PowerMockRunner @PrepareForTest(Utils::class) class MediaLicensePresenterTest { @Mock - internal var repository: UploadRepository? = null + internal lateinit var repository: UploadRepository @Mock - internal var view: MediaLicenseContract.View? = null + internal lateinit var defaultKvStore: JsonKvStore + + @Mock + internal lateinit var view: MediaLicenseContract.View @InjectMocks - var mediaLicensePresenter: MediaLicensePresenter? = null + lateinit var mediaLicensePresenter: MediaLicensePresenter /** * initial setup test environemnt @@ -39,7 +43,7 @@ class MediaLicensePresenterTest { @Throws(Exception::class) fun setUp() { MockitoAnnotations.initMocks(this) - mediaLicensePresenter?.onAttachView(view) + mediaLicensePresenter.onAttachView(view) PowerMockito.mockStatic(Utils::class.java) PowerMockito.`when`(Utils.licenseNameFor(ArgumentMatchers.anyString())).thenReturn(1) } @@ -50,9 +54,9 @@ class MediaLicensePresenterTest { */ @Test fun getLicenseTest() { - mediaLicensePresenter?.getLicenses() - verify(view)?.setLicenses(ArgumentMatchers.anyList()) - verify(view)?.setSelectedLicense(ArgumentMatchers.any()) + mediaLicensePresenter.getLicenses() + verify(view).setLicenses(ArgumentMatchers.anyList()) + verify(view).setSelectedLicense(ArgumentMatchers.any()) } /** @@ -60,7 +64,7 @@ class MediaLicensePresenterTest { */ @Test fun selectLicenseTest() { - mediaLicensePresenter?.selectLicense(ArgumentMatchers.anyString()) - verify(view)?.updateLicenseSummary(ArgumentMatchers.any(), ArgumentMatchers.anyInt()) + mediaLicensePresenter.selectLicense(ArgumentMatchers.anyString()) + verify(view).updateLicenseSummary(ArgumentMatchers.any(), ArgumentMatchers.anyInt()) } -} \ 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 b16021ced..b95d24ff8 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 @@ -3,6 +3,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.kvstore.JsonKvStore import fr.free.nrw.commons.nearby.Place import fr.free.nrw.commons.repository.UploadRepository import fr.free.nrw.commons.upload.mediaDetails.UploadMediaDetailsContract @@ -41,16 +42,19 @@ class UploadMediaPresenterTest { private lateinit var place: Place @Mock - private lateinit var uploadItem: UploadModel.UploadItem + private lateinit var uploadItem: UploadItem @Mock private lateinit var uploadMediaDetails: List - private lateinit var testObservableUploadItem: Observable + private lateinit var testObservableUploadItem: Observable private lateinit var testSingleImageResult: Single private lateinit var testScheduler: TestScheduler + @Mock + private lateinit var jsonKvStore: JsonKvStore + /** * initial setup unit test environment */ @@ -61,7 +65,8 @@ class UploadMediaPresenterTest { testObservableUploadItem = Observable.just(uploadItem) testSingleImageResult = Single.just(1) testScheduler = TestScheduler() - uploadMediaPresenter = UploadMediaPresenter(repository, testScheduler, testScheduler) + uploadMediaPresenter = UploadMediaPresenter(repository, + jsonKvStore,testScheduler, testScheduler) uploadMediaPresenter.onAttachView(view) } @@ -81,7 +86,7 @@ class UploadMediaPresenterTest { verify(view).showProgress(true) testScheduler.triggerActions() verify(view).onImageProcessed( - ArgumentMatchers.any(UploadModel.UploadItem::class.java), + ArgumentMatchers.any(UploadItem::class.java), ArgumentMatchers.any(Place::class.java) ) verify(view).showProgress(false) @@ -92,10 +97,11 @@ class UploadMediaPresenterTest { */ @Test fun verifyImageQualityTest() { - whenever(repository.getImageQuality(ArgumentMatchers.any(UploadModel.UploadItem::class.java))) + whenever(repository.uploads).thenReturn(listOf(uploadItem)) + whenever(repository.getImageQuality(uploadItem)) .thenReturn(testSingleImageResult) whenever(uploadItem.imageQuality).thenReturn(ArgumentMatchers.anyInt()) - uploadMediaPresenter.verifyImageQuality(uploadItem) + uploadMediaPresenter.verifyImageQuality(0) verify(view).showProgress(true) testScheduler.triggerActions() verify(view).showProgress(false) @@ -107,21 +113,21 @@ class UploadMediaPresenterTest { @Test fun handleImageResult() { //Positive case test - uploadMediaPresenter.handleImageResult(IMAGE_KEEP) + uploadMediaPresenter.handleImageResult(IMAGE_KEEP, uploadItem) verify(view).onImageValidationSuccess() //Duplicate file name - uploadMediaPresenter.handleImageResult(FILE_NAME_EXISTS) - verify(view).showDuplicatePicturePopup() + uploadMediaPresenter.handleImageResult(FILE_NAME_EXISTS, uploadItem) + verify(view).showDuplicatePicturePopup(uploadItem) //Empty Caption test - uploadMediaPresenter.handleImageResult(EMPTY_CAPTION) + uploadMediaPresenter.handleImageResult(EMPTY_CAPTION, uploadItem) verify(view).showMessage(ArgumentMatchers.anyInt(), ArgumentMatchers.anyInt()) //Bad Picture test //Empty Caption test - uploadMediaPresenter.handleImageResult(-7) - verify(view)?.showBadImagePopup(ArgumentMatchers.anyInt()) + uploadMediaPresenter.handleImageResult(-7, uploadItem) + verify(view)?.showBadImagePopup(ArgumentMatchers.anyInt(), eq(uploadItem)) } @@ -138,7 +144,6 @@ class UploadMediaPresenterTest { testScheduler.triggerActions() verify(view).showProgress(true) verify(view).onImageValidationSuccess() - uploadMediaPresenter.setUploadItem(0, uploadItem) } } @@ -155,7 +160,6 @@ class UploadMediaPresenterTest { testScheduler.triggerActions() verify(view).showProgress(true) verify(view).onImageValidationSuccess() - uploadMediaPresenter.setUploadItem(0, uploadItem) } } @@ -164,12 +168,13 @@ class UploadMediaPresenterTest { */ @Test fun fetchPreviousImageAndTitleTestPositive() { + whenever(repository.uploads).thenReturn(listOf(uploadItem)) whenever(repository.getPreviousUploadItem(ArgumentMatchers.anyInt())) .thenReturn(uploadItem) - whenever(uploadItem.uploadMediaDetails).thenReturn(uploadMediaDetails) + whenever(uploadItem.uploadMediaDetails).thenReturn(listOf()) uploadMediaPresenter.fetchPreviousTitleAndDescription(0) - verify(view).setCaptionsAndDescriptions(ArgumentMatchers.any()) + verify(view).updateMediaDetails(ArgumentMatchers.any()) } /** @@ -188,9 +193,9 @@ class UploadMediaPresenterTest { */ @Test fun handleBadImageBaseTestInvalidLocation() { - uploadMediaPresenter.handleBadImage(8) - verify(repository).saveValue(ArgumentMatchers.anyString(), eq(false)) - verify(view).showBadImagePopup(8) + uploadMediaPresenter.handleBadImage(8, uploadItem) + verify(jsonKvStore).putBoolean(ArgumentMatchers.anyString(), eq(false)) + verify(view).showBadImagePopup(8, uploadItem) } /** @@ -198,7 +203,7 @@ class UploadMediaPresenterTest { */ @Test fun handleBadImageBaseTestEmptyTitle() { - uploadMediaPresenter.handleBadImage(-3) + uploadMediaPresenter.handleBadImage(-3, uploadItem) verify(view).showMessage(ArgumentMatchers.anyInt(), ArgumentMatchers.anyInt()) } @@ -207,8 +212,8 @@ class UploadMediaPresenterTest { */ @Test fun handleBadImageBaseTestFileNameExists() { - uploadMediaPresenter.handleBadImage(-4) - verify(view).showDuplicatePicturePopup() + uploadMediaPresenter.handleBadImage(-4, uploadItem) + verify(view).showDuplicatePicturePopup(uploadItem) } @@ -222,13 +227,4 @@ class UploadMediaPresenterTest { verify(view).showSimilarImageFragment("original", "possible", similar) } - /** - * Test set upload item - */ - @Test - fun setUploadItemTest() { - uploadMediaPresenter.setUploadItem(0, uploadItem) - verify(repository).updateUploadItem(0, uploadItem) - } - }