mirror of
https://github.com/commons-app/apps-android-commons.git
synced 2025-10-26 20:33:53 +01:00
Fixes 1848 : Option for adding location for those pictures which have no location (#4755)
* Location wizard * Location wizard * Minor fix * message changed * Test fail fixed * Test fail fixed * Test fail fixed * last location triggered * last location added * Some test added * Java docs added * More java docs added
This commit is contained in:
parent
587ff3b54f
commit
e135fea20d
9 changed files with 161 additions and 44 deletions
|
|
@ -6,6 +6,7 @@ import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconAllowOverlap
|
|||
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconIgnorePlacement;
|
||||
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconImage;
|
||||
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.visibility;
|
||||
import static fr.free.nrw.commons.upload.mediaDetails.UploadMediaDetailFragment.LAST_LOCATION;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.graphics.BitmapFactory;
|
||||
|
|
@ -49,13 +50,17 @@ import com.mapbox.mapboxsdk.style.layers.SymbolLayer;
|
|||
import com.mapbox.mapboxsdk.style.sources.GeoJsonSource;
|
||||
import fr.free.nrw.commons.R;
|
||||
import fr.free.nrw.commons.Utils;
|
||||
import fr.free.nrw.commons.kvstore.JsonKvStore;
|
||||
import fr.free.nrw.commons.theme.BaseActivity;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import timber.log.Timber;
|
||||
|
||||
/**
|
||||
* Helps to pick location and return the result with an intent
|
||||
*/
|
||||
public class LocationPickerActivity extends AppCompatActivity implements OnMapReadyCallback,
|
||||
public class LocationPickerActivity extends BaseActivity implements OnMapReadyCallback,
|
||||
OnCameraMoveStartedListener, OnCameraIdleListener, Observer<CameraPosition> {
|
||||
|
||||
/**
|
||||
|
|
@ -114,6 +119,13 @@ public class LocationPickerActivity extends AppCompatActivity implements OnMapRe
|
|||
* smallToolbarText : textView of shadow
|
||||
*/
|
||||
private TextView smallToolbarText;
|
||||
/**
|
||||
* applicationKvStore : for storing values
|
||||
*/
|
||||
@Inject
|
||||
@Named("default_preferences")
|
||||
public
|
||||
JsonKvStore applicationKvStore;
|
||||
|
||||
@Override
|
||||
protected void onCreate(@Nullable final Bundle savedInstanceState) {
|
||||
|
|
@ -365,6 +377,12 @@ public class LocationPickerActivity extends AppCompatActivity implements OnMapRe
|
|||
* Return the intent with required data
|
||||
*/
|
||||
void placeSelected() {
|
||||
if (activity.equals("NoLocationUploadActivity")) {
|
||||
applicationKvStore.putString(LAST_LOCATION,
|
||||
mapboxMap.getCameraPosition().target.getLatitude()
|
||||
+ ","
|
||||
+ mapboxMap.getCameraPosition().target.getLongitude());
|
||||
}
|
||||
final Intent returningIntent = new Intent();
|
||||
returningIntent.putExtra(LocationPickerConstants.MAP_CAMERA_POSITION,
|
||||
mapboxMap.getCameraPosition());
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package fr.free.nrw.commons.di;
|
|||
import dagger.Module;
|
||||
import dagger.android.ContributesAndroidInjector;
|
||||
import fr.free.nrw.commons.AboutActivity;
|
||||
import fr.free.nrw.commons.LocationPicker.LocationPickerActivity;
|
||||
import fr.free.nrw.commons.WelcomeActivity;
|
||||
import fr.free.nrw.commons.auth.LoginActivity;
|
||||
import fr.free.nrw.commons.auth.SignupActivity;
|
||||
|
|
@ -44,6 +45,9 @@ public abstract class ActivityBuilderModule {
|
|||
@ContributesAndroidInjector
|
||||
abstract AboutActivity bindAboutActivity();
|
||||
|
||||
@ContributesAndroidInjector
|
||||
abstract LocationPickerActivity bindLocationPickerActivity();
|
||||
|
||||
@ContributesAndroidInjector
|
||||
abstract SignupActivity bindSignupActivity();
|
||||
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ import fr.free.nrw.commons.utils.ImageUtils;
|
|||
import fr.free.nrw.commons.utils.ViewUtil;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
|
@ -53,6 +54,12 @@ public class UploadMediaDetailFragment extends UploadBaseFragment implements
|
|||
UploadMediaDetailsContract.View, UploadMediaDetailAdapter.EventListener {
|
||||
|
||||
private static final int REQUEST_CODE = 1211;
|
||||
/**
|
||||
* A key for applicationKvStore.
|
||||
* By this key we can retrieve the location of last UploadItem ex. 12.3433,54.78897
|
||||
* from applicationKvStore.
|
||||
*/
|
||||
public static final String LAST_LOCATION = "last_location_while_uploading";
|
||||
@BindView(R.id.tv_title)
|
||||
TextView tvTitle;
|
||||
@BindView(R.id.ib_map)
|
||||
|
|
@ -397,10 +404,6 @@ public class UploadMediaDetailFragment extends UploadBaseFragment implements
|
|||
() -> {}, true);
|
||||
}
|
||||
|
||||
@Override public void showMapWithImageCoordinates(boolean shouldShow) {
|
||||
ibMap.setVisibility(shouldShow ? View.VISIBLE : View.GONE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showExternalMap(final UploadItem uploadItem) {
|
||||
goToLocationPickerActivity(uploadItem);
|
||||
|
|
@ -414,14 +417,36 @@ public class UploadMediaDetailFragment extends UploadBaseFragment implements
|
|||
private void goToLocationPickerActivity(final UploadItem uploadItem) {
|
||||
|
||||
editableUploadItem = uploadItem;
|
||||
startActivityForResult(new LocationPicker.IntentBuilder()
|
||||
.defaultLocation(new CameraPosition.Builder()
|
||||
.target(new com.mapbox.mapboxsdk.geometry.LatLng(uploadItem.getGpsCoords()
|
||||
.getDecLatitude(),
|
||||
uploadItem.getGpsCoords().getDecLongitude()))
|
||||
.zoom(16).build())
|
||||
.activityKey("UploadActivity")
|
||||
.build(getActivity()), REQUEST_CODE);
|
||||
double defaultLatitude = 37.773972;
|
||||
double defaultLongitude = -122.431297;
|
||||
|
||||
if (uploadItem.getGpsCoords()
|
||||
.getDecLatitude() != 0.0 && uploadItem.getGpsCoords().getDecLongitude() != 0.0) {
|
||||
defaultLatitude = uploadItem.getGpsCoords()
|
||||
.getDecLatitude();
|
||||
defaultLongitude = uploadItem.getGpsCoords().getDecLongitude();
|
||||
startActivityForResult(new LocationPicker.IntentBuilder()
|
||||
.defaultLocation(new CameraPosition.Builder()
|
||||
.target(
|
||||
new com.mapbox.mapboxsdk.geometry.LatLng(defaultLatitude, defaultLongitude))
|
||||
.zoom(16).build())
|
||||
.activityKey("UploadActivity")
|
||||
.build(getActivity()), REQUEST_CODE);
|
||||
} else {
|
||||
if (defaultKvStore.getString(LAST_LOCATION) != null) {
|
||||
final String[] locationLatLng
|
||||
= defaultKvStore.getString(LAST_LOCATION).split(",");
|
||||
defaultLatitude = Double.parseDouble(locationLatLng[0]);
|
||||
defaultLongitude = Double.parseDouble(locationLatLng[1]);
|
||||
}
|
||||
startActivityForResult(new LocationPicker.IntentBuilder()
|
||||
.defaultLocation(new CameraPosition.Builder()
|
||||
.target(
|
||||
new com.mapbox.mapboxsdk.geometry.LatLng(defaultLatitude, defaultLongitude))
|
||||
.zoom(16).build())
|
||||
.activityKey("NoLocationUploadActivity")
|
||||
.build(getActivity()), REQUEST_CODE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -470,6 +495,22 @@ public class UploadMediaDetailFragment extends UploadBaseFragment implements
|
|||
uploadMediaDetailAdapter.setItems(uploadMediaDetails);
|
||||
}
|
||||
|
||||
/**
|
||||
* Showing dialog for adding location
|
||||
*
|
||||
* @param onSkipClicked proceed for verifying image quality
|
||||
*/
|
||||
@Override
|
||||
public void displayAddLocationDialog(final Runnable onSkipClicked) {
|
||||
DialogUtil.showAlertDialog(Objects.requireNonNull(getActivity()),
|
||||
getString(R.string.no_location_found_title),
|
||||
getString(R.string.no_location_found_message),
|
||||
getString(R.string.add_location),
|
||||
getString(R.string.skip_login),
|
||||
this::onIbMapClicked,
|
||||
onSkipClicked);
|
||||
}
|
||||
|
||||
private void deleteThisPicture() {
|
||||
callback.deletePictureAtIndex(callback.getIndexInViewFlipper(this));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,11 +34,11 @@ public interface UploadMediaDetailsContract {
|
|||
|
||||
void showConnectionErrorPopup();
|
||||
|
||||
void showMapWithImageCoordinates(boolean shouldShow);
|
||||
|
||||
void showExternalMap(UploadItem uploadItem);
|
||||
|
||||
void updateMediaDetails(List<UploadMediaDetail> uploadMediaDetails);
|
||||
|
||||
void displayAddLocationDialog(Runnable runnable);
|
||||
}
|
||||
|
||||
interface UserActionListener extends BasePresenter<View> {
|
||||
|
|
|
|||
|
|
@ -114,7 +114,6 @@ public class UploadMediaPresenter implements UserActionListener, SimilarImageInt
|
|||
final ImageCoordinates gpsCoords = uploadItem.getGpsCoords();
|
||||
final boolean hasImageCoordinates =
|
||||
gpsCoords != null && gpsCoords.getImageCoordsExists();
|
||||
view.showMapWithImageCoordinates(hasImageCoordinates);
|
||||
view.showProgress(false);
|
||||
if (hasImageCoordinates && place == null) {
|
||||
checkNearbyPlaces(uploadItem);
|
||||
|
|
@ -169,28 +168,54 @@ public class UploadMediaPresenter implements UserActionListener, SimilarImageInt
|
|||
*/
|
||||
@Override
|
||||
public void verifyImageQuality(int uploadItemIndex) {
|
||||
view.showProgress(true);
|
||||
|
||||
final UploadItem uploadItem = repository.getUploads().get(uploadItemIndex);
|
||||
compositeDisposable.add(
|
||||
repository
|
||||
.getImageQuality(uploadItem)
|
||||
.observeOn(mainThreadScheduler)
|
||||
.subscribe(imageResult -> {
|
||||
view.showProgress(false);
|
||||
handleImageResult(imageResult, uploadItem);
|
||||
},
|
||||
throwable -> {
|
||||
view.showProgress(false);
|
||||
if (throwable instanceof UnknownHostException) {
|
||||
|
||||
if (uploadItem.getGpsCoords().getDecimalCoords() == null) {
|
||||
final Runnable onSkipClicked = () -> {
|
||||
view.showProgress(true);
|
||||
compositeDisposable.add(
|
||||
repository
|
||||
.getImageQuality(uploadItem)
|
||||
.observeOn(mainThreadScheduler)
|
||||
.subscribe(imageResult -> {
|
||||
view.showProgress(false);
|
||||
handleImageResult(imageResult, uploadItem);
|
||||
},
|
||||
throwable -> {
|
||||
view.showProgress(false);
|
||||
if (throwable instanceof UnknownHostException) {
|
||||
view.showConnectionErrorPopup();
|
||||
} else {
|
||||
view.showMessage("" + throwable.getLocalizedMessage(),
|
||||
R.color.color_error);
|
||||
}
|
||||
Timber.e(throwable, "Error occurred while handling image");
|
||||
})
|
||||
);
|
||||
};
|
||||
view.displayAddLocationDialog(onSkipClicked);
|
||||
} else {
|
||||
view.showProgress(true);
|
||||
compositeDisposable.add(
|
||||
repository
|
||||
.getImageQuality(uploadItem)
|
||||
.observeOn(mainThreadScheduler)
|
||||
.subscribe(imageResult -> {
|
||||
view.showProgress(false);
|
||||
handleImageResult(imageResult, uploadItem);
|
||||
},
|
||||
throwable -> {
|
||||
view.showProgress(false);
|
||||
if (throwable instanceof UnknownHostException) {
|
||||
view.showConnectionErrorPopup();
|
||||
} else {
|
||||
} else {
|
||||
view.showMessage("" + throwable.getLocalizedMessage(),
|
||||
R.color.color_error);
|
||||
}
|
||||
Timber.e(throwable, "Error occurred while handling image");
|
||||
})
|
||||
);
|
||||
}
|
||||
Timber.e(throwable, "Error occurred while handling image");
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@
|
|||
android:layout_marginEnd="@dimen/standard_gap"
|
||||
android:layout_marginRight="@dimen/standard_gap"
|
||||
android:layout_toLeftOf="@id/ib_expand_collapse"
|
||||
android:visibility="gone"
|
||||
android:visibility="visible"
|
||||
app:srcCompat="@drawable/ic_map_white_24dp"
|
||||
tools:visibility="visible" />
|
||||
|
||||
|
|
|
|||
|
|
@ -682,5 +682,8 @@ Upload your first media by tapping on the add button.</string>
|
|||
<string name="apply">Apply</string>
|
||||
<string name="reset">Reset</string>
|
||||
<string name="location_message">Location data helps Wiki editors find your picture, making it much more useful.\nYour recent uploads have no location.\nWe suggest you turn on location in your camera app\'s settings.\nThank you for uploading!</string>
|
||||
<string name="no_location_found_title">No location found</string>
|
||||
<string name="no_location_found_message">How about adding the place where this image was taken?\nLocation data helps Wiki editors find your picture, making it much more useful.\nThank you!</string>
|
||||
<string name="add_location">Add location</string>
|
||||
<string name="feedback_sharing_data_alert">Please remove from this email any information that you are not comfortable sharing publicly. Also, please be aware that your email address with which you are posting, and the associated name and profile picture, will be visible publicly.</string>
|
||||
</resources>
|
||||
|
|
|
|||
|
|
@ -44,6 +44,9 @@ class UploadMediaPresenterTest {
|
|||
@Mock
|
||||
private lateinit var uploadItem: UploadItem
|
||||
|
||||
@Mock
|
||||
private lateinit var imageCoordinates: ImageCoordinates
|
||||
|
||||
@Mock
|
||||
private lateinit var uploadMediaDetails: List<UploadMediaDetail>
|
||||
|
||||
|
|
@ -93,20 +96,41 @@ class UploadMediaPresenterTest {
|
|||
}
|
||||
|
||||
/**
|
||||
* unit test for method UploadMediaPresenter.verifyImageQuality
|
||||
* unit test for method UploadMediaPresenter.verifyImageQuality (For else case)
|
||||
*/
|
||||
@Test
|
||||
fun verifyImageQualityTest() {
|
||||
whenever(repository.uploads).thenReturn(listOf(uploadItem))
|
||||
whenever(repository.getImageQuality(uploadItem))
|
||||
.thenReturn(testSingleImageResult)
|
||||
whenever(uploadItem.imageQuality).thenReturn(ArgumentMatchers.anyInt())
|
||||
whenever(uploadItem.imageQuality).thenReturn(0)
|
||||
whenever(uploadItem.gpsCoords)
|
||||
.thenReturn(imageCoordinates)
|
||||
whenever(uploadItem.gpsCoords.decimalCoords)
|
||||
.thenReturn("imageCoordinates")
|
||||
uploadMediaPresenter.verifyImageQuality(0)
|
||||
verify(view).showProgress(true)
|
||||
testScheduler.triggerActions()
|
||||
verify(view).showProgress(false)
|
||||
}
|
||||
|
||||
/**
|
||||
* unit test for method UploadMediaPresenter.verifyImageQuality (For if case)
|
||||
*/
|
||||
@Test
|
||||
fun `verify ImageQuality Test while coordinates equals to null`() {
|
||||
whenever(repository.uploads).thenReturn(listOf(uploadItem))
|
||||
whenever(repository.getImageQuality(uploadItem))
|
||||
.thenReturn(testSingleImageResult)
|
||||
whenever(uploadItem.imageQuality).thenReturn(0)
|
||||
whenever(uploadItem.gpsCoords)
|
||||
.thenReturn(imageCoordinates)
|
||||
whenever(uploadItem.gpsCoords.decimalCoords)
|
||||
.thenReturn(null)
|
||||
uploadMediaPresenter.verifyImageQuality(0)
|
||||
testScheduler.triggerActions()
|
||||
}
|
||||
|
||||
/**
|
||||
* unit test for method UploadMediaPresenter.handleImageResult
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -58,6 +58,7 @@ class UploadMediaDetailFragmentUnitTest {
|
|||
private lateinit var context: Context
|
||||
private lateinit var layoutInflater: LayoutInflater
|
||||
private lateinit var view: View
|
||||
private lateinit var runnable: Runnable
|
||||
|
||||
private lateinit var tvTitle: TextView
|
||||
private lateinit var tooltip: ImageView
|
||||
|
|
@ -338,13 +339,6 @@ class UploadMediaDetailFragmentUnitTest {
|
|||
fragment.showConnectionErrorPopup()
|
||||
}
|
||||
|
||||
@Test
|
||||
@Throws(Exception::class)
|
||||
fun testShowMapWithImageCoordinates() {
|
||||
Shadows.shadowOf(Looper.getMainLooper()).idle()
|
||||
fragment.showMapWithImageCoordinates(true)
|
||||
}
|
||||
|
||||
@Test
|
||||
@Throws(Exception::class)
|
||||
fun testShowExternalMap() {
|
||||
|
|
@ -429,4 +423,12 @@ class UploadMediaDetailFragmentUnitTest {
|
|||
fragment.onButtonCopyTitleDescToSubsequentMedia()
|
||||
}
|
||||
|
||||
@Test
|
||||
@Throws(Exception::class)
|
||||
fun testDisplayAddLocationDialog() {
|
||||
Shadows.shadowOf(Looper.getMainLooper()).idle()
|
||||
runnable = Runnable { }
|
||||
fragment.displayAddLocationDialog(runnable)
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue