Working geofavorites

This commit is contained in:
Daniele Verducci (Slimpenguin) 2024-02-20 14:02:51 +01:00
parent fd4a9c1f5d
commit 739399f54b
7 changed files with 225 additions and 14 deletions

View File

@ -17,10 +17,14 @@
package it.danieleverducci.nextcloudmaps.activity.main; package it.danieleverducci.nextcloudmaps.activity.main;
import android.Manifest;
import android.content.Intent; import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Bundle; import android.os.Bundle;
import android.view.View; import android.view.View;
import androidx.annotation.NonNull;
import androidx.core.app.ActivityCompat;
import androidx.core.view.GravityCompat; import androidx.core.view.GravityCompat;
import androidx.drawerlayout.widget.DrawerLayout; import androidx.drawerlayout.widget.DrawerLayout;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
@ -48,12 +52,14 @@ import it.danieleverducci.nextcloudmaps.utils.SettingsManager;
public class MainActivity extends NextcloudMapsStyledActivity { public class MainActivity extends NextcloudMapsStyledActivity {
private static final String TAG = "MainActivity"; private static final String TAG = "MainActivity";
private static final int PERMISSION_REQUEST_CODE = 3890;
private static final String NAVIGATION_KEY_ADD_GEOFAVORITE_FROM_GPS = "add_from_gps"; private static final String NAVIGATION_KEY_ADD_GEOFAVORITE_FROM_GPS = "add_from_gps";
private static final String NAVIGATION_KEY_ADD_GEOFAVORITE_FROM_MAP = "add_from_map"; private static final String NAVIGATION_KEY_ADD_GEOFAVORITE_FROM_MAP = "add_from_map";
private static final String NAVIGATION_KEY_SHOW_ABOUT = "about"; private static final String NAVIGATION_KEY_SHOW_ABOUT = "about";
private static final String NAVIGATION_KEY_SWITCH_ACCOUNT = "switch_account"; private static final String NAVIGATION_KEY_SWITCH_ACCOUNT = "switch_account";
private ArrayList<OnGpsPermissionGrantedListener> onGpsPermissionGrantedListener = new ArrayList<>();
private DrawerLayout drawerLayout; private DrawerLayout drawerLayout;
private boolean isFabOpen = false; private boolean isFabOpen = false;
@ -66,12 +72,44 @@ public class MainActivity extends NextcloudMapsStyledActivity {
public void showMap() { public void showMap() {
replaceFragment(new GeofavoriteMapFragment()); replaceFragment(new GeofavoriteMapFragment());
SettingsManager.setGeofavoriteListShownAsMap(this, true);
} }
public void showList() { public void showList() {
replaceFragment(new GeofavoriteListFragment()); replaceFragment(new GeofavoriteListFragment());
SettingsManager.setGeofavoriteListShownAsMap(this, false);
} }
public void addOnGpsPermissionGrantedListener(OnGpsPermissionGrantedListener l) {
onGpsPermissionGrantedListener.add(l);
}
public void removeOnGpsPermissionGrantedListener(OnGpsPermissionGrantedListener l) {
onGpsPermissionGrantedListener.remove(l);
}
public void requestGpsPermissions() {
ActivityCompat.requestPermissions(
this,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
PERMISSION_REQUEST_CODE
);
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == PERMISSION_REQUEST_CODE && permissions[0].equals(Manifest.permission.ACCESS_FINE_LOCATION)) {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
for (OnGpsPermissionGrantedListener l : onGpsPermissionGrantedListener) {
l.onGpsPermissionGranted();
}
}
}
}
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
@ -184,4 +222,8 @@ public class MainActivity extends NextcloudMapsStyledActivity {
} }
public interface OnGpsPermissionGrantedListener {
public void onGpsPermissionGranted();
}
} }

View File

@ -80,8 +80,6 @@ public class GeofavoriteListFragment extends GeofavoritesFragment implements Sor
return false; return false;
}); });
//setSupportActionBar(toolbar);
homeToolbar.setOnClickListener(view -> updateToolbars(false)); homeToolbar.setOnClickListener(view -> updateToolbars(false));
AppCompatImageButton menuButton = v.findViewById(R.id.menu_button); AppCompatImageButton menuButton = v.findViewById(R.id.menu_button);
@ -121,7 +119,7 @@ public class GeofavoriteListFragment extends GeofavoritesFragment implements Sor
geofavoriteAdapter.setSortRule(sortRule); geofavoriteAdapter.setSortRule(sortRule);
// Register for data source events // Register for data source events
mGeofavoritesFragmentViewModel.getIsUpdating().observe(this, new Observer<Boolean>() { mGeofavoritesFragmentViewModel.getIsUpdating().observe(getViewLifecycleOwner(), new Observer<Boolean>() {
@Override @Override
public void onChanged(@Nullable Boolean changed) { public void onChanged(@Nullable Boolean changed) {
if(Boolean.TRUE.equals(changed)){ if(Boolean.TRUE.equals(changed)){
@ -132,7 +130,7 @@ public class GeofavoriteListFragment extends GeofavoritesFragment implements Sor
} }
} }
}); });
mGeofavoritesFragmentViewModel.getGeofavorites().observe(this, new Observer<List<Geofavorite>>() { mGeofavoritesFragmentViewModel.getGeofavorites().observe(getViewLifecycleOwner(), new Observer<List<Geofavorite>>() {
@Override @Override
public void onChanged(List<Geofavorite> geofavorites) { public void onChanged(List<Geofavorite> geofavorites) {
geofavoriteAdapter.setGeofavoriteList(geofavorites); geofavoriteAdapter.setGeofavoriteList(geofavorites);

View File

@ -1,7 +1,10 @@
package it.danieleverducci.nextcloudmaps.fragments; package it.danieleverducci.nextcloudmaps.fragments;
import android.Manifest;
import android.content.pm.PackageManager;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.os.Bundle; import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
@ -9,23 +12,32 @@ import android.view.ViewGroup;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.appcompat.content.res.AppCompatResources; import androidx.appcompat.content.res.AppCompatResources;
import androidx.core.app.ActivityCompat;
import androidx.core.graphics.drawable.DrawableCompat; import androidx.core.graphics.drawable.DrawableCompat;
import androidx.lifecycle.Observer; import androidx.lifecycle.Observer;
import org.osmdroid.api.IMapController;
import org.osmdroid.events.MapEventsReceiver;
import org.osmdroid.util.GeoPoint; import org.osmdroid.util.GeoPoint;
import org.osmdroid.views.MapView; import org.osmdroid.views.MapView;
import org.osmdroid.views.overlay.MapEventsOverlay;
import org.osmdroid.views.overlay.Marker; import org.osmdroid.views.overlay.Marker;
import org.osmdroid.views.overlay.infowindow.MarkerInfoWindow; import org.osmdroid.views.overlay.infowindow.InfoWindow;
import org.osmdroid.views.overlay.mylocation.GpsMyLocationProvider;
import org.osmdroid.views.overlay.mylocation.MyLocationNewOverlay;
import java.util.List; import java.util.List;
import java.util.Set;
import it.danieleverducci.nextcloudmaps.R; import it.danieleverducci.nextcloudmaps.R;
import it.danieleverducci.nextcloudmaps.activity.main.MainActivity; import it.danieleverducci.nextcloudmaps.activity.main.MainActivity;
import it.danieleverducci.nextcloudmaps.model.Geofavorite; import it.danieleverducci.nextcloudmaps.model.Geofavorite;
import it.danieleverducci.nextcloudmaps.utils.MapUtils; import it.danieleverducci.nextcloudmaps.utils.MapUtils;
import it.danieleverducci.nextcloudmaps.utils.SettingsManager;
import it.danieleverducci.nextcloudmaps.views.GeofavMarkerInfoWindow; import it.danieleverducci.nextcloudmaps.views.GeofavMarkerInfoWindow;
public class GeofavoriteMapFragment extends GeofavoritesFragment { public class GeofavoriteMapFragment extends GeofavoritesFragment implements MainActivity.OnGpsPermissionGrantedListener {
private MapView map; private MapView map;
@Override @Override
@ -39,7 +51,21 @@ public class GeofavoriteMapFragment extends GeofavoritesFragment {
@Override @Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_geofavorite_map, container, false); View v = inflater.inflate(R.layout.fragment_geofavorite_map, container, false);
// Setup map
map = v.findViewById(R.id.map); map = v.findViewById(R.id.map);
MapEventsOverlay meo = new MapEventsOverlay(requireContext(), new MapEventsReceiver() {
@Override
public boolean singleTapConfirmedHelper(GeoPoint p) {
InfoWindow.closeAllInfoWindowsOn(map);
return false;
}
@Override
public boolean longPressHelper(GeoPoint p) {return false;}
});
map.getOverlays().add(0, meo);
showUserPosition();
// Setup view listeners // Setup view listeners
View showListButton = v.findViewById(R.id.view_mode_list); View showListButton = v.findViewById(R.id.view_mode_list);
@ -70,17 +96,90 @@ public class GeofavoriteMapFragment extends GeofavoritesFragment {
return v; return v;
} }
@Override
public void onStart() {
super.onStart();
((MainActivity)requireActivity()).addOnGpsPermissionGrantedListener(this);
}
@Override
public void onStop() {
super.onStop();
((MainActivity)requireActivity()).removeOnGpsPermissionGrantedListener(this);
SettingsManager.setLastMapPosition(
requireContext(),
map.getMapCenter().getLatitude(),
map.getMapCenter().getLongitude(),
map.getZoomLevelDouble()
);
}
@Override @Override
public void onSearch(String query) { public void onSearch(String query) {
// TODO: filter // TODO: filter
} }
@Override
public void onGpsPermissionGranted() {
showUserPosition();
}
private void showUserPosition() {
// Center map on last position
double[] pos = SettingsManager.getLastMapPosition(requireContext());
IMapController mapController = map.getController();
mapController.setCenter(new GeoPoint(pos[0], pos[1]));
mapController.setZoom(pos[2]);
// Check if user granted location permission
if (ActivityCompat.checkSelfPermission(requireContext(), Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
ActivityCompat.checkSelfPermission(requireContext(), Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED
) {
// User didn't grant permission. Ask it.
((MainActivity)requireActivity()).requestGpsPermissions();
return;
}
MyLocationNewOverlay mLocationOverlay = new MyLocationNewOverlay(new GpsMyLocationProvider(requireContext()), map);
mLocationOverlay.enableMyLocation();
mLocationOverlay.runOnFirstFix(() -> requireActivity().runOnUiThread(() -> map.getController().animateTo(mLocationOverlay.getMyLocation())));
map.getOverlays().add(mLocationOverlay);
}
private void addMarker(Geofavorite geofavorite){ private void addMarker(Geofavorite geofavorite){
GeoPoint pos = new GeoPoint(geofavorite.getLat(), geofavorite.getLng()); GeoPoint pos = new GeoPoint(geofavorite.getLat(), geofavorite.getLng());
// Set icon and color
Drawable icon = DrawableCompat.wrap(AppCompatResources.getDrawable(requireContext(), R.drawable.ic_list_pin)); Drawable icon = DrawableCompat.wrap(AppCompatResources.getDrawable(requireContext(), R.drawable.ic_list_pin));
DrawableCompat.setTint(icon, geofavorite.categoryColor()); DrawableCompat.setTint(icon, geofavorite.categoryColor());
// Set infowindow (popup opened on marker click) and its listeners
GeofavMarkerInfoWindow iw = new GeofavMarkerInfoWindow(map, geofavorite);
iw.setOnGeofavMarkerInfoWindowClickListener(new GeofavMarkerInfoWindow.OnGeofavMarkerInfoWindowClickListener() {
@Override
public void onGeofavMarkerInfoWindowEditClick() {
openGeofavorite(geofavorite);
}
@Override
public void onGeofavMarkerInfoWindowShareClick() {
shareGeofavorite(geofavorite);
}
@Override
public void onGeofavMarkerInfoWindowNavClick() {
navigateToGeofavorite(geofavorite);
}
@Override
public void onGeofavMarkerInfoWindowDeleteClick() {
deleteGeofavorite(geofavorite);
}
});
// Set marker
Marker m = new Marker(map); Marker m = new Marker(map);
m.setPosition(pos); m.setPosition(pos);
m.setAnchor(Marker.ANCHOR_CENTER, Marker.ANCHOR_BOTTOM); m.setAnchor(Marker.ANCHOR_CENTER, Marker.ANCHOR_BOTTOM);
@ -88,7 +187,7 @@ public class GeofavoriteMapFragment extends GeofavoritesFragment {
m.setTitle(geofavorite.getName()); m.setTitle(geofavorite.getName());
m.setSnippet(geofavorite.getComment()); m.setSnippet(geofavorite.getComment());
m.setSubDescription(geofavorite.getCategory()); m.setSubDescription(geofavorite.getCategory());
m.setInfoWindow(new GeofavMarkerInfoWindow(map)); m.setInfoWindow(iw);
map.getOverlays().add(m); map.getOverlays().add(m);
} }
} }

View File

@ -14,6 +14,7 @@ import androidx.lifecycle.ViewModelProvider;
import it.danieleverducci.nextcloudmaps.R; import it.danieleverducci.nextcloudmaps.R;
import it.danieleverducci.nextcloudmaps.activity.detail.GeofavoriteDetailActivity; import it.danieleverducci.nextcloudmaps.activity.detail.GeofavoriteDetailActivity;
import it.danieleverducci.nextcloudmaps.activity.main.GeofavoritesFragmentViewModel; import it.danieleverducci.nextcloudmaps.activity.main.GeofavoritesFragmentViewModel;
import it.danieleverducci.nextcloudmaps.activity.main.MainActivity;
import it.danieleverducci.nextcloudmaps.model.Geofavorite; import it.danieleverducci.nextcloudmaps.model.Geofavorite;
import it.danieleverducci.nextcloudmaps.utils.IntentGenerator; import it.danieleverducci.nextcloudmaps.utils.IntentGenerator;

View File

@ -1,12 +1,17 @@
package it.danieleverducci.nextcloudmaps.utils; package it.danieleverducci.nextcloudmaps.utils;
import android.content.Context; import android.content.Context;
import android.content.SharedPreferences;
import androidx.preference.PreferenceManager; import androidx.preference.PreferenceManager;
import it.danieleverducci.nextcloudmaps.activity.main.GeofavoriteAdapter; import it.danieleverducci.nextcloudmaps.activity.main.GeofavoriteAdapter;
public class SettingsManager { public class SettingsManager {
static private final String SETTING_SORT_BY = "SETTING_SORT_BY"; static private final String SETTING_SORT_BY = "SETTING_SORT_BY";
static private final String SETTING_LAST_SELECTED_LIST_VIEW = "SETTING_LAST_SELECTED_LIST_VIEW"; static private final String SETTING_LAST_SELECTED_LIST_VIEW = "SETTING_LAST_SELECTED_LIST_VIEW";
static private final String SETTING_LAST_MAP_POSITION_LAT = "SETTING_LAST_MAP_POSITION_LAT";
static private final String SETTING_LAST_MAP_POSITION_LNG = "SETTING_LAST_MAP_POSITION_LNG";
static private final String SETTING_LAST_MAP_POSITION_ZOOM = "SETTING_LAST_MAP_POSITION_ZOOM";
public static int getGeofavoriteListSortBy(Context context) { public static int getGeofavoriteListSortBy(Context context) {
return PreferenceManager.getDefaultSharedPreferences(context) return PreferenceManager.getDefaultSharedPreferences(context)
@ -27,4 +32,26 @@ public class SettingsManager {
PreferenceManager.getDefaultSharedPreferences(context) PreferenceManager.getDefaultSharedPreferences(context)
.edit().putBoolean(SETTING_LAST_SELECTED_LIST_VIEW, value).apply(); .edit().putBoolean(SETTING_LAST_SELECTED_LIST_VIEW, value).apply();
} }
/**
* Returns the last saved position
* @param context
* @return double[lat,lng,zoom]
*/
public static double[] getLastMapPosition(Context context) {
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
return new double[] {
(double) sp.getFloat(SETTING_LAST_MAP_POSITION_LAT, 0.0f),
(double) sp.getFloat(SETTING_LAST_MAP_POSITION_LNG, 0.0f),
(double) sp.getFloat(SETTING_LAST_MAP_POSITION_ZOOM, 10.0f),
};
}
public static void setLastMapPosition(Context context, double lat, double lng, double zoom) {
PreferenceManager.getDefaultSharedPreferences(context).edit()
.putFloat(SETTING_LAST_MAP_POSITION_LAT, (float)lat)
.putFloat(SETTING_LAST_MAP_POSITION_LNG, (float)lng)
.putFloat(SETTING_LAST_MAP_POSITION_ZOOM, (float)zoom)
.apply();
}
} }

View File

@ -1,25 +1,60 @@
package it.danieleverducci.nextcloudmaps.views; package it.danieleverducci.nextcloudmaps.views;
import android.view.View;
import org.osmdroid.views.MapView; import org.osmdroid.views.MapView;
import org.osmdroid.views.overlay.infowindow.InfoWindow;
import org.osmdroid.views.overlay.infowindow.MarkerInfoWindow; import org.osmdroid.views.overlay.infowindow.MarkerInfoWindow;
import it.danieleverducci.nextcloudmaps.R; import it.danieleverducci.nextcloudmaps.R;
import it.danieleverducci.nextcloudmaps.model.Geofavorite;
public class GeofavMarkerInfoWindow extends MarkerInfoWindow { public class GeofavMarkerInfoWindow extends MarkerInfoWindow implements View.OnClickListener {
/** private OnGeofavMarkerInfoWindowClickListener onGeofavMarkerInfoWindowClickListener;
* @param mapView
*/ public GeofavMarkerInfoWindow(MapView mapView, Geofavorite geofavorite) {
public GeofavMarkerInfoWindow(MapView mapView) {
super(R.layout.infowindow_geofav, mapView); super(R.layout.infowindow_geofav, mapView);
getView().findViewById(R.id.action_icon_share).setOnClickListener(this);
getView().findViewById(R.id.action_icon_nav).setOnClickListener(this);
getView().findViewById(R.id.action_icon_delete).setOnClickListener(this);
getView().findViewById(R.id.action_icon_edit).setOnClickListener(this);
}
public void setOnGeofavMarkerInfoWindowClickListener(OnGeofavMarkerInfoWindowClickListener l) {
this.onGeofavMarkerInfoWindowClickListener = l;
} }
@Override @Override
public void onOpen(Object item) { public void onOpen(Object item) {
InfoWindow.closeAllInfoWindowsOn(getMapView());
super.onOpen(item); super.onOpen(item);
} }
@Override @Override
public void onClose() { public void onClick(View v) {
super.onClose(); if (onGeofavMarkerInfoWindowClickListener == null)
return;
if (v.getId() == R.id.action_icon_share)
onGeofavMarkerInfoWindowClickListener.onGeofavMarkerInfoWindowShareClick();
if (v.getId() == R.id.action_icon_nav)
onGeofavMarkerInfoWindowClickListener.onGeofavMarkerInfoWindowNavClick();
if (v.getId() == R.id.action_icon_delete)
onGeofavMarkerInfoWindowClickListener.onGeofavMarkerInfoWindowDeleteClick();
if (v.getId() == R.id.action_icon_edit)
onGeofavMarkerInfoWindowClickListener.onGeofavMarkerInfoWindowEditClick();
}
public interface OnGeofavMarkerInfoWindowClickListener {
public void onGeofavMarkerInfoWindowEditClick();
public void onGeofavMarkerInfoWindowShareClick();
public void onGeofavMarkerInfoWindowNavClick();
public void onGeofavMarkerInfoWindowDeleteClick();
} }
} }

View File

@ -72,6 +72,15 @@
android:src="@drawable/ic_delete_grey" android:src="@drawable/ic_delete_grey"
app:tint="@color/defaultBrand"/> app:tint="@color/defaultBrand"/>
<ImageView
android:id="@+id/action_icon_edit"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:padding="10dp"
android:src="@drawable/ic_edit"
app:tint="@color/defaultBrand"/>
</LinearLayout> </LinearLayout>
<ImageView <ImageView