diff --git a/app/src/main/java/fr/free/nrw/commons/nearby/NearbyController.java b/app/src/main/java/fr/free/nrw/commons/nearby/NearbyController.java index 35280cd1e..afec72ee6 100644 --- a/app/src/main/java/fr/free/nrw/commons/nearby/NearbyController.java +++ b/app/src/main/java/fr/free/nrw/commons/nearby/NearbyController.java @@ -20,8 +20,8 @@ import timber.log.Timber; public class NearbyController extends MapController { - private static final int MAX_RESULTS = 1000; private final NearbyPlaces nearbyPlaces; + public static final int MAX_RESULTS = 1000; public static double currentLocationSearchRadius = 10.0; //in kilometers public static LatLng currentLocation; // Users latest fetched location public static LatLng latestSearchLocation; // Can be current and camera target on search this area button is used diff --git a/app/src/main/java/fr/free/nrw/commons/nearby/contract/NearbyParentFragmentContract.java b/app/src/main/java/fr/free/nrw/commons/nearby/contract/NearbyParentFragmentContract.java index bcf8d8421..9cc06fe8e 100644 --- a/app/src/main/java/fr/free/nrw/commons/nearby/contract/NearbyParentFragmentContract.java +++ b/app/src/main/java/fr/free/nrw/commons/nearby/contract/NearbyParentFragmentContract.java @@ -2,6 +2,7 @@ package fr.free.nrw.commons.nearby.contract; import android.content.Context; import androidx.annotation.Nullable; +import androidx.lifecycle.LifecycleCoroutineScope; import fr.free.nrw.commons.BaseMarker; import fr.free.nrw.commons.kvstore.JsonKvStore; import fr.free.nrw.commons.location.LatLng; diff --git a/app/src/main/java/fr/free/nrw/commons/nearby/fragments/NearbyParentFragment.java b/app/src/main/java/fr/free/nrw/commons/nearby/fragments/NearbyParentFragment.java index ebacbad34..b3de36c38 100644 --- a/app/src/main/java/fr/free/nrw/commons/nearby/fragments/NearbyParentFragment.java +++ b/app/src/main/java/fr/free/nrw/commons/nearby/fragments/NearbyParentFragment.java @@ -56,6 +56,8 @@ import androidx.appcompat.app.AlertDialog.Builder; import androidx.constraintlayout.widget.ConstraintLayout; import androidx.core.content.ContextCompat; import androidx.core.content.FileProvider; +import androidx.lifecycle.LifecycleOwner; +import androidx.lifecycle.LifecycleOwnerKt; import androidx.recyclerview.widget.DividerItemDecoration; import androidx.recyclerview.widget.GridLayoutManager; import androidx.recyclerview.widget.LinearLayoutManager; @@ -156,7 +158,7 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment FragmentNearbyParentBinding binding; - private JustExperimenting justExperimenting; +// private JustExperimenting justExperimenting; public final MapEventsOverlay mapEventsOverlay = new MapEventsOverlay(new MapEventsReceiver() { @Override @@ -351,7 +353,7 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment binding = FragmentNearbyParentBinding.inflate(inflater, container, false); view = binding.getRoot(); - justExperimenting = new JustExperimenting(this); +// justExperimenting = new JustExperimenting(this); initNetworkBroadCastReceiver(); presenter = new NearbyParentFragmentPresenter(bookmarkLocationDao); @@ -1361,7 +1363,7 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment ? getTextBetweenParentheses( updatedPlace.getLongDescription()) : updatedPlace.getLongDescription()); marker.showInfoWindow(); - justExperimenting.handlePlaceClicked(updatedPlace); +// justExperimenting.handlePlaceClicked(updatedPlace); savePlaceToDatabase(place); Drawable icon = ContextCompat.getDrawable(getContext(), getIconFor(updatedPlace, isBookMarked)); @@ -1502,8 +1504,8 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment */ private void updateMapMarkers(final List nearbyPlaces, final LatLng curLatLng, final boolean shouldUpdateSelectedMarker) { - presenter.updateMapMarkers(nearbyPlaces, curLatLng, shouldUpdateSelectedMarker); - setFilterState(); + presenter.updateMapMarkers(nearbyPlaces, curLatLng, + LifecycleOwnerKt.getLifecycleScope(getViewLifecycleOwner())); } @@ -1766,8 +1768,10 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment final boolean displayExists = false; final boolean displayNeedsPhoto= false; final boolean displayWlm = false; - // Remove the previous markers before updating them -// clearAllMarkers(); // moved + if (selectedLabels == null || selectedLabels.size() == 0) { + replaceMarkerOverlays(NearbyController.markerLabelList); + return; + } ArrayList es = new ArrayList<>(); for (final MarkerPlaceGroup markerPlaceGroup : NearbyController.markerLabelList) { final Place place = markerPlaceGroup.getPlace(); @@ -1810,26 +1814,10 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment if (shouldUpdateMarker) { MarkerPlaceGroup e = new MarkerPlaceGroup(markerPlaceGroup.getIsBookmarked(), place); -// updateMarker(markerPlaceGroup.getIsBookmarked(), place, -// NearbyController.currentLocation); es.add(e); } } - justExperimenting.loadNewMarkers(es); -// Timber.tag("temptagtwo").e("iscowa: "+(binding.map.getOverlays() instanceof CopyOnWriteArrayList)); -// Timber.tag("temptagtwo").e("additional debug info: "+(Looper.myLooper() == Looper.getMainLooper())); - - //TODO experimentation touncomment -// if (selectedLabels == null || selectedLabels.size() == 0) { -// ArrayList markerArrayList = new ArrayList<>(); -// for (final MarkerPlaceGroup markerPlaceGroup : NearbyController.markerLabelList) { -// BaseMarker nearbyBaseMarker = new BaseMarker(); -// nearbyBaseMarker.setPlace(markerPlaceGroup.getPlace()); -// markerArrayList.add(nearbyBaseMarker); -// } -// addMarkersToMap(markerArrayList); -// } - + replaceMarkerOverlays(es); } @Override @@ -1955,9 +1943,14 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment return marker; } - public void replaceMarkerOverlays(final List ms) { + public void replaceMarkerOverlays(final List markerPlaceGroups) { + ArrayList newMarkers = new ArrayList<>(markerPlaceGroups.size()); + for (MarkerPlaceGroup markerPlaceGroup : markerPlaceGroups) { + newMarkers.add( + convertToMarker(markerPlaceGroup.getPlace(), markerPlaceGroup.getIsBookmarked())); + } clearAllMarkers(); - binding.map.getOverlays().addAll(ms); + binding.map.getOverlays().addAll(newMarkers); } /** diff --git a/app/src/main/java/fr/free/nrw/commons/nearby/helper/JustExperimenting.kt b/app/src/main/java/fr/free/nrw/commons/nearby/helper/JustExperimenting.kt index a143385e9..2199cf7dc 100644 --- a/app/src/main/java/fr/free/nrw/commons/nearby/helper/JustExperimenting.kt +++ b/app/src/main/java/fr/free/nrw/commons/nearby/helper/JustExperimenting.kt @@ -55,7 +55,7 @@ class JustExperimenting(frag: NearbyParentFragment) { delay(skipDelayMs) } skippedCount = 0 - frag.replaceMarkerOverlays(markers) +// frag.replaceMarkerOverlays(markers) } } } diff --git a/app/src/main/java/fr/free/nrw/commons/nearby/presenter/NearbyParentFragmentPresenter.kt b/app/src/main/java/fr/free/nrw/commons/nearby/presenter/NearbyParentFragmentPresenter.kt index c23401026..047a78e25 100644 --- a/app/src/main/java/fr/free/nrw/commons/nearby/presenter/NearbyParentFragmentPresenter.kt +++ b/app/src/main/java/fr/free/nrw/commons/nearby/presenter/NearbyParentFragmentPresenter.kt @@ -3,6 +3,7 @@ package fr.free.nrw.commons.nearby.presenter import android.location.Location import android.view.View import androidx.annotation.MainThread +import androidx.lifecycle.LifecycleCoroutineScope import fr.free.nrw.commons.BaseMarker import fr.free.nrw.commons.bookmarks.locations.BookmarkLocationsDao import fr.free.nrw.commons.kvstore.JsonKvStore @@ -18,6 +19,11 @@ import fr.free.nrw.commons.nearby.contract.NearbyParentFragmentContract import fr.free.nrw.commons.utils.LocationUtils import fr.free.nrw.commons.wikidata.WikidataConstants.PLACE_OBJECT import fr.free.nrw.commons.wikidata.WikidataEditListener.WikidataP18EditListener +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Job +import kotlinx.coroutines.delay +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext import timber.log.Timber import java.lang.reflect.InvocationHandler import java.lang.reflect.Method @@ -35,6 +41,25 @@ class NearbyParentFragmentPresenter private var nearbyParentFragmentView: NearbyParentFragmentContract.View = DUMMY + private var loadPlacesDataAyncJob: Job? = null + private var schedulePlacesUpdateJob: Job? = null + private object schedulePlacesUpdateOptions { + var skippedCount = 0 + val skipLimit = 2 + val skipDelayMs = 1000L + } + suspend fun schedulePlacesUpdate(markerPlaceGroups: List) = withContext(Dispatchers.Main) { + if (markerPlaceGroups.isEmpty()) return@withContext + schedulePlacesUpdateJob?.cancel() + schedulePlacesUpdateJob = launch { + if (schedulePlacesUpdateOptions.skippedCount++ < schedulePlacesUpdateOptions.skipLimit) { + delay(schedulePlacesUpdateOptions.skipDelayMs) + } + schedulePlacesUpdateOptions.skippedCount = 0 + updatePlaceGroupsToControllerAndRender(markerPlaceGroups) + } + } + override fun attachView(view: NearbyParentFragmentContract.View) { this.nearbyParentFragmentView = view } @@ -111,7 +136,7 @@ class NearbyParentFragmentPresenter * * @param locationChangeType defines if location changed significantly or slightly */ - override fun updateMapAndList(locationChangeType: LocationChangeType) { + override fun updateMapAndList(locationChangeType: LocationChangeType?) { Timber.d("Presenter updates map and list") if (isNearbyLocked) { Timber.d("Nearby is locked, so updateMapAndList returns") @@ -172,21 +197,32 @@ class NearbyParentFragmentPresenter * @param nearbyPlaces This variable has placeToCenter list information and distances. */ fun updateMapMarkers( - nearbyPlaces: MutableList?, currentLatLng: LatLng?, - shouldTrackPosition: Boolean + nearbyPlaces: List?, currentLatLng: LatLng, + scope: LifecycleCoroutineScope? ) { + val nearbyPlaces: MutableList = + nearbyPlaces?.sortedBy { it.getDistanceInDouble(currentLatLng) } + ?.take(NearbyController.MAX_RESULTS) + ?.toMutableList() + ?: return -// nearbyParentFragmentView.clearAllMarkers(); - val baseMarkers = NearbyController - .loadAttractionsFromLocationToBaseMarkerOptions( - currentLatLng, // Curlatlang will be used to calculate distances - nearbyPlaces - ) - nearbyParentFragmentView.updateMapMarkers(baseMarkers) + loadPlacesDataAyncJob?.cancel() lockUnlockNearby(false) // So that new location updates wont come nearbyParentFragmentView.setProgressBarVisibility(false) - nearbyParentFragmentView.updateListFragment(nearbyPlaces) + updatePlaceGroupsToControllerAndRender(nearbyPlaces.map { + MarkerPlaceGroup( + // currently only the place's location is known, but bookmarks are stored by name + false, + it + ) + }) + + loadPlacesDataAyncJob = scope?.launch(Dispatchers.IO) { + withContext(Dispatchers.Main) { + + } + } } /** @@ -219,7 +255,7 @@ class NearbyParentFragmentPresenter } override fun filterByMarkerType( - selectedLabels: MutableList?, state: Int, + selectedLabels: List?, state: Int, filterForPlaceState: Boolean, filterForAllNoneType: Boolean ) { if (filterForAllNoneType) { // Means we will set labels based on states @@ -262,6 +298,14 @@ class NearbyParentFragmentPresenter } } + @MainThread + fun updatePlaceGroupsToControllerAndRender(markerPlaceGroups: List) { + NearbyController.markerLabelList.clear() + NearbyController.markerLabelList.addAll(markerPlaceGroups) + nearbyParentFragmentView.setFilterState() + nearbyParentFragmentView.updateListFragment(markerPlaceGroups.map { it.place }) + } + override fun setCheckboxUnknown() { nearbyParentFragmentView.setCheckBoxState(CheckBoxTriStates.UNKNOWN) } diff --git a/app/src/test/kotlin/fr/free/nrw/commons/nearby/NearbyParentFragmentPresenterTest.kt b/app/src/test/kotlin/fr/free/nrw/commons/nearby/NearbyParentFragmentPresenterTest.kt index d112ba507..813c3c297 100644 --- a/app/src/test/kotlin/fr/free/nrw/commons/nearby/NearbyParentFragmentPresenterTest.kt +++ b/app/src/test/kotlin/fr/free/nrw/commons/nearby/NearbyParentFragmentPresenterTest.kt @@ -457,7 +457,7 @@ class NearbyParentFragmentPresenterTest { nearbyPlacesInfo.placeList = null whenever(bookmarkLocationsDao.allBookmarksLocations).thenReturn(Collections.emptyList()) - nearbyPresenter.updateMapMarkers(nearbyPlacesInfo.placeList, latestLocation, true) + nearbyPresenter.updateMapMarkers(nearbyPlacesInfo.placeList, latestLocation, null) Mockito.verify(nearbyParentFragmentView).updateMapMarkers(any()) Mockito.verify(nearbyParentFragmentView).setProgressBarVisibility(false) Mockito.verify(nearbyParentFragmentView).updateListFragment(nearbyPlacesInfo.placeList)