From 1a4ad6976d3ef2b81149eafb0c5dd875e0998937 Mon Sep 17 00:00:00 2001 From: ShashwatKedia Date: Sun, 14 Jan 2024 08:50:38 +0530 Subject: [PATCH 1/4] Resolves issue #2239 by adding an arrow for direction --- .../contributions/ContributionsFragment.java | 29 ++++++++++++++++++- .../nearby/NearbyNotificationCardView.java | 21 ++++++++++++-- .../free/nrw/commons/utils/LengthUtils.java | 20 +++++++++++++ .../res/drawable/baseline_arrow_upward_24.xml | 5 ++++ app/src/main/res/layout/nearby_card_view.xml | 7 +++++ app/src/main/res/values/styles.xml | 2 +- .../free/nrw/commons/utils/LengthUtilsTest.kt | 27 +++++++++++++++++ 7 files changed, 106 insertions(+), 5 deletions(-) create mode 100644 app/src/main/res/drawable/baseline_arrow_upward_24.xml diff --git a/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsFragment.java b/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsFragment.java index b9cbf83f91..3001b01465 100644 --- a/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsFragment.java +++ b/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsFragment.java @@ -1,15 +1,21 @@ package fr.free.nrw.commons.contributions; +import static android.content.Context.SENSOR_SERVICE; import static fr.free.nrw.commons.contributions.Contribution.STATE_FAILED; import static fr.free.nrw.commons.contributions.Contribution.STATE_PAUSED; import static fr.free.nrw.commons.nearby.fragments.NearbyParentFragment.WLM_URL; import static fr.free.nrw.commons.profile.ProfileActivity.KEY_USERNAME; +import static fr.free.nrw.commons.utils.LengthUtils.computeBearing; import static fr.free.nrw.commons.utils.LengthUtils.formatDistanceBetween; import android.Manifest; import android.Manifest.permission; import android.annotation.SuppressLint; import android.content.Context; +import android.hardware.Sensor; +import android.hardware.SensorEvent; +import android.hardware.SensorEventListener; +import android.hardware.SensorManager; import android.os.Bundle; import android.view.LayoutInflater; import android.view.Menu; @@ -83,6 +89,7 @@ public class ContributionsFragment OnBackStackChangedListener, LocationUpdateListener, MediaDetailProvider, + SensorEventListener, ICampaignsView, ContributionsContract.View, Callback{ @Inject @Named("default_preferences") JsonKvStore store; @Inject NearbyController nearbyController; @@ -122,6 +129,10 @@ public class ContributionsFragment String userName; private boolean isUserProfile; + + private SensorManager mSensorManager; + private Sensor mLight; + private float direction; private ActivityResultLauncher nearbyLocationPermissionLauncher = registerForActivityResult(new ActivityResultContracts.RequestMultiplePermissions(), new ActivityResultCallback>() { @Override public void onActivityResult(Map result) { @@ -162,6 +173,8 @@ public void onCreate(@Nullable Bundle savedInstanceState) { userName = getArguments().getString(KEY_USERNAME); isUserProfile = true; } + mSensorManager = (SensorManager) getActivity().getSystemService(SENSOR_SERVICE); + mLight = mSensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION); } @Nullable @@ -428,6 +441,7 @@ public void onPause() { super.onPause(); locationManager.removeLocationListener(this); locationManager.unregisterLocationManager(); + mSensorManager.unregisterListener(this); } @Override @@ -464,6 +478,7 @@ public void onResume() { fetchCampaigns(); } } + mSensorManager.registerListener(this, mLight, SensorManager.SENSOR_DELAY_UI); } private void checkPermissionsAndShowNearbyCardView() { @@ -521,7 +536,8 @@ private void updateNearbyNotification(@Nullable NearbyController.NearbyPlacesInf Place closestNearbyPlace = nearbyPlacesInfo.placeList.get(0); String distance = formatDistanceBetween(curLatLng, closestNearbyPlace.location); closestNearbyPlace.setDistance(distance); - nearbyNotificationCardView.updateContent(closestNearbyPlace); + direction = (float) computeBearing(curLatLng, closestNearbyPlace.location); + nearbyNotificationCardView.updateContent(closestNearbyPlace, direction); } else { // Means that no close nearby place is found nearbyNotificationCardView.setVisibility(View.GONE); @@ -793,6 +809,17 @@ public void onClick(View view) { } }; + @Override + public void onSensorChanged(SensorEvent event) { + float rotateDegree = Math.round(event.values[0]); + nearbyNotificationCardView.rotateCompass(rotateDegree, direction); + } + + @Override + public void onAccuracyChanged(Sensor sensor, int accuracy) { + + } + } diff --git a/app/src/main/java/fr/free/nrw/commons/nearby/NearbyNotificationCardView.java b/app/src/main/java/fr/free/nrw/commons/nearby/NearbyNotificationCardView.java index 99121eec2b..3a1c14e07d 100644 --- a/app/src/main/java/fr/free/nrw/commons/nearby/NearbyNotificationCardView.java +++ b/app/src/main/java/fr/free/nrw/commons/nearby/NearbyNotificationCardView.java @@ -27,6 +27,7 @@ public class NearbyNotificationCardView extends SwipableCardView { private TextView notificationTitle; private TextView notificationDistance; private ImageView notificationIcon; + private ImageView notificationCompass; private ProgressBar progressBar; public CardViewVisibilityState cardViewVisibilityState; @@ -64,6 +65,7 @@ private void init() { notificationDistance = rootView.findViewById(R.id.nearby_distance); notificationIcon = rootView.findViewById(R.id.nearby_icon); + notificationCompass = rootView.findViewById(R.id.nearby_compass); progressBar = rootView.findViewById(R.id.progressBar); @@ -111,10 +113,11 @@ private void succeeded() { } /** - * Pass place information to views. + * Pass place information to views and set compass arrow direction * @param place Closes place where we will get information from + * @param direction Direction in which compass arrow needs to be set */ - public void updateContent(Place place) { + public void updateContent(Place place, float direction) { Timber.d("Update nearby card notification content"); this.setVisibility(VISIBLE); cardViewVisibilityState = CardViewVisibilityState.READY; @@ -129,7 +132,7 @@ public void updateContent(Place place) { notificationIcon.setVisibility(VISIBLE); notificationTitle.setText(place.name); notificationDistance.setText(place.distance); - + notificationCompass.setRotation(direction); } @Override @@ -151,6 +154,7 @@ protected void onVisibilityChanged(@NonNull View changedView, int visibility) { notificationTitle.setVisibility(VISIBLE); notificationDistance.setVisibility(VISIBLE); notificationIcon.setVisibility(VISIBLE); + notificationCompass.setVisibility(VISIBLE); break; case LOADING: permissionRequestButton.setVisibility(GONE); @@ -160,6 +164,7 @@ protected void onVisibilityChanged(@NonNull View changedView, int visibility) { notificationTitle.setVisibility(GONE); notificationDistance.setVisibility(GONE); notificationIcon.setVisibility(GONE); + notificationCompass.setVisibility(GONE); permissionRequestButton.setVisibility(GONE); break; case ASK_PERMISSION: @@ -192,4 +197,14 @@ public enum PermissionType { ENABLE_LOCATION_PERMISSION, // For only after Marshmallow NO_PERMISSION_NEEDED } + + /** + * Rotates the compass arrow in tandem with the rotation of device + * + * @param rotateDegree Degree by which device was rotated + * @param direction Direction in which arrow has to point + */ + public void rotateCompass(float rotateDegree, float direction){ + notificationCompass.setRotation(-(rotateDegree-direction)); + } } diff --git a/app/src/main/java/fr/free/nrw/commons/utils/LengthUtils.java b/app/src/main/java/fr/free/nrw/commons/utils/LengthUtils.java index cf8e807dbd..d5e1ab0f79 100644 --- a/app/src/main/java/fr/free/nrw/commons/utils/LengthUtils.java +++ b/app/src/main/java/fr/free/nrw/commons/utils/LengthUtils.java @@ -123,4 +123,24 @@ private static double hav(double x) { double sinHalf = Math.sin(x * 0.5D); return sinHalf * sinHalf; } + + /** + * Computes bearing between the two given points + * + * @see Bearing + * @param point1 Coordinates of first point + * @param point2 Coordinates of second point + * @return Bearing between the two end points in degrees + * @throws NullPointerException if one or both the points are null + */ + + public static double computeBearing(@NonNull LatLng point1, @NonNull LatLng point2) { + double diffLongitute = Math.toRadians(point2.getLongitude() - point1.getLongitude()); + double lat1 = Math.toRadians(point1.getLatitude()); + double lat2 = Math.toRadians(point2.getLatitude()); + double y = Math.sin(diffLongitute) * Math.cos(lat2); + double x = Math.cos(lat1) * Math.sin(lat2) - Math.sin(lat1) * Math.cos(lat2) * Math.cos(diffLongitute); + double bearing = Math.atan2(y, x); + return (Math.toDegrees(bearing) + 360) % 360; + } } diff --git a/app/src/main/res/drawable/baseline_arrow_upward_24.xml b/app/src/main/res/drawable/baseline_arrow_upward_24.xml new file mode 100644 index 0000000000..4b7962fdcf --- /dev/null +++ b/app/src/main/res/drawable/baseline_arrow_upward_24.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/layout/nearby_card_view.xml b/app/src/main/res/layout/nearby_card_view.xml index c88daa12f6..7161a09363 100644 --- a/app/src/main/res/layout/nearby_card_view.xml +++ b/app/src/main/res/layout/nearby_card_view.xml @@ -93,6 +93,13 @@ + + diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index 2de2481294..597aa0eec5 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -1,4 +1,4 @@ - + @color/contributionListDarkBackground diff --git a/app/src/test/kotlin/fr/free/nrw/commons/utils/LengthUtilsTest.kt b/app/src/test/kotlin/fr/free/nrw/commons/utils/LengthUtilsTest.kt index b744c6f4de..23ea105ea8 100644 --- a/app/src/test/kotlin/fr/free/nrw/commons/utils/LengthUtilsTest.kt +++ b/app/src/test/kotlin/fr/free/nrw/commons/utils/LengthUtilsTest.kt @@ -106,6 +106,29 @@ class LengthUtilsTest { assertDistanceBetween(20015115.07, pointA, pointB) } + // Test LengthUtils.formatDistanceBetween() + + @Test + fun testBearingPoleToPole() { + val pointA = LatLng(90.0, 0.0, 0f) + val pointB = LatLng(-90.0, 0.0, 0f) + assertBearing(180.00, pointA, pointB) + } + + @Test + fun testBearingRandomPoints() { + val pointA = LatLng(27.17, 78.04, 0f) + val pointB = LatLng(-40.69, 04.13, 0f) + assertBearing(227.46, pointA, pointB) + } + + @Test + fun testBearingSamePlace() { + val pointA = LatLng(90.0, 0.0, 0f) + val pointB = LatLng(90.0, 0.0, 0f) + assertBearing(0.0, pointA, pointB) + } + // Test assertion helper functions private fun assertFormattedDistanceBetween(expected: String, pointA: LatLng, pointB: LatLng) = @@ -117,4 +140,8 @@ class LengthUtilsTest { private fun assertDistanceBetween(expected: Double, pointA: LatLng, pointB: LatLng) = // Acceptable error: 1cm assertEquals(expected, LengthUtils.computeDistanceBetween(pointA, pointB), 0.01) + + private fun assertBearing(expected: Double, pointA: LatLng, pointB: LatLng) = + // Acceptable error: 1 degree + assertEquals(expected, LengthUtils.computeBearing(pointA,pointB), 1.0) } \ No newline at end of file From 90a503a20b28926a0c8d05e04f506dba9b701d02 Mon Sep 17 00:00:00 2001 From: ShashwatKedia Date: Sun, 14 Jan 2024 09:12:33 +0530 Subject: [PATCH 2/4] Removed unnecessary change in styles.xml --- app/src/main/res/values/styles.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index 597aa0eec5..2de2481294 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -1,4 +1,4 @@ - + @color/contributionListDarkBackground From 598649e8469be5c312abe804596700ea6c8410de Mon Sep 17 00:00:00 2001 From: Nicolas Raoul Date: Mon, 15 Jan 2024 13:50:48 +0900 Subject: [PATCH 3/4] spacing --- app/src/main/java/fr/free/nrw/commons/utils/LengthUtils.java | 1 - 1 file changed, 1 deletion(-) diff --git a/app/src/main/java/fr/free/nrw/commons/utils/LengthUtils.java b/app/src/main/java/fr/free/nrw/commons/utils/LengthUtils.java index d5e1ab0f79..0ca61a1d9c 100644 --- a/app/src/main/java/fr/free/nrw/commons/utils/LengthUtils.java +++ b/app/src/main/java/fr/free/nrw/commons/utils/LengthUtils.java @@ -133,7 +133,6 @@ private static double hav(double x) { * @return Bearing between the two end points in degrees * @throws NullPointerException if one or both the points are null */ - public static double computeBearing(@NonNull LatLng point1, @NonNull LatLng point2) { double diffLongitute = Math.toRadians(point2.getLongitude() - point1.getLongitude()); double lat1 = Math.toRadians(point1.getLatitude()); From 68f74c9990c43a1202188571c59f1d6fb6779c76 Mon Sep 17 00:00:00 2001 From: Nicolas Raoul Date: Mon, 15 Jan 2024 13:53:49 +0900 Subject: [PATCH 4/4] javadoc --- .../nrw/commons/contributions/ContributionsFragment.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsFragment.java b/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsFragment.java index 3001b01465..533c05c9cd 100644 --- a/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsFragment.java +++ b/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsFragment.java @@ -809,6 +809,9 @@ public void onClick(View view) { } }; + /** + * When the device rotates, rotate the Nearby banner's compass arrow in tandem. + */ @Override public void onSensorChanged(SensorEvent event) { float rotateDegree = Math.round(event.values[0]); @@ -817,9 +820,6 @@ public void onSensorChanged(SensorEvent event) { @Override public void onAccuracyChanged(Sensor sensor, int accuracy) { - + // Nothing to do. } - - } -