Convert the map presenter to kotlin

This commit is contained in:
Paul Hawke 2025-07-31 08:49:07 -05:00
parent ed6576b385
commit cd1aaa82e0
3 changed files with 224 additions and 237 deletions

View file

@ -33,7 +33,7 @@ class ExploreMapContract {
} }
interface UserActions { interface UserActions {
fun updateMap(locationChangeType: LocationChangeType?) fun updateMap(locationChangeType: LocationChangeType)
fun lockUnlockNearby(isNearbyLocked: Boolean) fun lockUnlockNearby(isNearbyLocked: Boolean)
fun attachView(view: View?) fun attachView(view: View?)
fun detachView() fun detachView()

View file

@ -1,236 +0,0 @@
package fr.free.nrw.commons.explore.map;
import static fr.free.nrw.commons.location.LocationServiceManager.LocationChangeType.LOCATION_SIGNIFICANTLY_CHANGED;
import static fr.free.nrw.commons.location.LocationServiceManager.LocationChangeType.SEARCH_CUSTOM_AREA;
import android.location.Location;
import android.view.View;
import fr.free.nrw.commons.BaseMarker;
import fr.free.nrw.commons.MapController;
import fr.free.nrw.commons.MapController.ExplorePlacesInfo;
import fr.free.nrw.commons.bookmarks.locations.BookmarkLocationsDao;
import fr.free.nrw.commons.explore.map.ExploreMapController.NearbyBaseMarkerThumbCallback;
import fr.free.nrw.commons.kvstore.JsonKvStore;
import fr.free.nrw.commons.location.LatLng;
import fr.free.nrw.commons.location.LocationServiceManager.LocationChangeType;
import fr.free.nrw.commons.nearby.Place;
import io.reactivex.Observable;
import java.lang.reflect.Proxy;
import java.util.List;
import timber.log.Timber;
public class ExploreMapPresenter
implements ExploreMapContract.UserActions,
NearbyBaseMarkerThumbCallback {
BookmarkLocationsDao bookmarkLocationDao;
private boolean isNearbyLocked;
private LatLng currentLatLng;
private ExploreMapController exploreMapController;
private static final ExploreMapContract.View DUMMY = (ExploreMapContract.View) Proxy
.newProxyInstance(
ExploreMapContract.View.class.getClassLoader(),
new Class[]{ExploreMapContract.View.class}, (proxy, method, args) -> {
if (method.getName().equals("onMyEvent")) {
return null;
} else if (String.class == method.getReturnType()) {
return "";
} else if (Integer.class == method.getReturnType()) {
return Integer.valueOf(0);
} else if (int.class == method.getReturnType()) {
return 0;
} else if (Boolean.class == method.getReturnType()) {
return Boolean.FALSE;
} else if (boolean.class == method.getReturnType()) {
return false;
} else {
return null;
}
}
);
private ExploreMapContract.View exploreMapFragmentView = DUMMY;
public ExploreMapPresenter(BookmarkLocationsDao bookmarkLocationDao) {
this.bookmarkLocationDao = bookmarkLocationDao;
}
@Override
public void updateMap(LocationChangeType locationChangeType) {
Timber.d("Presenter updates map and list" + locationChangeType.toString());
if (isNearbyLocked) {
Timber.d("Nearby is locked, so updateMapAndList returns");
return;
}
if (!exploreMapFragmentView.isNetworkConnectionEstablished()) {
Timber.d("Network connection is not established");
return;
}
/**
* Significant changed - Markers and current location will be updated together
* Slightly changed - Only current position marker will be updated
*/
if (locationChangeType.equals(LOCATION_SIGNIFICANTLY_CHANGED)) {
Timber.d("LOCATION_SIGNIFICANTLY_CHANGED");
LatLng populateLatLng = exploreMapFragmentView.getMapCenter();
//If "Show in Explore" was selected in Nearby, use the previous LatLng
if (exploreMapFragmentView instanceof ExploreMapFragment) {
ExploreMapFragment exploreMapFragment = (ExploreMapFragment)exploreMapFragmentView;
if (exploreMapFragment.recentlyCameFromNearbyMap()) {
//Ensure this LatLng will not be used again if user searches their GPS location
exploreMapFragment.setRecentlyCameFromNearbyMap(false);
populateLatLng = exploreMapFragment.getPreviousLatLng();
}
}
lockUnlockNearby(true);
exploreMapFragmentView.setProgressBarVisibility(true);
exploreMapFragmentView.populatePlaces(populateLatLng);
} else if (locationChangeType.equals(SEARCH_CUSTOM_AREA)) {
Timber.d("SEARCH_CUSTOM_AREA");
lockUnlockNearby(true);
exploreMapFragmentView.setProgressBarVisibility(true);
exploreMapFragmentView.populatePlaces(exploreMapFragmentView.getMapFocus());
} else { // Means location changed slightly, ie user is walking or driving.
Timber.d("Means location changed slightly");
}
}
/**
* Nearby updates takes time, since they are network operations. During update time, we don't
* want to get any other calls from user. So locking nearby.
*
* @param isNearbyLocked true means lock, false means unlock
*/
@Override
public void lockUnlockNearby(boolean isNearbyLocked) {
this.isNearbyLocked = isNearbyLocked;
if (isNearbyLocked) {
exploreMapFragmentView.disableFABRecenter();
} else {
exploreMapFragmentView.enableFABRecenter();
}
}
@Override
public void attachView(ExploreMapContract.View view) {
exploreMapFragmentView = view;
}
@Override
public void detachView() {
exploreMapFragmentView = DUMMY;
}
/**
* Sets click listener of FAB
*/
@Override
public void setActionListeners(JsonKvStore applicationKvStore) {
exploreMapFragmentView.setFABRecenterAction(v -> {
exploreMapFragmentView.recenterMap(currentLatLng);
});
}
@Override
public boolean backButtonClicked() {
return exploreMapFragmentView.backButtonClicked();
}
public void onMapReady(ExploreMapController exploreMapController) {
this.exploreMapController = exploreMapController;
if (null != exploreMapFragmentView) {
exploreMapFragmentView.addSearchThisAreaButtonAction();
initializeMapOperations();
}
}
public void initializeMapOperations() {
lockUnlockNearby(false);
updateMap(LOCATION_SIGNIFICANTLY_CHANGED);
}
public Observable<ExplorePlacesInfo> loadAttractionsFromLocation(LatLng currentLatLng,
LatLng searchLatLng, boolean checkingAroundCurrent) {
return Observable
.fromCallable(() -> exploreMapController
.loadAttractionsFromLocation(currentLatLng, searchLatLng, checkingAroundCurrent));
}
/**
* Populates places for custom location, should be used for finding nearby places around a
* location where you are not at.
*
* @param explorePlacesInfo This variable has placeToCenter list information and distances.
*/
public void updateMapMarkers(
MapController.ExplorePlacesInfo explorePlacesInfo) {
if (explorePlacesInfo.mediaList != null) {
prepareNearbyBaseMarkers(explorePlacesInfo);
} else {
lockUnlockNearby(false); // So that new location updates wont come
exploreMapFragmentView.setProgressBarVisibility(false);
}
}
void prepareNearbyBaseMarkers(MapController.ExplorePlacesInfo explorePlacesInfo) {
ExploreMapController.Companion.loadAttractionsFromLocationToBaseMarkerOptions(explorePlacesInfo.currentLatLng,
// Curlatlang will be used to calculate distances
(List<Place>) explorePlacesInfo.explorePlaceList,
exploreMapFragmentView.getContext(),
this,
explorePlacesInfo);
}
@Override
public void onNearbyBaseMarkerThumbsReady(List<BaseMarker> baseMarkers,
ExplorePlacesInfo explorePlacesInfo) {
if (null != exploreMapFragmentView) {
exploreMapFragmentView.addMarkersToMap(baseMarkers);
lockUnlockNearby(false); // So that new location updates wont come
exploreMapFragmentView.setProgressBarVisibility(false);
}
}
public View.OnClickListener onSearchThisAreaClicked() {
return v -> {
// Lock map operations during search this area operation
exploreMapFragmentView.setSearchThisAreaButtonVisibility(false);
if (searchCloseToCurrentLocation()) {
updateMap(LOCATION_SIGNIFICANTLY_CHANGED);
} else {
updateMap(SEARCH_CUSTOM_AREA);
}
};
}
/**
* Returns true if search this area button is used around our current location, so that we can
* continue following our current location again
*
* @return Returns true if search this area button is used around our current location
*/
public boolean searchCloseToCurrentLocation() {
if (null == exploreMapFragmentView.getLastMapFocus()) {
return true;
}
Location mylocation = new Location("");
Location dest_location = new Location("");
dest_location.setLatitude(exploreMapFragmentView.getMapFocus().getLatitude());
dest_location.setLongitude(exploreMapFragmentView.getMapFocus().getLongitude());
mylocation.setLatitude(exploreMapFragmentView.getLastMapFocus().getLatitude());
mylocation.setLongitude(exploreMapFragmentView.getLastMapFocus().getLongitude());
Float distance = mylocation.distanceTo(dest_location);
return !(distance > 2000.0 * 3 / 4);
}
}

View file

@ -0,0 +1,223 @@
package fr.free.nrw.commons.explore.map
import android.location.Location
import android.view.View
import fr.free.nrw.commons.BaseMarker
import fr.free.nrw.commons.MapController.ExplorePlacesInfo
import fr.free.nrw.commons.bookmarks.locations.BookmarkLocationsDao
import fr.free.nrw.commons.explore.map.ExploreMapController.Companion.loadAttractionsFromLocationToBaseMarkerOptions
import fr.free.nrw.commons.explore.map.ExploreMapController.NearbyBaseMarkerThumbCallback
import fr.free.nrw.commons.kvstore.JsonKvStore
import fr.free.nrw.commons.location.LatLng
import fr.free.nrw.commons.location.LocationServiceManager.LocationChangeType
import fr.free.nrw.commons.nearby.Place
import io.reactivex.Observable
import timber.log.Timber
import java.lang.reflect.Method
import java.lang.reflect.Proxy
import java.util.concurrent.Callable
class ExploreMapPresenter(
var bookmarkLocationDao: BookmarkLocationsDao
) : ExploreMapContract.UserActions, NearbyBaseMarkerThumbCallback {
private var isNearbyLocked = false
private val currentLatLng: LatLng? = null
private var exploreMapController: ExploreMapController? = null
private var exploreMapFragmentView: ExploreMapContract.View? = DUMMY
override fun updateMap(locationChangeType: LocationChangeType) {
Timber.d("Presenter updates map and list$locationChangeType")
if (isNearbyLocked) {
Timber.d("Nearby is locked, so updateMapAndList returns")
return
}
if (!exploreMapFragmentView!!.isNetworkConnectionEstablished()) {
Timber.d("Network connection is not established")
return
}
/**
* Significant changed - Markers and current location will be updated together
* Slightly changed - Only current position marker will be updated
*/
if (locationChangeType == LocationChangeType.LOCATION_SIGNIFICANTLY_CHANGED) {
Timber.d("LOCATION_SIGNIFICANTLY_CHANGED")
var populateLatLng = exploreMapFragmentView!!.getMapCenter()
//If "Show in Explore" was selected in Nearby, use the previous LatLng
if (exploreMapFragmentView is ExploreMapFragment) {
val exploreMapFragment = exploreMapFragmentView as ExploreMapFragment
if (exploreMapFragment.recentlyCameFromNearbyMap()) {
//Ensure this LatLng will not be used again if user searches their GPS location
exploreMapFragment.setRecentlyCameFromNearbyMap(false)
populateLatLng = exploreMapFragment.previousLatLng
}
}
lockUnlockNearby(true)
exploreMapFragmentView!!.setProgressBarVisibility(true)
exploreMapFragmentView!!.populatePlaces(populateLatLng)
} else if (locationChangeType == LocationChangeType.SEARCH_CUSTOM_AREA) {
Timber.d("SEARCH_CUSTOM_AREA")
lockUnlockNearby(true)
exploreMapFragmentView!!.setProgressBarVisibility(true)
exploreMapFragmentView!!.populatePlaces(exploreMapFragmentView!!.getMapFocus())
} else { // Means location changed slightly, ie user is walking or driving.
Timber.d("Means location changed slightly")
}
}
/**
* Nearby updates takes time, since they are network operations. During update time, we don't
* want to get any other calls from user. So locking nearby.
*
* @param isNearbyLocked true means lock, false means unlock
*/
override fun lockUnlockNearby(isNearbyLocked: Boolean) {
this.isNearbyLocked = isNearbyLocked
if (isNearbyLocked) {
exploreMapFragmentView!!.disableFABRecenter()
} else {
exploreMapFragmentView!!.enableFABRecenter()
}
}
override fun attachView(view: ExploreMapContract.View?) {
exploreMapFragmentView = view
}
override fun detachView() {
exploreMapFragmentView = DUMMY
}
/**
* Sets click listener of FAB
*/
override fun setActionListeners(applicationKvStore: JsonKvStore?) {
exploreMapFragmentView!!.setFABRecenterAction {
exploreMapFragmentView!!.recenterMap(currentLatLng)
}
}
override fun backButtonClicked(): Boolean =
exploreMapFragmentView!!.backButtonClicked()
fun onMapReady(exploreMapController: ExploreMapController?) {
this.exploreMapController = exploreMapController
if (null != exploreMapFragmentView) {
exploreMapFragmentView!!.addSearchThisAreaButtonAction()
initializeMapOperations()
}
}
fun initializeMapOperations() {
lockUnlockNearby(false)
updateMap(LocationChangeType.LOCATION_SIGNIFICANTLY_CHANGED)
}
fun loadAttractionsFromLocation(
currentLatLng: LatLng?,
searchLatLng: LatLng?, checkingAroundCurrent: Boolean
): Observable<ExplorePlacesInfo?> = Observable.fromCallable(Callable {
exploreMapController!!.loadAttractionsFromLocation(
currentLatLng,
searchLatLng,
checkingAroundCurrent
)
})
/**
* Populates places for custom location, should be used for finding nearby places around a
* location where you are not at.
*
* @param explorePlacesInfo This variable has placeToCenter list information and distances.
*/
fun updateMapMarkers(
explorePlacesInfo: ExplorePlacesInfo
) {
if (explorePlacesInfo.mediaList != null) {
prepareNearbyBaseMarkers(explorePlacesInfo)
} else {
lockUnlockNearby(false) // So that new location updates wont come
exploreMapFragmentView!!.setProgressBarVisibility(false)
}
}
private fun prepareNearbyBaseMarkers(explorePlacesInfo: ExplorePlacesInfo) {
loadAttractionsFromLocationToBaseMarkerOptions(
explorePlacesInfo.currentLatLng, // Curlatlang will be used to calculate distances
explorePlacesInfo.explorePlaceList,
exploreMapFragmentView!!.getContext()!!,
this,
explorePlacesInfo
)
}
override fun onNearbyBaseMarkerThumbsReady(
baseMarkers: List<BaseMarker>?,
explorePlacesInfo: ExplorePlacesInfo?
) {
if (null != exploreMapFragmentView) {
exploreMapFragmentView!!.addMarkersToMap(baseMarkers)
lockUnlockNearby(false) // So that new location updates wont come
exploreMapFragmentView!!.setProgressBarVisibility(false)
}
}
fun onSearchThisAreaClicked(): View.OnClickListener {
return View.OnClickListener {
// Lock map operations during search this area operation
exploreMapFragmentView!!.setSearchThisAreaButtonVisibility(false)
updateMap(if (searchCloseToCurrentLocation()) {
LocationChangeType.LOCATION_SIGNIFICANTLY_CHANGED
} else {
LocationChangeType.SEARCH_CUSTOM_AREA
})
}
}
/**
* Returns true if search this area button is used around our current location, so that we can
* continue following our current location again
*
* @return Returns true if search this area button is used around our current location
*/
private fun searchCloseToCurrentLocation(): Boolean {
if (null == exploreMapFragmentView!!.getLastMapFocus()) {
return true
}
val mylocation = Location("").apply {
latitude = exploreMapFragmentView!!.getLastMapFocus()!!.latitude
longitude = exploreMapFragmentView!!.getLastMapFocus()!!.longitude
}
val dest_location = Location("").apply {
latitude = exploreMapFragmentView!!.getMapFocus()!!.latitude
longitude = exploreMapFragmentView!!.getMapFocus()!!.longitude
}
val distance = mylocation.distanceTo(dest_location)
return !(distance > 2000.0 * 3 / 4)
}
companion object {
private val DUMMY = Proxy.newProxyInstance(
ExploreMapContract.View::class.java.classLoader,
arrayOf<Class<*>>(ExploreMapContract.View::class.java)
) { _: Any?, method: Method, _: Array<Any?>? ->
when {
method.name == "onMyEvent" -> null
String::class.java == method.returnType -> ""
Int::class.java == method.returnType -> 0
Int::class.javaPrimitiveType == method.returnType -> 0
Boolean::class.java == method.returnType -> java.lang.Boolean.FALSE
Boolean::class.javaPrimitiveType == method.returnType -> false
else -> null
}
} as ExploreMapContract.View
}
}