Compare commits
24 Commits
v0.1
...
adding-map
Author | SHA1 | Date | |
---|---|---|---|
be910bcabe | |||
fdb314c48b | |||
b8541c994a | |||
2a62da3cf2 | |||
7c5de6ccd7 | |||
4ff6c569d0 | |||
c58041fc20 | |||
b3169f6525 | |||
6bca4462a3 | |||
e558fa28b5 | |||
809616aefa | |||
b8551cbb13 | |||
9161b61b6e | |||
9c83707bfc | |||
bd3ca1740a | |||
5d4e56135e | |||
bac3639c3f | |||
e89ce8e7da | |||
79ad2633e7 | |||
a327cf7a21 | |||
b3c63df32e | |||
76e99b7700 | |||
369c842a14 | |||
29bf3c80d3 |
2
.idea/compiler.xml
generated
@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="CompilerConfiguration">
|
<component name="CompilerConfiguration">
|
||||||
<bytecodeTargetLevel target="11" />
|
<bytecodeTargetLevel target="1.8" />
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
17
.idea/deploymentTargetDropDown.xml
generated
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="deploymentTargetDropDown">
|
||||||
|
<targetSelectedWithDropDown>
|
||||||
|
<Target>
|
||||||
|
<type value="QUICK_BOOT_TARGET" />
|
||||||
|
<deviceKey>
|
||||||
|
<Key>
|
||||||
|
<type value="VIRTUAL_DEVICE_PATH" />
|
||||||
|
<value value="$USER_HOME$/.android/avd/Pixel_XL_API_30.avd" />
|
||||||
|
</Key>
|
||||||
|
</deviceKey>
|
||||||
|
</Target>
|
||||||
|
</targetSelectedWithDropDown>
|
||||||
|
<timeTargetWasSelectedWithDropDown value="2021-09-14T16:48:49.750165Z" />
|
||||||
|
</component>
|
||||||
|
</project>
|
17
.idea/misc.xml
generated
@ -1,4 +1,19 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_11" default="true" project-jdk-name="11" project-jdk-type="JavaSDK" />
|
<component name="DesignSurface">
|
||||||
|
<option name="filePathToZoomLevelMap">
|
||||||
|
<map>
|
||||||
|
<entry key="../../../../layout/custom_preview.xml" value="0.5661458333333333" />
|
||||||
|
<entry key="app/src/main/res/layout/activity_geofavorite_detail.xml" value="0.4" />
|
||||||
|
<entry key="app/src/main/res/layout/activity_list_view.xml" value="0.5307291666666667" />
|
||||||
|
<entry key="app/src/main/res/layout/activity_main.xml" value="0.5218150087260035" />
|
||||||
|
<entry key="app/src/main/res/layout/fragment_geofavorite_list.xml" value="0.1734375" />
|
||||||
|
<entry key="app/src/main/res/layout/fragment_map.xml" value="0.19010416666666666" />
|
||||||
|
<entry key="app/src/main/res/layout/item_geofav.xml" value="0.5307291666666667" />
|
||||||
|
<entry key="app/src/main/res/menu/list_context_menu.xml" value="0.41944444444444445" />
|
||||||
|
</map>
|
||||||
|
</option>
|
||||||
|
</component>
|
||||||
|
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
||||||
|
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" project-jdk-name="11" project-jdk-type="JavaSDK" />
|
||||||
</project>
|
</project>
|
10
.idea/runConfigurations.xml
generated
@ -1,10 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="RunConfigurationProducerService">
|
|
||||||
<option name="ignoredProducers">
|
|
||||||
<set>
|
|
||||||
<option value="com.android.tools.idea.compose.preview.runconfiguration.ComposePreviewRunConfigurationProducer" />
|
|
||||||
</set>
|
|
||||||
</option>
|
|
||||||
</component>
|
|
||||||
</project>
|
|
@ -1,3 +1,5 @@
|
|||||||
|

|
||||||
|
|
||||||
# Nextcloud Maps Geobookmarks Android app
|
# Nextcloud Maps Geobookmarks Android app
|
||||||
|
|
||||||
Android app to show your Nextcloud Maps geobookmarks list. Geobookmarks can be opened in all apps supporting geo links (i.e. Google Maps, Organic Maps etc...).
|
Android app to show your Nextcloud Maps geobookmarks list. Geobookmarks can be opened in all apps supporting geo links (i.e. Google Maps, Organic Maps etc...).
|
||||||
@ -7,3 +9,7 @@ A new geobookmark can be created on current location.
|
|||||||
|
|
||||||
This work is heavily based on [matiasdelellis's Nextcloud SSO example](https://github.com/matiasdelellis/app-tutorial-android) to implement [Nextcloud single sign on](https://github.com/nextcloud/Android-SingleSignOn).
|
This work is heavily based on [matiasdelellis's Nextcloud SSO example](https://github.com/matiasdelellis/app-tutorial-android) to implement [Nextcloud single sign on](https://github.com/nextcloud/Android-SingleSignOn).
|
||||||
|
|
||||||
|
 
|
||||||
|
|
||||||
|
Download it from [the releases page](https://github.com/penguin86/nextcloud-maps-client/releases)
|
||||||
|
|
||||||
|
@ -24,8 +24,8 @@ android {
|
|||||||
applicationId "it.danieleverducci.nextcloudmaps"
|
applicationId "it.danieleverducci.nextcloudmaps"
|
||||||
minSdkVersion 23
|
minSdkVersion 23
|
||||||
targetSdkVersion 30
|
targetSdkVersion 30
|
||||||
versionCode 1
|
versionCode 2
|
||||||
versionName "0.1"
|
versionName "0.2"
|
||||||
|
|
||||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||||
}
|
}
|
||||||
@ -55,15 +55,16 @@ dependencies {
|
|||||||
implementation fileTree(dir: "libs", include: ["*.jar"])
|
implementation fileTree(dir: "libs", include: ["*.jar"])
|
||||||
|
|
||||||
implementation 'com.android.support:design:30.0.1'
|
implementation 'com.android.support:design:30.0.1'
|
||||||
implementation 'androidx.appcompat:appcompat:1.2.0'
|
implementation 'androidx.appcompat:appcompat:1.3.1'
|
||||||
implementation 'androidx.recyclerview:recyclerview:1.1.0'
|
implementation 'androidx.recyclerview:recyclerview:1.2.1'
|
||||||
implementation "androidx.cardview:cardview:1.0.0"
|
implementation "androidx.cardview:cardview:1.0.0"
|
||||||
implementation 'androidx.constraintlayout:constraintlayout:2.0.1'
|
implementation 'androidx.constraintlayout:constraintlayout:2.1.0'
|
||||||
implementation "androidx.preference:preference:1.1.1"
|
implementation "androidx.preference:preference:1.1.1"
|
||||||
|
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
|
||||||
|
|
||||||
testImplementation 'junit:junit:4.13'
|
testImplementation 'junit:junit:4.13.2'
|
||||||
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
|
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
|
||||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
|
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
|
||||||
|
|
||||||
// Retrofif2
|
// Retrofif2
|
||||||
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
|
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
|
||||||
@ -71,4 +72,8 @@ dependencies {
|
|||||||
|
|
||||||
// Nextcloud SSO
|
// Nextcloud SSO
|
||||||
implementation "com.github.nextcloud:Android-SingleSignOn:0.5.6"
|
implementation "com.github.nextcloud:Android-SingleSignOn:0.5.6"
|
||||||
|
|
||||||
|
// OSMDroid
|
||||||
|
compile 'org.osmdroid:osmdroid-android:6.1.10'
|
||||||
|
|
||||||
}
|
}
|
||||||
|
18
app/release/output-metadata.json
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
"version": 2,
|
||||||
|
"artifactType": {
|
||||||
|
"type": "APK",
|
||||||
|
"kind": "Directory"
|
||||||
|
},
|
||||||
|
"applicationId": "it.danieleverducci.nextcloudmaps",
|
||||||
|
"variantName": "release",
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"type": "SINGLE",
|
||||||
|
"filters": [],
|
||||||
|
"versionCode": 2,
|
||||||
|
"versionName": "0.2",
|
||||||
|
"outputFile": "app-release.apk"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
@ -30,6 +30,7 @@
|
|||||||
<application
|
<application
|
||||||
android:allowBackup="true"
|
android:allowBackup="true"
|
||||||
android:icon="@mipmap/ic_launcher"
|
android:icon="@mipmap/ic_launcher"
|
||||||
|
android:roundIcon="@mipmap/ic_launcher_round"
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
android:supportsRtl="true"
|
android:supportsRtl="true"
|
||||||
android:theme="@style/AppTheme">
|
android:theme="@style/AppTheme">
|
||||||
@ -48,7 +49,7 @@
|
|||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".activity.main.GeofavoriteDetailActivity"
|
android:name=".activity.detail.GeofavoriteDetailActivity"
|
||||||
android:theme="@style/AppTheme"/>
|
android:theme="@style/AppTheme"/>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
|
BIN
app/src/main/ic_launcher-playstore.png
Normal file
After Width: | Height: | Size: 14 KiB |
@ -0,0 +1,355 @@
|
|||||||
|
/*
|
||||||
|
* Nextcloud Maps Geofavorites for Android
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package it.danieleverducci.nextcloudmaps.activity.detail;
|
||||||
|
|
||||||
|
import android.Manifest;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
|
import android.graphics.Color;
|
||||||
|
import android.location.Location;
|
||||||
|
import android.location.LocationListener;
|
||||||
|
import android.location.LocationManager;
|
||||||
|
import android.os.Build;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
|
import androidx.appcompat.content.res.AppCompatResources;
|
||||||
|
import androidx.core.app.ActivityCompat;
|
||||||
|
import androidx.preference.PreferenceManager;
|
||||||
|
|
||||||
|
import org.osmdroid.api.IMapController;
|
||||||
|
import org.osmdroid.config.Configuration;
|
||||||
|
import org.osmdroid.util.GeoPoint;
|
||||||
|
import org.osmdroid.views.CustomZoomButtonsController;
|
||||||
|
import org.osmdroid.views.overlay.Marker;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
import it.danieleverducci.nextcloudmaps.R;
|
||||||
|
import it.danieleverducci.nextcloudmaps.api.ApiProvider;
|
||||||
|
import it.danieleverducci.nextcloudmaps.databinding.ActivityGeofavoriteDetailBinding;
|
||||||
|
import it.danieleverducci.nextcloudmaps.model.Geofavorite;
|
||||||
|
import retrofit2.Call;
|
||||||
|
import retrofit2.Callback;
|
||||||
|
import retrofit2.Response;
|
||||||
|
|
||||||
|
public class GeofavoriteDetailActivity extends AppCompatActivity implements LocationListener, ActivityCompat.OnRequestPermissionsResultCallback {
|
||||||
|
|
||||||
|
public static final String TAG = "GeofavDetail";
|
||||||
|
public static final String DEFAULT_CATEGORY = "Personal";
|
||||||
|
public static final int MINIMUM_ACCEPTABLE_ACCURACY = 50; // In meters
|
||||||
|
public static final String ARG_GEOFAVORITE = "geofav";
|
||||||
|
private static final int PERMISSION_REQUEST_CODE = 9999;
|
||||||
|
|
||||||
|
private ViewHolder mViewHolder;
|
||||||
|
private Geofavorite mGeofavorite;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
|
// OSMDroid config
|
||||||
|
Configuration.getInstance().load(getApplicationContext(),
|
||||||
|
PreferenceManager.getDefaultSharedPreferences(getApplicationContext()));
|
||||||
|
|
||||||
|
mViewHolder = new ViewHolder(getLayoutInflater());
|
||||||
|
setContentView(mViewHolder.getRootView());
|
||||||
|
mViewHolder.setOnSubmitListener(new OnSubmitListener() {
|
||||||
|
@Override
|
||||||
|
public void onBackPressed() {
|
||||||
|
finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSubmit() {
|
||||||
|
saveGeofavorite();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onMapClicked() {
|
||||||
|
Toast.makeText(GeofavoriteDetailActivity.this, "TODO: Open map activity with pin", Toast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (getIntent().hasExtra(ARG_GEOFAVORITE)) {
|
||||||
|
// Opening geofavorite from list
|
||||||
|
mGeofavorite = (Geofavorite) getIntent().getSerializableExtra(ARG_GEOFAVORITE);
|
||||||
|
mViewHolder.hideAccuracy();
|
||||||
|
} else {
|
||||||
|
// New geofavorite
|
||||||
|
mGeofavorite = new Geofavorite();
|
||||||
|
mGeofavorite.setCategory(DEFAULT_CATEGORY);
|
||||||
|
mGeofavorite.setDateCreated(System.currentTimeMillis());
|
||||||
|
mGeofavorite.setDateModified(System.currentTimeMillis());
|
||||||
|
// Precompile location
|
||||||
|
getLocation();
|
||||||
|
}
|
||||||
|
|
||||||
|
mViewHolder.updateView(mGeofavorite);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onResume() {
|
||||||
|
super.onResume();
|
||||||
|
// OSMDroid config
|
||||||
|
Configuration.getInstance().load(getApplicationContext(),
|
||||||
|
PreferenceManager.getDefaultSharedPreferences(getApplicationContext()));
|
||||||
|
mViewHolder.onResume();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPause() {
|
||||||
|
// OSMDroid config
|
||||||
|
Configuration.getInstance().save(getApplicationContext(),
|
||||||
|
PreferenceManager.getDefaultSharedPreferences(getApplicationContext()));
|
||||||
|
mViewHolder.onPause();
|
||||||
|
super.onPause();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the submit button is clicked
|
||||||
|
* @param v The button
|
||||||
|
*/
|
||||||
|
public void onSubmit(View v) {
|
||||||
|
saveGeofavorite();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks fields and sends updated geofavorite to Nextcloud instance
|
||||||
|
*/
|
||||||
|
private void saveGeofavorite() {
|
||||||
|
mViewHolder.updateModel(mGeofavorite);
|
||||||
|
|
||||||
|
if (!mGeofavorite.valid()) {
|
||||||
|
Toast.makeText(GeofavoriteDetailActivity.this, R.string.incomplete_geofavorite, Toast.LENGTH_SHORT).show();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Call<Geofavorite> call;
|
||||||
|
if (mGeofavorite.getId() == 0) {
|
||||||
|
// New geofavorite
|
||||||
|
call = ApiProvider.getAPI().createGeofavorite(mGeofavorite);
|
||||||
|
} else {
|
||||||
|
// Update existing geofavorite
|
||||||
|
call = ApiProvider.getAPI().updateGeofavorite(mGeofavorite.getId(), mGeofavorite);
|
||||||
|
}
|
||||||
|
call.enqueue(new Callback<Geofavorite>() {
|
||||||
|
@Override
|
||||||
|
public void onResponse(Call<Geofavorite> call, Response<Geofavorite> response) {
|
||||||
|
if (response.isSuccessful())
|
||||||
|
finish();
|
||||||
|
else
|
||||||
|
onGeofavoriteSaveFailed();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(Call<Geofavorite> call, Throwable t) {
|
||||||
|
onGeofavoriteSaveFailed();
|
||||||
|
Log.e(TAG, "Unable to update geofavorite: " + t.getMessage());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onGeofavoriteSaveFailed() {
|
||||||
|
runOnUiThread(() ->
|
||||||
|
Toast.makeText(GeofavoriteDetailActivity.this, R.string.error_saving_geofavorite, Toast.LENGTH_SHORT).show()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtains the current location (requesting user's permission, if necessary)
|
||||||
|
* and calls updateLocationField()
|
||||||
|
*/
|
||||||
|
private void getLocation() {
|
||||||
|
// Check if user granted location permission
|
||||||
|
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
|
||||||
|
// User didn't grant permission. Ask it.
|
||||||
|
requestPermissions(new String[] {Manifest.permission.ACCESS_FINE_LOCATION}, PERMISSION_REQUEST_CODE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LocationManager locationManager = (LocationManager)
|
||||||
|
getSystemService(Context.LOCATION_SERVICE);
|
||||||
|
// Try to use last available location
|
||||||
|
Location lastKnown = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
|
||||||
|
if (lastKnown != null)
|
||||||
|
updateLocationField(lastKnown);
|
||||||
|
// Register for location updates in case the user moves before saving
|
||||||
|
locationManager.requestLocationUpdates(
|
||||||
|
LocationManager.GPS_PROVIDER, 1000, 10, this
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compiles the geofavorite location field with the provided location object
|
||||||
|
* @param location to set in the geofavorite
|
||||||
|
*/
|
||||||
|
private void updateLocationField(Location location) {
|
||||||
|
// Update model
|
||||||
|
mGeofavorite.setLat(location.getLatitude());
|
||||||
|
mGeofavorite.setLng(location.getLongitude());
|
||||||
|
// Update view
|
||||||
|
mViewHolder.updateViewCoords(mGeofavorite);
|
||||||
|
mViewHolder.setAccuracy(location.getAccuracy());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Location updates callbacks **/
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onLocationChanged(@NonNull Location location) {
|
||||||
|
updateLocationField(location);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onStatusChanged(String provider, int status, Bundle extras) {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onProviderEnabled(@NonNull String provider) {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onProviderDisabled(@NonNull String provider) {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPointerCaptureChanged(boolean hasCapture) {}
|
||||||
|
|
||||||
|
|
||||||
|
/** Position permission request result **/
|
||||||
|
|
||||||
|
@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) {
|
||||||
|
getLocation();
|
||||||
|
} else {
|
||||||
|
Toast.makeText(this, R.string.location_permission_required, Toast.LENGTH_LONG).show();
|
||||||
|
finish();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private class ViewHolder implements View.OnClickListener {
|
||||||
|
private final ActivityGeofavoriteDetailBinding binding;
|
||||||
|
private OnSubmitListener listener;
|
||||||
|
private Marker mapMarker;
|
||||||
|
|
||||||
|
public ViewHolder(LayoutInflater inflater) {
|
||||||
|
this.binding = ActivityGeofavoriteDetailBinding.inflate(inflater);
|
||||||
|
this.binding.submitBt.setOnClickListener(this);
|
||||||
|
this.binding.mapBt.setOnClickListener(this);
|
||||||
|
this.binding.backBt.setOnClickListener(this);
|
||||||
|
|
||||||
|
// Set map properties
|
||||||
|
this.binding.map.getZoomController().setVisibility(CustomZoomButtonsController.Visibility.NEVER);
|
||||||
|
this.binding.map.setMultiTouchControls(true);
|
||||||
|
|
||||||
|
// Create marker
|
||||||
|
mapMarker = new Marker(binding.map);
|
||||||
|
mapMarker.setIcon(AppCompatResources.getDrawable(GeofavoriteDetailActivity.this, R.drawable.ic_map_pin));
|
||||||
|
mapMarker.setAnchor(Marker.ANCHOR_CENTER, Marker.ANCHOR_BOTTOM);
|
||||||
|
binding.map.getOverlays().add(mapMarker);
|
||||||
|
}
|
||||||
|
|
||||||
|
public View getRootView() {
|
||||||
|
return this.binding.root;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateView(Geofavorite item) {
|
||||||
|
binding.nameEt.setText(item.getName());
|
||||||
|
binding.descriptionEt.setText(item.getComment());
|
||||||
|
binding.createdTv.setText(new Date(item.getDateCreated() * 1000).toString());
|
||||||
|
binding.modifiedTv.setText(new Date(item.getDateModified() * 1000).toString());
|
||||||
|
binding.categoryTv.setText(item.getCategory()); // TODO: Category spinner from existing categories
|
||||||
|
updateViewCoords(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateViewCoords(Geofavorite item) {
|
||||||
|
binding.coordsTv.setText(item.getCoordinatesString());
|
||||||
|
|
||||||
|
// Center map
|
||||||
|
GeoPoint position = new GeoPoint(item.getLat(), item.getLng());
|
||||||
|
IMapController mapController = binding.map.getController();
|
||||||
|
mapController.setZoom(19.0f);
|
||||||
|
mapController.setCenter(position);
|
||||||
|
|
||||||
|
// Set pin
|
||||||
|
mapMarker.setPosition(position);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateModel(Geofavorite item) {
|
||||||
|
item.setName(binding.nameEt.getText().toString());
|
||||||
|
item.setComment(binding.descriptionEt.getText().toString());
|
||||||
|
item.setDateModified(System.currentTimeMillis() / 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAccuracy(float accuracy) {
|
||||||
|
binding.accuracyTv.setText(getString(R.string.accuracy).replace("{accuracy}", ((int)accuracy) + ""));
|
||||||
|
// Color the accuracy background with a scale from red (MINIMUM_ACCEPTABLE_ACCURACY) to green (0 meters)
|
||||||
|
float red = accuracy / MINIMUM_ACCEPTABLE_ACCURACY;
|
||||||
|
if (red > 1.0f) red = 1.0f;
|
||||||
|
float green = 1.0f - red;
|
||||||
|
if (Build.VERSION.SDK_INT >= 26)
|
||||||
|
binding.accuracyTv.setBackgroundColor(Color.rgb(red, green, 0.0f));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void hideAccuracy() {
|
||||||
|
binding.accuracyTv.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOnSubmitListener(OnSubmitListener listener) {
|
||||||
|
this.listener = listener;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onResume() {
|
||||||
|
binding.map.onResume();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onPause() {
|
||||||
|
binding.map.onPause();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
if (v.getId() == R.id.submit_bt && this.listener != null) {
|
||||||
|
this.listener.onSubmit();
|
||||||
|
}
|
||||||
|
if (v.getId() == R.id.map_bt && this.listener != null) {
|
||||||
|
this.listener.onMapClicked();
|
||||||
|
}
|
||||||
|
if (v.getId() == R.id.back_bt && this.listener != null) {
|
||||||
|
this.listener.onBackPressed();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected interface OnSubmitListener {
|
||||||
|
void onSubmit();
|
||||||
|
void onMapClicked();
|
||||||
|
void onBackPressed();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
package it.danieleverducci.nextcloudmaps.activity.main;
|
||||||
|
|
||||||
|
import it.danieleverducci.nextcloudmaps.model.Geofavorite;
|
||||||
|
|
||||||
|
public interface GeofavoriteActivity {
|
||||||
|
void showGeofavoriteDetailActivity(Geofavorite item);
|
||||||
|
void showGeofavoriteDeteleDialog(Geofavorite item);
|
||||||
|
void updateGeofavorites();
|
||||||
|
void getGeofavorites();
|
||||||
|
|
||||||
|
}
|
@ -21,16 +21,23 @@
|
|||||||
package it.danieleverducci.nextcloudmaps.activity.main;
|
package it.danieleverducci.nextcloudmaps.activity.main;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
import android.text.Html;
|
import android.text.Html;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.ContextMenu;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.Menu;
|
||||||
|
import android.view.MenuInflater;
|
||||||
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.Filter;
|
import android.widget.Filter;
|
||||||
import android.widget.Filterable;
|
import android.widget.Filterable;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
import android.widget.PopupMenu;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.cardview.widget.CardView;
|
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@ -41,7 +48,9 @@ import java.util.List;
|
|||||||
import it.danieleverducci.nextcloudmaps.R;
|
import it.danieleverducci.nextcloudmaps.R;
|
||||||
import it.danieleverducci.nextcloudmaps.model.Geofavorite;
|
import it.danieleverducci.nextcloudmaps.model.Geofavorite;
|
||||||
|
|
||||||
public class GeofavoriteAdapter extends RecyclerView.Adapter<GeofavoriteAdapter.RecyclerViewAdapter> implements Filterable {
|
public class GeofavoriteAdapter extends RecyclerView.Adapter<GeofavoriteAdapter.GeofavoriteViewHolder> implements Filterable {
|
||||||
|
|
||||||
|
public static final String TAG = "GeofavoriteAdapter";
|
||||||
|
|
||||||
public static final int SORT_BY_TITLE = 0;
|
public static final int SORT_BY_TITLE = 0;
|
||||||
public static final int SORT_BY_CREATED = 1;
|
public static final int SORT_BY_CREATED = 1;
|
||||||
@ -53,6 +62,9 @@ public class GeofavoriteAdapter extends RecyclerView.Adapter<GeofavoriteAdapter.
|
|||||||
private List<Geofavorite> geofavoriteListFiltered = new ArrayList<>();
|
private List<Geofavorite> geofavoriteListFiltered = new ArrayList<>();
|
||||||
private int sortRule = SORT_BY_CREATED;
|
private int sortRule = SORT_BY_CREATED;
|
||||||
|
|
||||||
|
// Contains the position of the element containing the overflow menu clicked
|
||||||
|
private int overflowMenuSelectedPosition = -1;
|
||||||
|
|
||||||
public GeofavoriteAdapter(Context context, ItemClickListener itemClickListener) {
|
public GeofavoriteAdapter(Context context, ItemClickListener itemClickListener) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.itemClickListener = itemClickListener;
|
this.itemClickListener = itemClickListener;
|
||||||
@ -70,6 +82,17 @@ public class GeofavoriteAdapter extends RecyclerView.Adapter<GeofavoriteAdapter.
|
|||||||
return geofavoriteListFiltered.get(position);
|
return geofavoriteListFiltered.get(position);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void removeById(int id) {
|
||||||
|
for (Geofavorite g : geofavoriteList) {
|
||||||
|
if (g.getId() == id) {
|
||||||
|
geofavoriteList.remove(g);
|
||||||
|
geofavoriteListFiltered.remove(g);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
notifyDataSetChanged();
|
||||||
|
}
|
||||||
|
|
||||||
public int getSortRule() {
|
public int getSortRule() {
|
||||||
return sortRule;
|
return sortRule;
|
||||||
}
|
}
|
||||||
@ -83,13 +106,13 @@ public class GeofavoriteAdapter extends RecyclerView.Adapter<GeofavoriteAdapter.
|
|||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
@Override
|
@Override
|
||||||
public RecyclerViewAdapter onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
public GeofavoriteViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||||
View view = LayoutInflater.from(context).inflate(R.layout.item_note, parent, false);
|
View view = LayoutInflater.from(context).inflate(R.layout.item_geofav, parent, false);
|
||||||
return new RecyclerViewAdapter(view, itemClickListener);
|
return new GeofavoriteViewHolder(view, itemClickListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBindViewHolder(@NonNull RecyclerViewAdapter holder, int position) {
|
public void onBindViewHolder(@NonNull GeofavoriteViewHolder holder, int position) {
|
||||||
Geofavorite geofavorite = geofavoriteListFiltered.get(position);
|
Geofavorite geofavorite = geofavoriteListFiltered.get(position);
|
||||||
|
|
||||||
holder.tv_title.setText(Html.fromHtml(geofavorite.getName()));
|
holder.tv_title.setText(Html.fromHtml(geofavorite.getName()));
|
||||||
@ -140,26 +163,43 @@ public class GeofavoriteAdapter extends RecyclerView.Adapter<GeofavoriteAdapter.
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class RecyclerViewAdapter extends RecyclerView.ViewHolder implements View.OnClickListener {
|
class GeofavoriteViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
|
||||||
TextView tv_title, tv_content;
|
TextView tv_title, tv_content;
|
||||||
|
ImageView bt_context_menu;
|
||||||
|
ImageView bt_share;
|
||||||
|
|
||||||
ItemClickListener itemClickListener;
|
ItemClickListener itemClickListener;
|
||||||
|
|
||||||
RecyclerViewAdapter(@NonNull View itemView, ItemClickListener itemClickListener) {
|
|
||||||
|
GeofavoriteViewHolder(@NonNull View itemView, ItemClickListener itemClickListener) {
|
||||||
super(itemView);
|
super(itemView);
|
||||||
|
|
||||||
tv_title = itemView.findViewById(R.id.title);
|
tv_title = itemView.findViewById(R.id.title);
|
||||||
tv_content = itemView.findViewById(R.id.content);
|
tv_content = itemView.findViewById(R.id.content);
|
||||||
|
bt_context_menu = itemView.findViewById(R.id.geofav_context_menu_bt);
|
||||||
|
bt_share = itemView.findViewById(R.id.geofav_share_bt);
|
||||||
|
|
||||||
this.itemClickListener = itemClickListener;
|
this.itemClickListener = itemClickListener;
|
||||||
itemView.setOnClickListener(this);
|
itemView.setOnClickListener(this);
|
||||||
|
|
||||||
tv_content.setOnClickListener(this);
|
bt_context_menu.setOnClickListener(this);
|
||||||
|
bt_share.setOnClickListener(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View view) {
|
public void onClick(View view) {
|
||||||
itemClickListener.onItemClick(view, getAdapterPosition());
|
switch (view.getId()) {
|
||||||
|
case R.id.geofav_context_menu_bt:
|
||||||
|
onOverflowIconClicked(view, getAdapterPosition());
|
||||||
|
break;
|
||||||
|
case R.id.geofav_share_bt:
|
||||||
|
if (itemClickListener != null)
|
||||||
|
itemClickListener.onItemShareClick(get(getAdapterPosition()));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (itemClickListener != null)
|
||||||
|
itemClickListener.onItemClick(get(getAdapterPosition()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -171,7 +211,37 @@ public class GeofavoriteAdapter extends RecyclerView.Adapter<GeofavoriteAdapter.
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface ItemClickListener {
|
|
||||||
void onItemClick(View view, int position);
|
private void onOverflowIconClicked(View view, int position) {
|
||||||
|
// Save selected item
|
||||||
|
overflowMenuSelectedPosition = position;
|
||||||
|
// Open menu
|
||||||
|
PopupMenu popup = new PopupMenu(context, view);
|
||||||
|
popup.inflate(R.menu.list_context_menu);
|
||||||
|
popup.setOnMenuItemClickListener(this::optionsItemSelected);
|
||||||
|
popup.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean optionsItemSelected(MenuItem item) {
|
||||||
|
if (overflowMenuSelectedPosition < 0) {
|
||||||
|
Log.e(TAG, "No overflow menu selected position saved!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Geofavorite gf = get(overflowMenuSelectedPosition);
|
||||||
|
overflowMenuSelectedPosition = -1;
|
||||||
|
if (item.getItemId() == R.id.list_context_menu_detail && itemClickListener != null)
|
||||||
|
itemClickListener.onItemDetailsClick(gf);
|
||||||
|
if (item.getItemId() == R.id.list_context_menu_delete)
|
||||||
|
itemClickListener.onItemDeleteClick(gf);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface ItemClickListener {
|
||||||
|
void onItemClick(Geofavorite item);
|
||||||
|
void onItemShareClick(Geofavorite item);
|
||||||
|
void onItemDetailsClick(Geofavorite item);
|
||||||
|
void onItemDeleteClick(Geofavorite item);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
@ -1,188 +0,0 @@
|
|||||||
/*
|
|
||||||
* Nextcloud Maps Geofavorites for Android
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package it.danieleverducci.nextcloudmaps.activity.main;
|
|
||||||
|
|
||||||
import android.Manifest;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.pm.PackageManager;
|
|
||||||
import android.location.Location;
|
|
||||||
import android.location.LocationListener;
|
|
||||||
import android.location.LocationManager;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.util.Log;
|
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.view.View;
|
|
||||||
import android.widget.Toast;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
|
||||||
import androidx.core.app.ActivityCompat;
|
|
||||||
|
|
||||||
import it.danieleverducci.nextcloudmaps.R;
|
|
||||||
import it.danieleverducci.nextcloudmaps.api.ApiProvider;
|
|
||||||
import it.danieleverducci.nextcloudmaps.databinding.ActivityGeofavoriteDetailBinding;
|
|
||||||
import it.danieleverducci.nextcloudmaps.model.Geofavorite;
|
|
||||||
import retrofit2.Call;
|
|
||||||
import retrofit2.Callback;
|
|
||||||
import retrofit2.Response;
|
|
||||||
|
|
||||||
public class GeofavoriteDetailActivity extends AppCompatActivity implements LocationListener, ActivityCompat.OnRequestPermissionsResultCallback {
|
|
||||||
|
|
||||||
public static final String TAG = "GeofavDetail";
|
|
||||||
public static final String ARG_GEOFAVORITE_ID = "geofavid";
|
|
||||||
private static final int PERMISSION_REQUEST_CODE = 9999;
|
|
||||||
|
|
||||||
private ActivityGeofavoriteDetailBinding binding;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
|
||||||
super.onCreate(savedInstanceState);
|
|
||||||
|
|
||||||
binding = ActivityGeofavoriteDetailBinding.inflate(getLayoutInflater());
|
|
||||||
setContentView(binding.root);
|
|
||||||
|
|
||||||
int id = getIntent().getIntExtra(ARG_GEOFAVORITE_ID, 0);
|
|
||||||
if (id == 0) {
|
|
||||||
// New geofavorite
|
|
||||||
Geofavorite gf = new Geofavorite();
|
|
||||||
gf.setDateCreated(System.currentTimeMillis());
|
|
||||||
gf.setDateModified(System.currentTimeMillis());
|
|
||||||
binding.setGeofavorite(gf);
|
|
||||||
// Precompile location
|
|
||||||
getLocation();
|
|
||||||
} else {
|
|
||||||
// TODO: Load geofavorite from cache for edit
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when the submit button is clicked
|
|
||||||
* @param v The button
|
|
||||||
*/
|
|
||||||
public void onSubmit(View v) {
|
|
||||||
saveGeofavorite();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks fields and sends updated geofavorite to Nextcloud instance
|
|
||||||
*/
|
|
||||||
private void saveGeofavorite() {
|
|
||||||
Geofavorite gf = binding.getGeofavorite();
|
|
||||||
gf.setName(binding.nameEt.getText().toString());
|
|
||||||
gf.setComment(binding.descriptionEt.getText().toString());
|
|
||||||
gf.setDateModified(System.currentTimeMillis());
|
|
||||||
|
|
||||||
if (!gf.valid()) {
|
|
||||||
Toast.makeText(GeofavoriteDetailActivity.this, R.string.incomplete_geofavorite, Toast.LENGTH_SHORT).show();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Call<Geofavorite> call;
|
|
||||||
if (gf.getId() == 0) {
|
|
||||||
// New geofavorite
|
|
||||||
call = ApiProvider.getAPI().createGeofavorite(gf);
|
|
||||||
} else {
|
|
||||||
// Update existing geofavorite
|
|
||||||
call = ApiProvider.getAPI().updateGeofavorite(gf.getId(), gf);
|
|
||||||
}
|
|
||||||
call.enqueue(new Callback<Geofavorite>() {
|
|
||||||
@Override
|
|
||||||
public void onResponse(Call<Geofavorite> call, Response<Geofavorite> response) {
|
|
||||||
finish();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onFailure(Call<Geofavorite> call, Throwable t) {
|
|
||||||
Toast.makeText(GeofavoriteDetailActivity.this, R.string.error_saving_geofavorite, Toast.LENGTH_SHORT).show();
|
|
||||||
Log.e(TAG, "Unable to update geofavorite: " + t.getMessage());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Obtains the current location (requesting user's permission, if necessary)
|
|
||||||
* and calls updateLocationField()
|
|
||||||
*/
|
|
||||||
private void getLocation() {
|
|
||||||
// Check if user granted location permission
|
|
||||||
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
|
|
||||||
// User didn't grant permission. Ask it.
|
|
||||||
requestPermissions(new String[] {Manifest.permission.ACCESS_FINE_LOCATION}, PERMISSION_REQUEST_CODE);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
LocationManager locationManager = (LocationManager)
|
|
||||||
getSystemService(Context.LOCATION_SERVICE);
|
|
||||||
// Try to use last available location
|
|
||||||
Location lastKnown = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
|
|
||||||
if (lastKnown != null)
|
|
||||||
updateLocationField(lastKnown);
|
|
||||||
// Register for location updates in case the user moves before saving
|
|
||||||
locationManager.requestLocationUpdates(
|
|
||||||
LocationManager.GPS_PROVIDER, 1000, 10, this
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Compiles the geofavorite location field with the provided location object
|
|
||||||
* @param location to set in the geofavorite
|
|
||||||
*/
|
|
||||||
private void updateLocationField(Location location) {
|
|
||||||
binding.getGeofavorite().setLat(location.getLatitude());
|
|
||||||
binding.getGeofavorite().setLng(location.getLongitude());
|
|
||||||
binding.notifyChange();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** Location updates callbacks **/
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onLocationChanged(@NonNull Location location) {
|
|
||||||
updateLocationField(location);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onStatusChanged(String provider, int status, Bundle extras) {}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onProviderEnabled(@NonNull String provider) {}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onProviderDisabled(@NonNull String provider) {}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onPointerCaptureChanged(boolean hasCapture) {}
|
|
||||||
|
|
||||||
|
|
||||||
/** Position permission request result **/
|
|
||||||
|
|
||||||
@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) {
|
|
||||||
getLocation();
|
|
||||||
} else {
|
|
||||||
Toast.makeText(this, R.string.location_permission_required, Toast.LENGTH_LONG).show();
|
|
||||||
finish();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -17,13 +17,15 @@
|
|||||||
|
|
||||||
package it.danieleverducci.nextcloudmaps.activity.main;
|
package it.danieleverducci.nextcloudmaps.activity.main;
|
||||||
|
|
||||||
|
import android.content.DialogInterface;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.net.Uri;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
|
import android.util.Log;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import androidx.appcompat.app.AlertDialog;
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
import androidx.appcompat.widget.AppCompatImageButton;
|
import androidx.appcompat.widget.AppCompatImageButton;
|
||||||
import androidx.appcompat.widget.AppCompatImageView;
|
import androidx.appcompat.widget.AppCompatImageView;
|
||||||
@ -31,6 +33,7 @@ import androidx.appcompat.widget.SearchView;
|
|||||||
import androidx.appcompat.widget.Toolbar;
|
import androidx.appcompat.widget.Toolbar;
|
||||||
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.FragmentManager;
|
import androidx.fragment.app.FragmentManager;
|
||||||
import androidx.fragment.app.FragmentTransaction;
|
import androidx.fragment.app.FragmentTransaction;
|
||||||
import androidx.preference.PreferenceManager;
|
import androidx.preference.PreferenceManager;
|
||||||
@ -47,10 +50,10 @@ import java.util.List;
|
|||||||
|
|
||||||
import it.danieleverducci.nextcloudmaps.R;
|
import it.danieleverducci.nextcloudmaps.R;
|
||||||
import it.danieleverducci.nextcloudmaps.activity.about.AboutActivity;
|
import it.danieleverducci.nextcloudmaps.activity.about.AboutActivity;
|
||||||
|
import it.danieleverducci.nextcloudmaps.activity.detail.GeofavoriteDetailActivity;
|
||||||
import it.danieleverducci.nextcloudmaps.activity.login.LoginActivity;
|
import it.danieleverducci.nextcloudmaps.activity.login.LoginActivity;
|
||||||
import it.danieleverducci.nextcloudmaps.activity.main.NavigationAdapter.NavigationItem;
|
import it.danieleverducci.nextcloudmaps.activity.main.NavigationAdapter.NavigationItem;
|
||||||
import it.danieleverducci.nextcloudmaps.activity.main.SortingOrderDialogFragment.OnSortingOrderListener;
|
import it.danieleverducci.nextcloudmaps.activity.main.SortingOrderDialogFragment.OnSortingOrderListener;
|
||||||
import it.danieleverducci.nextcloudmaps.api.ApiProvider;
|
|
||||||
import it.danieleverducci.nextcloudmaps.model.Geofavorite;
|
import it.danieleverducci.nextcloudmaps.model.Geofavorite;
|
||||||
|
|
||||||
import static android.view.View.GONE;
|
import static android.view.View.GONE;
|
||||||
@ -59,66 +62,34 @@ import static it.danieleverducci.nextcloudmaps.activity.main.GeofavoriteAdapter.
|
|||||||
import static it.danieleverducci.nextcloudmaps.activity.main.GeofavoriteAdapter.SORT_BY_CREATED;
|
import static it.danieleverducci.nextcloudmaps.activity.main.GeofavoriteAdapter.SORT_BY_CREATED;
|
||||||
import static it.danieleverducci.nextcloudmaps.activity.main.GeofavoriteAdapter.SORT_BY_TITLE;
|
import static it.danieleverducci.nextcloudmaps.activity.main.GeofavoriteAdapter.SORT_BY_TITLE;
|
||||||
|
|
||||||
public class MainActivity extends AppCompatActivity implements MainView, OnSortingOrderListener {
|
public class MainActivity extends AppCompatActivity implements MainView, GeofavoriteActivity {
|
||||||
|
|
||||||
private static final int INTENT_ADD = 100;
|
private static final int INTENT_ADD = 100;
|
||||||
private static final int INTENT_EDIT = 200;
|
private static final int INTENT_EDIT = 200;
|
||||||
|
|
||||||
|
private static final String TAG = "MainActivity";
|
||||||
|
|
||||||
private static final String NAVIGATION_KEY_ADD_GEOFAVORITE = "add";
|
private static final String NAVIGATION_KEY_ADD_GEOFAVORITE = "add";
|
||||||
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 SharedPreferences preferences;
|
|
||||||
|
|
||||||
private DrawerLayout drawerLayout;
|
private DrawerLayout drawerLayout;
|
||||||
private Toolbar toolbar;
|
private Toolbar toolbar;
|
||||||
private MaterialCardView homeToolbar;
|
private MaterialCardView homeToolbar;
|
||||||
private SearchView searchView;
|
private SearchView searchView;
|
||||||
private SwipeRefreshLayout swipeRefresh;
|
|
||||||
private RecyclerView recyclerView;
|
|
||||||
private StaggeredGridLayoutManager layoutManager;
|
|
||||||
private FloatingActionButton fab;
|
private FloatingActionButton fab;
|
||||||
|
|
||||||
private MainPresenter presenter;
|
private MainPresenter presenter;
|
||||||
private GeofavoriteAdapter geofavoriteAdapter;
|
|
||||||
private ItemClickListener itemClickListener;
|
|
||||||
|
|
||||||
NavigationAdapter navigationCommonAdapter;
|
NavigationAdapter navigationCommonAdapter;
|
||||||
|
|
||||||
private ApiProvider mApi;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
setContentView(R.layout.activity_main);
|
setContentView(R.layout.activity_main);
|
||||||
|
|
||||||
preferences = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
|
|
||||||
|
|
||||||
int sortRule = preferences.getInt(getString(R.string.setting_sort_by), SORT_BY_CREATED);
|
|
||||||
boolean gridViewEnabled = preferences.getBoolean(getString(R.string.setting_grid_view_enabled), true);
|
|
||||||
|
|
||||||
recyclerView = findViewById(R.id.recycler_view);
|
|
||||||
layoutManager = new StaggeredGridLayoutManager(gridViewEnabled ? 2 : 1, StaggeredGridLayoutManager.VERTICAL);
|
|
||||||
recyclerView.setLayoutManager(layoutManager);
|
|
||||||
|
|
||||||
presenter = new MainPresenter(this);
|
presenter = new MainPresenter(this);
|
||||||
|
|
||||||
itemClickListener = ((view, position) -> {
|
|
||||||
Geofavorite geofavorite = geofavoriteAdapter.get(position);
|
|
||||||
Intent i = new Intent();
|
|
||||||
i.setAction(Intent.ACTION_VIEW);
|
|
||||||
i.setData(geofavorite.getGeoUri());
|
|
||||||
startActivity(i);
|
|
||||||
});
|
|
||||||
|
|
||||||
geofavoriteAdapter = new GeofavoriteAdapter(getApplicationContext(), itemClickListener);
|
|
||||||
recyclerView.setAdapter(geofavoriteAdapter);
|
|
||||||
|
|
||||||
geofavoriteAdapter.setSortRule(sortRule);
|
|
||||||
|
|
||||||
swipeRefresh = findViewById(R.id.swipe_refresh);
|
|
||||||
swipeRefresh.setOnRefreshListener(() -> presenter.getGeofavorites());
|
|
||||||
|
|
||||||
fab = findViewById(R.id.add);
|
fab = findViewById(R.id.add);
|
||||||
fab.setOnClickListener(view -> addGeofavorite());
|
fab.setOnClickListener(view -> addGeofavorite());
|
||||||
|
|
||||||
@ -159,16 +130,7 @@ public class MainActivity extends AppCompatActivity implements MainView, OnSorti
|
|||||||
AppCompatImageButton menuButton = findViewById(R.id.menu_button);
|
AppCompatImageButton menuButton = findViewById(R.id.menu_button);
|
||||||
menuButton.setOnClickListener(view -> drawerLayout.openDrawer(GravityCompat.START));
|
menuButton.setOnClickListener(view -> drawerLayout.openDrawer(GravityCompat.START));
|
||||||
|
|
||||||
AppCompatImageView viewButton = findViewById(R.id.view_mode);
|
|
||||||
viewButton.setOnClickListener(view -> {
|
|
||||||
boolean gridEnabled = layoutManager.getSpanCount() == 1;
|
|
||||||
onGridIconChosen(gridEnabled);
|
|
||||||
});
|
|
||||||
|
|
||||||
updateSortingIcon(sortRule);
|
updateSortingIcon(sortRule);
|
||||||
updateGridIcon(gridViewEnabled);
|
|
||||||
|
|
||||||
mApi = new ApiProvider(getApplicationContext());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -248,54 +210,71 @@ public class MainActivity extends AppCompatActivity implements MainView, OnSorti
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void showLoading() {
|
public void showLoading() {
|
||||||
swipeRefresh.setRefreshing(true);
|
//todo notify GeofavoriteListConsumer.geoFavoriteLoading(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void hideLoading() {
|
public void hideLoading() {
|
||||||
swipeRefresh.setRefreshing(false);
|
//todo notify GeofavoriteListConsumer.geoFavoriteLoading(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onGetResult(List<Geofavorite> geofavorite_list) {
|
public void onGetResult(List<Geofavorite> geofavorite_list) {
|
||||||
geofavoriteAdapter.setGeofavoriteList(geofavorite_list);
|
//todo notify GeofavoriteListConsumer
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onGeofavoriteDeleted(int id) {
|
||||||
|
// Notify fragment
|
||||||
|
runOnUiThread(() -> {
|
||||||
|
//todo notify GeofavoriteListConsumer
|
||||||
|
Toast.makeText(MainActivity.this, R.string.list_geofavorite_deleted, Toast.LENGTH_LONG).show();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onErrorLoading(String message) {
|
public void onErrorLoading(String message) {
|
||||||
Toast.makeText(MainActivity.this, message, Toast.LENGTH_LONG).show();
|
Toast.makeText(MainActivity.this, R.string.list_geofavorite_connection_error, Toast.LENGTH_LONG).show();
|
||||||
|
Log.e(TAG, "Unable to obtain geofavorites list: " + message);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSortingOrderChosen(int sortSelection) {
|
public void showGeofavoriteDeteleDialog(Geofavorite item) {
|
||||||
geofavoriteAdapter.setSortRule(sortSelection);
|
AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
|
||||||
updateSortingIcon(sortSelection);
|
builder.setMessage(getString(R.string.dialog_delete_message).replace("{name}", item.getName()))
|
||||||
|
.setTitle(R.string.dialog_delete_title)
|
||||||
preferences.edit().putInt(getString(R.string.setting_sort_by), sortSelection).apply();
|
.setPositiveButton(R.string.dialog_delete_delete, new DialogInterface.OnClickListener() {
|
||||||
|
public void onClick(DialogInterface dialog, int id) {
|
||||||
|
presenter.deleteGeofavorite(item.getId());
|
||||||
|
dialog.dismiss();
|
||||||
|
// Callback is onGeofavoriteDeleted
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.setNegativeButton(R.string.dialog_delete_cancel, new DialogInterface.OnClickListener() {
|
||||||
|
public void onClick(DialogInterface dialog, int id) {
|
||||||
|
dialog.dismiss();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
AlertDialog ad = builder.create();
|
||||||
|
ad.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateSortingIcon(int sortSelection) {
|
@Override
|
||||||
AppCompatImageView sortButton = findViewById(R.id.sort_mode);
|
public void updateGeofavorites() {
|
||||||
switch (sortSelection) {
|
presenter.getGeofavorites();
|
||||||
case SORT_BY_TITLE:
|
|
||||||
sortButton.setImageResource(R.drawable.ic_alphabetical_asc);
|
|
||||||
break;
|
|
||||||
case SORT_BY_CREATED:
|
|
||||||
sortButton.setImageResource(R.drawable.ic_modification_asc);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onGridIconChosen(boolean gridEnabled) {
|
@Override
|
||||||
layoutManager.setSpanCount(gridEnabled ? 2 : 1);
|
public void getGeofavorites() {
|
||||||
updateGridIcon(gridEnabled);
|
|
||||||
|
|
||||||
preferences.edit().putBoolean(getString(R.string.setting_grid_view_enabled), gridEnabled).apply();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateGridIcon(boolean gridEnabled) {
|
@Override
|
||||||
AppCompatImageView viewButton = findViewById(R.id.view_mode);
|
public void showGeofavoriteDetailActivity(Geofavorite item) {
|
||||||
viewButton.setImageResource(gridEnabled ? R.drawable.ic_view_list : R.drawable.ic_view_module);
|
Intent i = new Intent(this, GeofavoriteDetailActivity.class);
|
||||||
|
i.putExtra(GeofavoriteDetailActivity.ARG_GEOFAVORITE, item);
|
||||||
|
startActivity(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
@ -50,6 +50,11 @@ public class MainPresenter {
|
|||||||
view.hideLoading();
|
view.hideLoading();
|
||||||
if (response.isSuccessful() && response.body() != null) {
|
if (response.isSuccessful() && response.body() != null) {
|
||||||
view.onGetResult(response.body());
|
view.onGetResult(response.body());
|
||||||
|
} else {
|
||||||
|
((AppCompatActivity) view).runOnUiThread(() -> {
|
||||||
|
view.hideLoading();
|
||||||
|
view.onErrorLoading(response.raw().message());
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -63,4 +68,22 @@ public class MainPresenter {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void deleteGeofavorite(int id) {
|
||||||
|
view.showLoading();
|
||||||
|
Call<Geofavorite> call = ApiProvider.getAPI().deleteGeofavorite(id);
|
||||||
|
call.enqueue(new Callback<Geofavorite>() {
|
||||||
|
@Override
|
||||||
|
public void onResponse(Call<Geofavorite> call, Response<Geofavorite> response) {
|
||||||
|
view.hideLoading();
|
||||||
|
view.onGeofavoriteDeleted(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(Call<Geofavorite> call, Throwable t) {
|
||||||
|
view.hideLoading();
|
||||||
|
view.onErrorLoading(t.getLocalizedMessage());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,5 +28,6 @@ public interface MainView {
|
|||||||
void showLoading();
|
void showLoading();
|
||||||
void hideLoading();
|
void hideLoading();
|
||||||
void onGetResult(List<Geofavorite> geofavorites);
|
void onGetResult(List<Geofavorite> geofavorites);
|
||||||
|
void onGeofavoriteDeleted(int id);
|
||||||
void onErrorLoading(String message);
|
void onErrorLoading(String message);
|
||||||
}
|
}
|
||||||
|
@ -48,12 +48,12 @@ public class ApiProvider {
|
|||||||
initSsoApi(new NextcloudAPI.ApiConnectedListener() {
|
initSsoApi(new NextcloudAPI.ApiConnectedListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onConnected() {
|
public void onConnected() {
|
||||||
// Ignore..
|
Log.d(TAG, "Connected to Nextcloud instance");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onError(Exception ex) {
|
public void onError(Exception ex) {
|
||||||
// Ignore...
|
Log.d(TAG, "Unable to connect to Nextcloud instance: " + ex.toString());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,12 @@
|
|||||||
|
package it.danieleverducci.nextcloudmaps.fragments;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import it.danieleverducci.nextcloudmaps.model.Geofavorite;
|
||||||
|
|
||||||
|
public interface GeofavoriteListConsumer {
|
||||||
|
void onGeofavoritesUpdated(List<Geofavorite> geofavorites);
|
||||||
|
void onGeofavoriteRemoved(Geofavorite geofavorite);
|
||||||
|
void onGeofavoriteAdded(Geofavorite geofavorite);
|
||||||
|
void onGeofavoriteLoading(boolean isLoading);
|
||||||
|
}
|
@ -0,0 +1,152 @@
|
|||||||
|
package it.danieleverducci.nextcloudmaps.fragments;
|
||||||
|
|
||||||
|
import static it.danieleverducci.nextcloudmaps.activity.main.GeofavoriteAdapter.SORT_BY_CREATED;
|
||||||
|
import static it.danieleverducci.nextcloudmaps.activity.main.GeofavoriteAdapter.SORT_BY_TITLE;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
import android.os.Bundle;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.appcompat.widget.AppCompatImageView;
|
||||||
|
import androidx.fragment.app.Fragment;
|
||||||
|
import androidx.preference.PreferenceManager;
|
||||||
|
import androidx.recyclerview.widget.StaggeredGridLayoutManager;
|
||||||
|
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import it.danieleverducci.nextcloudmaps.R;
|
||||||
|
import it.danieleverducci.nextcloudmaps.activity.main.GeofavoriteActivity;
|
||||||
|
import it.danieleverducci.nextcloudmaps.activity.main.GeofavoriteAdapter;
|
||||||
|
import it.danieleverducci.nextcloudmaps.activity.main.MainActivity;
|
||||||
|
import it.danieleverducci.nextcloudmaps.activity.main.SortingOrderDialogFragment;
|
||||||
|
import it.danieleverducci.nextcloudmaps.databinding.FragmentGeofavoriteListBinding;
|
||||||
|
import it.danieleverducci.nextcloudmaps.model.Geofavorite;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Geofavorites list
|
||||||
|
*/
|
||||||
|
public class GeofavoriteListFragment extends Fragment implements GeofavoriteListConsumer, SortingOrderDialogFragment.OnSortingOrderListener {
|
||||||
|
private FragmentGeofavoriteListBinding binding;
|
||||||
|
private GeofavoriteAdapter geofavoriteAdapter;
|
||||||
|
private SharedPreferences preferences;
|
||||||
|
|
||||||
|
public GeofavoriteListFragment() {
|
||||||
|
// Required empty public constructor
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||||
|
Bundle savedInstanceState) {
|
||||||
|
if (binding == null) {
|
||||||
|
binding = FragmentGeofavoriteListBinding.inflate(
|
||||||
|
LayoutInflater.from(container.getContext()),
|
||||||
|
container,
|
||||||
|
false
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
preferences = PreferenceManager.getDefaultSharedPreferences(getContext());
|
||||||
|
|
||||||
|
StaggeredGridLayoutManager layoutManager = new StaggeredGridLayoutManager(1, StaggeredGridLayoutManager.VERTICAL);
|
||||||
|
binding.recyclerView.setLayoutManager(layoutManager);
|
||||||
|
|
||||||
|
int sortRule = preferences.getInt(getString(R.string.setting_sort_by), SORT_BY_CREATED);
|
||||||
|
GeofavoriteAdapter.ItemClickListener rvItemClickListener = new GeofavoriteAdapter.ItemClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onItemClick(Geofavorite geofavorite) {
|
||||||
|
Intent i = new Intent();
|
||||||
|
i.setAction(Intent.ACTION_VIEW);
|
||||||
|
i.setData(geofavorite.getGeoUri());
|
||||||
|
startActivity(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onItemShareClick(Geofavorite item) {
|
||||||
|
Intent i = new Intent();
|
||||||
|
i.setAction(Intent.ACTION_SEND);
|
||||||
|
i.setType("text/plain");
|
||||||
|
String shareMessage = getString(R.string.share_message)
|
||||||
|
.replace("{lat}", ""+item.getLat())
|
||||||
|
.replace("{lng}", ""+item.getLng());
|
||||||
|
i.putExtra(Intent.EXTRA_TEXT, shareMessage );
|
||||||
|
startActivity(Intent.createChooser(i, getString(R.string.share_via)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onItemDetailsClick(Geofavorite item) {
|
||||||
|
if (getActivity() instanceof GeofavoriteActivity)
|
||||||
|
((GeofavoriteActivity)getActivity()).showGeofavoriteDetailActivity(item);
|
||||||
|
else
|
||||||
|
throw new IllegalStateException("Expected activity implementing GeofavoriteAcivity");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onItemDeleteClick(Geofavorite item) {
|
||||||
|
if (getActivity() instanceof GeofavoriteActivity)
|
||||||
|
((GeofavoriteActivity)getActivity()).showGeofavoriteDeteleDialog(item);
|
||||||
|
else
|
||||||
|
throw new IllegalStateException("Expected activity implementing GeofavoriteAcivity");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
geofavoriteAdapter = new GeofavoriteAdapter(getContext(), rvItemClickListener);
|
||||||
|
binding.recyclerView.setAdapter(geofavoriteAdapter);
|
||||||
|
geofavoriteAdapter.setSortRule(sortRule);
|
||||||
|
|
||||||
|
binding.swipeRefresh.setOnRefreshListener(() ->
|
||||||
|
((GeofavoriteActivity)getActivity()).updateGeofavorites());
|
||||||
|
|
||||||
|
return binding.root;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onGeofavoritesUpdated(List<Geofavorite> geofavorites) {
|
||||||
|
if (geofavoriteAdapter != null)
|
||||||
|
geofavoriteAdapter.setGeofavoriteList(geofavorites);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onGeofavoriteRemoved(Geofavorite geofavorite) {
|
||||||
|
// Update list
|
||||||
|
geofavoriteAdapter.removeById(geofavorite.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onGeofavoriteAdded(Geofavorite geofavorite) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onGeofavoriteLoading(boolean isLoading) {
|
||||||
|
binding.swipeRefresh.setRefreshing(isLoading);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSortingOrderChosen(int sortSelection) {
|
||||||
|
geofavoriteAdapter.setSortRule(sortSelection);
|
||||||
|
updateSortingIcon(sortSelection);
|
||||||
|
|
||||||
|
preferences.edit().putInt(getString(R.string.setting_sort_by), sortSelection).apply();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateSortingIcon(int sortSelection) {
|
||||||
|
// TODO: Gestire il bottone come bottone generico da aggiungere all'activity
|
||||||
|
AppCompatImageView sortButton = findViewById(R.id.sort_mode);
|
||||||
|
switch (sortSelection) {
|
||||||
|
case SORT_BY_TITLE:
|
||||||
|
sortButton.setImageResource(R.drawable.ic_alphabetical_asc);
|
||||||
|
break;
|
||||||
|
case SORT_BY_CREATED:
|
||||||
|
sortButton.setImageResource(R.drawable.ic_modification_asc);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,66 @@
|
|||||||
|
package it.danieleverducci.nextcloudmaps.fragments;
|
||||||
|
|
||||||
|
import android.os.Bundle;
|
||||||
|
|
||||||
|
import androidx.fragment.app.Fragment;
|
||||||
|
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
|
import it.danieleverducci.nextcloudmaps.R;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A simple {@link Fragment} subclass.
|
||||||
|
* Use the {@link MapFragment#newInstance} factory method to
|
||||||
|
* create an instance of this fragment.
|
||||||
|
*/
|
||||||
|
public class MapFragment extends Fragment {
|
||||||
|
|
||||||
|
// TODO: Rename parameter arguments, choose names that match
|
||||||
|
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
|
||||||
|
private static final String ARG_PARAM1 = "param1";
|
||||||
|
private static final String ARG_PARAM2 = "param2";
|
||||||
|
|
||||||
|
// TODO: Rename and change types of parameters
|
||||||
|
private String mParam1;
|
||||||
|
private String mParam2;
|
||||||
|
|
||||||
|
public MapFragment() {
|
||||||
|
// Required empty public constructor
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use this factory method to create a new instance of
|
||||||
|
* this fragment using the provided parameters.
|
||||||
|
*
|
||||||
|
* @param param1 Parameter 1.
|
||||||
|
* @param param2 Parameter 2.
|
||||||
|
* @return A new instance of fragment MapFragment.
|
||||||
|
*/
|
||||||
|
// TODO: Rename and change types and number of parameters
|
||||||
|
public static MapFragment newInstance(String param1, String param2) {
|
||||||
|
MapFragment fragment = new MapFragment();
|
||||||
|
Bundle args = new Bundle();
|
||||||
|
args.putString(ARG_PARAM1, param1);
|
||||||
|
args.putString(ARG_PARAM2, param2);
|
||||||
|
fragment.setArguments(args);
|
||||||
|
return fragment;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
if (getArguments() != null) {
|
||||||
|
mParam1 = getArguments().getString(ARG_PARAM1);
|
||||||
|
mParam2 = getArguments().getString(ARG_PARAM2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||||
|
Bundle savedInstanceState) {
|
||||||
|
// Inflate the layout for this fragment
|
||||||
|
return inflater.inflate(R.layout.fragment_map, container, false);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,5 @@
|
|||||||
|
package it.danieleverducci.nextcloudmaps.fragments;
|
||||||
|
|
||||||
|
public interface SortableListFragment {
|
||||||
|
|
||||||
|
}
|
@ -25,6 +25,8 @@ import android.widget.TextView;
|
|||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.databinding.BaseObservable;
|
||||||
|
import androidx.databinding.Bindable;
|
||||||
import androidx.databinding.BindingAdapter;
|
import androidx.databinding.BindingAdapter;
|
||||||
|
|
||||||
import com.google.gson.annotations.Expose;
|
import com.google.gson.annotations.Expose;
|
||||||
@ -90,13 +92,13 @@ public class Geofavorite implements Serializable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void setName(String name) {
|
public void setName(String name) {
|
||||||
this.name = name;
|
if (!name.equals(this.name))
|
||||||
|
this.name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getDateModified() {
|
public long getDateModified() {
|
||||||
return dateModified;
|
return dateModified;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setDateModified(long dateModified) {
|
public void setDateModified(long dateModified) {
|
||||||
this.dateModified = dateModified;
|
this.dateModified = dateModified;
|
||||||
}
|
}
|
||||||
@ -104,7 +106,6 @@ public class Geofavorite implements Serializable {
|
|||||||
public long getDateCreated() {
|
public long getDateCreated() {
|
||||||
return dateCreated;
|
return dateCreated;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setDateCreated(long dateCreated) {
|
public void setDateCreated(long dateCreated) {
|
||||||
this.dateCreated = dateCreated;
|
this.dateCreated = dateCreated;
|
||||||
}
|
}
|
||||||
@ -112,7 +113,6 @@ public class Geofavorite implements Serializable {
|
|||||||
public double getLat() {
|
public double getLat() {
|
||||||
return lat;
|
return lat;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setLat(double lat) {
|
public void setLat(double lat) {
|
||||||
this.lat = lat;
|
this.lat = lat;
|
||||||
}
|
}
|
||||||
@ -120,7 +120,6 @@ public class Geofavorite implements Serializable {
|
|||||||
public double getLng() {
|
public double getLng() {
|
||||||
return lng;
|
return lng;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setLng(double lng) {
|
public void setLng(double lng) {
|
||||||
this.lng = lng;
|
this.lng = lng;
|
||||||
}
|
}
|
||||||
@ -128,7 +127,6 @@ public class Geofavorite implements Serializable {
|
|||||||
public String getCategory() {
|
public String getCategory() {
|
||||||
return category;
|
return category;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCategory(String category) {
|
public void setCategory(String category) {
|
||||||
this.category = category;
|
this.category = category;
|
||||||
}
|
}
|
||||||
@ -137,24 +135,20 @@ public class Geofavorite implements Serializable {
|
|||||||
public String getComment() {
|
public String getComment() {
|
||||||
return comment;
|
return comment;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setComment(String comment) {
|
public void setComment(String comment) {
|
||||||
this.comment = comment;
|
this.comment = comment;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Comparator<Geofavorite> ByTitleAZ = (note, t1) -> note.name.compareTo(t1.name);
|
public static Comparator<Geofavorite> ByTitleAZ = (note, t1) -> note.name.compareTo(t1.name);
|
||||||
|
|
||||||
public static Comparator<Geofavorite> ByLastCreated = (note, t1) -> t1.id - note.id;
|
public static Comparator<Geofavorite> ByLastCreated = (note, t1) -> t1.id - note.id;
|
||||||
|
|
||||||
|
public String getCoordinatesString() {
|
||||||
|
return this.lat + " N, " + this.lng + " E";
|
||||||
|
}
|
||||||
public Uri getGeoUri() {
|
public Uri getGeoUri() {
|
||||||
return Uri.parse("geo:" + this.lat + "," + this.lng + "(" + this.name + ")");
|
return Uri.parse("geo:" + this.lat + "," + this.lng + "(" + this.name + ")");
|
||||||
}
|
}
|
||||||
|
|
||||||
@BindingAdapter("formatDate")
|
|
||||||
public static void formatDate(@NonNull TextView textView, long timestamp) {
|
|
||||||
textView.setText((new Date(timestamp)).toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean valid() {
|
public boolean valid() {
|
||||||
return getLat() != 0 && getLng() != 0 && getName() != null && getName().length() > 0;
|
return getLat() != 0 && getLng() != 0 && getName() != null && getName().length() > 0;
|
||||||
}
|
}
|
||||||
|
@ -1,27 +0,0 @@
|
|||||||
<!--
|
|
||||||
~ Nextcloud Maps Geofavorites for Android
|
|
||||||
~
|
|
||||||
~ This program is free software: you can redistribute it and/or modify
|
|
||||||
~ it under the terms of the GNU General Public License as published by
|
|
||||||
~ the Free Software Foundation, either version 3 of the License, or
|
|
||||||
~ (at your option) any later version.
|
|
||||||
~
|
|
||||||
~ This program is distributed in the hope that it will be useful,
|
|
||||||
~ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
~ GNU General Public License for more details.
|
|
||||||
~
|
|
||||||
~ You should have received a copy of the GNU General Public License
|
|
||||||
~ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<vector
|
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:width="32dp"
|
|
||||||
android:height="32dp"
|
|
||||||
android:viewportWidth="32"
|
|
||||||
android:viewportHeight="32">
|
|
||||||
<path
|
|
||||||
android:pathData="m6,2c-2.216,0 -4,1.784 -4,4v20c0,2.216 1.784,4 4,4h20c2.216,0 4,-1.784 4,-4v-16.719l-0.906,0.9068 -5.282,-5.2818 2.907,-2.9062h-20.719zM21.812,6.9062l5.282,5.2818 -8.313,8.312 -8.781,3.5 3.5,-8.781 8.312,-8.3128zM14.406,16.094l-2.656,4.406 1.75,1.75 4.406,-2.656 -3.5,-3.5z"
|
|
||||||
android:fillColor="#FFF"/>
|
|
||||||
</vector>
|
|
@ -1,74 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<vector
|
|
||||||
android:height="108dp"
|
|
||||||
android:width="108dp"
|
|
||||||
android:viewportHeight="108"
|
|
||||||
android:viewportWidth="108"
|
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
<path android:fillColor="#3DDC84"
|
|
||||||
android:pathData="M0,0h108v108h-108z"/>
|
|
||||||
<path android:fillColor="#00000000" android:pathData="M9,0L9,108"
|
|
||||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
|
||||||
<path android:fillColor="#00000000" android:pathData="M19,0L19,108"
|
|
||||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
|
||||||
<path android:fillColor="#00000000" android:pathData="M29,0L29,108"
|
|
||||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
|
||||||
<path android:fillColor="#00000000" android:pathData="M39,0L39,108"
|
|
||||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
|
||||||
<path android:fillColor="#00000000" android:pathData="M49,0L49,108"
|
|
||||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
|
||||||
<path android:fillColor="#00000000" android:pathData="M59,0L59,108"
|
|
||||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
|
||||||
<path android:fillColor="#00000000" android:pathData="M69,0L69,108"
|
|
||||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
|
||||||
<path android:fillColor="#00000000" android:pathData="M79,0L79,108"
|
|
||||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
|
||||||
<path android:fillColor="#00000000" android:pathData="M89,0L89,108"
|
|
||||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
|
||||||
<path android:fillColor="#00000000" android:pathData="M99,0L99,108"
|
|
||||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
|
||||||
<path android:fillColor="#00000000" android:pathData="M0,9L108,9"
|
|
||||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
|
||||||
<path android:fillColor="#00000000" android:pathData="M0,19L108,19"
|
|
||||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
|
||||||
<path android:fillColor="#00000000" android:pathData="M0,29L108,29"
|
|
||||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
|
||||||
<path android:fillColor="#00000000" android:pathData="M0,39L108,39"
|
|
||||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
|
||||||
<path android:fillColor="#00000000" android:pathData="M0,49L108,49"
|
|
||||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
|
||||||
<path android:fillColor="#00000000" android:pathData="M0,59L108,59"
|
|
||||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
|
||||||
<path android:fillColor="#00000000" android:pathData="M0,69L108,69"
|
|
||||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
|
||||||
<path android:fillColor="#00000000" android:pathData="M0,79L108,79"
|
|
||||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
|
||||||
<path android:fillColor="#00000000" android:pathData="M0,89L108,89"
|
|
||||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
|
||||||
<path android:fillColor="#00000000" android:pathData="M0,99L108,99"
|
|
||||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
|
||||||
<path android:fillColor="#00000000" android:pathData="M19,29L89,29"
|
|
||||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
|
||||||
<path android:fillColor="#00000000" android:pathData="M19,39L89,39"
|
|
||||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
|
||||||
<path android:fillColor="#00000000" android:pathData="M19,49L89,49"
|
|
||||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
|
||||||
<path android:fillColor="#00000000" android:pathData="M19,59L89,59"
|
|
||||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
|
||||||
<path android:fillColor="#00000000" android:pathData="M19,69L89,69"
|
|
||||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
|
||||||
<path android:fillColor="#00000000" android:pathData="M19,79L89,79"
|
|
||||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
|
||||||
<path android:fillColor="#00000000" android:pathData="M29,19L29,89"
|
|
||||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
|
||||||
<path android:fillColor="#00000000" android:pathData="M39,19L39,89"
|
|
||||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
|
||||||
<path android:fillColor="#00000000" android:pathData="M49,19L49,89"
|
|
||||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
|
||||||
<path android:fillColor="#00000000" android:pathData="M59,19L59,89"
|
|
||||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
|
||||||
<path android:fillColor="#00000000" android:pathData="M69,19L69,89"
|
|
||||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
|
||||||
<path android:fillColor="#00000000" android:pathData="M79,19L79,89"
|
|
||||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
|
||||||
</vector>
|
|
@ -2,13 +2,14 @@
|
|||||||
android:width="108dp"
|
android:width="108dp"
|
||||||
android:height="108dp"
|
android:height="108dp"
|
||||||
android:viewportWidth="108"
|
android:viewportWidth="108"
|
||||||
android:viewportHeight="108">
|
android:viewportHeight="108"
|
||||||
<group android:scaleX="1.5525"
|
android:tint="#FFFFFF">
|
||||||
android:scaleY="1.5525"
|
<group android:scaleX="2.61"
|
||||||
android:translateX="29.16"
|
android:scaleY="2.61"
|
||||||
android:translateY="29.16">
|
android:translateX="22.68"
|
||||||
|
android:translateY="22.68">
|
||||||
<path
|
<path
|
||||||
android:pathData="m6,2c-2.216,0 -4,1.784 -4,4v20c0,2.216 1.784,4 4,4h20c2.216,0 4,-1.784 4,-4v-16.719l-0.906,0.9068 -5.282,-5.2818 2.907,-2.9062h-20.719zM21.812,6.9062l5.282,5.2818 -8.313,8.312 -8.781,3.5 3.5,-8.781 8.312,-8.3128zM14.406,16.094l-2.656,4.406 1.75,1.75 4.406,-2.656 -3.5,-3.5z"
|
android:fillColor="@android:color/white"
|
||||||
android:fillColor="#FFF"/>
|
android:pathData="M12,2C8.13,2 5,5.13 5,9c0,5.25 7,13 7,13s7,-7.75 7,-13c0,-3.87 -3.13,-7 -7,-7zM12,11.5c-1.38,0 -2.5,-1.12 -2.5,-2.5s1.12,-2.5 2.5,-2.5 2.5,1.12 2.5,2.5 -1.12,2.5 -2.5,2.5z"/>
|
||||||
</group>
|
</group>
|
||||||
</vector>
|
</vector>
|
||||||
|
5
app/src/main/res/drawable/ic_map_pin.xml
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
<vector android:height="48dp" android:tint="#0082C9"
|
||||||
|
android:viewportHeight="24" android:viewportWidth="24"
|
||||||
|
android:width="48dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<path android:fillColor="@android:color/white" android:pathData="M12,2C8.13,2 5,5.13 5,9c0,5.25 7,13 7,13s7,-7.75 7,-13c0,-3.87 -3.13,-7 -7,-7zM12,11.5c-1.38,0 -2.5,-1.12 -2.5,-2.5s1.12,-2.5 2.5,-2.5 2.5,1.12 2.5,2.5 -1.12,2.5 -2.5,2.5z"/>
|
||||||
|
</vector>
|
5
app/src/main/res/drawable/ic_more.xml
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
<vector android:height="24dp" android:tint="#FFFFFF"
|
||||||
|
android:viewportHeight="24" android:viewportWidth="24"
|
||||||
|
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<path android:fillColor="@android:color/white" android:pathData="M12,8c1.1,0 2,-0.9 2,-2s-0.9,-2 -2,-2 -2,0.9 -2,2 0.9,2 2,2zM12,10c-1.1,0 -2,0.9 -2,2s0.9,2 2,2 2,-0.9 2,-2 -0.9,-2 -2,-2zM12,16c-1.1,0 -2,0.9 -2,2s0.9,2 2,2 2,-0.9 2,-2 -0.9,-2 -2,-2z"/>
|
||||||
|
</vector>
|
5
app/src/main/res/drawable/ic_share.xml
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
<vector android:height="24dp" android:tint="#FFFFFF"
|
||||||
|
android:viewportHeight="24" android:viewportWidth="24"
|
||||||
|
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<path android:fillColor="@android:color/white" android:pathData="M18,16.08c-0.76,0 -1.44,0.3 -1.96,0.77L8.91,12.7c0.05,-0.23 0.09,-0.46 0.09,-0.7s-0.04,-0.47 -0.09,-0.7l7.05,-4.11c0.54,0.5 1.25,0.81 2.04,0.81 1.66,0 3,-1.34 3,-3s-1.34,-3 -3,-3 -3,1.34 -3,3c0,0.24 0.04,0.47 0.09,0.7L8.04,9.81C7.5,9.31 6.79,9 6,9c-1.66,0 -3,1.34 -3,3s1.34,3 3,3c0.79,0 1.5,-0.31 2.04,-0.81l7.12,4.16c-0.05,0.21 -0.08,0.43 -0.08,0.65 0,1.61 1.31,2.92 2.92,2.92 1.61,0 2.92,-1.31 2.92,-2.92s-1.31,-2.92 -2.92,-2.92z"/>
|
||||||
|
</vector>
|
@ -1,23 +0,0 @@
|
|||||||
<!--
|
|
||||||
~ Nextcloud Maps Geofavorites for Android
|
|
||||||
~
|
|
||||||
~ This program is free software: you can redistribute it and/or modify
|
|
||||||
~ it under the terms of the GNU General Public License as published by
|
|
||||||
~ the Free Software Foundation, either version 3 of the License, or
|
|
||||||
~ (at your option) any later version.
|
|
||||||
~
|
|
||||||
~ This program is distributed in the hope that it will be useful,
|
|
||||||
~ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
~ GNU General Public License for more details.
|
|
||||||
~
|
|
||||||
~ You should have received a copy of the GNU General Public License
|
|
||||||
~ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
-->
|
|
||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:height="24dp"
|
|
||||||
android:width="24dp"
|
|
||||||
android:viewportWidth="24"
|
|
||||||
android:viewportHeight="24">
|
|
||||||
<path android:fillColor="#FFFFFF" android:pathData="M9,5V9H21V5M9,19H21V15H9M9,14H21V10H9M4,9H8V5H4M4,19H8V15H4M4,14H8V10H4V14Z" />
|
|
||||||
</vector>
|
|
@ -1,25 +0,0 @@
|
|||||||
<!--
|
|
||||||
~ Nextcloud Maps Geofavorites for Android
|
|
||||||
~
|
|
||||||
~ This program is free software: you can redistribute it and/or modify
|
|
||||||
~ it under the terms of the GNU General Public License as published by
|
|
||||||
~ the Free Software Foundation, either version 3 of the License, or
|
|
||||||
~ (at your option) any later version.
|
|
||||||
~
|
|
||||||
~ This program is distributed in the hope that it will be useful,
|
|
||||||
~ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
~ GNU General Public License for more details.
|
|
||||||
~
|
|
||||||
~ You should have received a copy of the GNU General Public License
|
|
||||||
~ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
-->
|
|
||||||
<vector
|
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:height="24dp"
|
|
||||||
android:width="24dp"
|
|
||||||
android:viewportWidth="24"
|
|
||||||
android:viewportHeight="24">
|
|
||||||
<path android:fillColor="#FFFFFF"
|
|
||||||
android:pathData="M16,5V11H21V5M10,11H15V5H10M16,18H21V12H16M10,18H15V12H10M4,18H9V12H4M4,11H9V5H4V11Z" />
|
|
||||||
</vector>
|
|
@ -2,99 +2,150 @@
|
|||||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
||||||
<data>
|
<FrameLayout
|
||||||
<variable
|
|
||||||
name="geofavorite"
|
|
||||||
type="it.danieleverducci.nextcloudmaps.model.Geofavorite"/>
|
|
||||||
</data>
|
|
||||||
|
|
||||||
<ScrollView
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:id="@+id/root">
|
android:id="@+id/root">
|
||||||
|
|
||||||
<LinearLayout
|
<ScrollView
|
||||||
android:orientation="vertical"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content">
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/map"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="200dp"
|
|
||||||
android:padding="50dp"
|
|
||||||
app:srcCompat="@drawable/ic_app"
|
|
||||||
android:background="@color/defaultBrand" />
|
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:padding="20dp">
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
<EditText
|
<FrameLayout
|
||||||
android:id="@+id/name_et"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="200dp">
|
||||||
android:ems="10"
|
<org.osmdroid.views.MapView
|
||||||
android:hint="@string/name"
|
android:id="@+id/map"
|
||||||
android:lines="1"
|
android:layout_width="match_parent"
|
||||||
android:maxLines="1"
|
android:layout_height="match_parent"
|
||||||
android:singleLine="true"
|
android:focusable="false"
|
||||||
android:ellipsize="end"
|
android:clickable="false"/>
|
||||||
android:text="@{geofavorite.name}"/>
|
<View
|
||||||
|
android:id="@+id/map_bt"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"/>
|
||||||
|
</FrameLayout>
|
||||||
|
|
||||||
<EditText
|
<LinearLayout
|
||||||
android:id="@+id/description_et"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="match_parent"
|
||||||
android:ems="10"
|
android:orientation="vertical"
|
||||||
android:gravity="start|top"
|
android:padding="20dp">
|
||||||
android:inputType="textMultiLine"
|
|
||||||
android:hint="@string/description"
|
|
||||||
android:ellipsize="end"
|
|
||||||
android:text="@{geofavorite.comment}" />
|
|
||||||
|
|
||||||
<TextView
|
<EditText
|
||||||
android:layout_width="match_parent"
|
android:id="@+id/name_et"
|
||||||
android:layout_height="wrap_content"
|
android:layout_width="match_parent"
|
||||||
android:layout_marginTop="20dp"
|
android:layout_height="wrap_content"
|
||||||
android:textStyle="bold"
|
android:ems="10"
|
||||||
android:text="@string/created" />
|
android:hint="@string/name"
|
||||||
|
android:lines="1"
|
||||||
|
android:maxLines="1"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:ellipsize="end"/>
|
||||||
|
|
||||||
<TextView
|
<EditText
|
||||||
android:id="@+id/created_tv"
|
android:id="@+id/description_et"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:textAlignment="textEnd"
|
android:ems="10"
|
||||||
app:formatDate="@{geofavorite.dateCreated}" />
|
android:gravity="start|top"
|
||||||
|
android:inputType="textMultiLine"
|
||||||
|
android:lines="5"
|
||||||
|
android:maxLines="10"
|
||||||
|
android:hint="@string/description"
|
||||||
|
android:ellipsize="end" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="20dp"
|
android:layout_marginTop="20dp"
|
||||||
android:text="@string/coords"
|
android:textStyle="bold"
|
||||||
android:textStyle="bold" />
|
android:text="@string/created" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/coords_tv"
|
android:id="@+id/created_tv"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:textAlignment="textEnd"
|
android:textAlignment="textEnd" />
|
||||||
android:text="@{geofavorite.lat +` °N, ` + geofavorite.lng + ` °E`}" />
|
|
||||||
|
|
||||||
<Button
|
<TextView
|
||||||
android:id="@+id/submit_bt"
|
android:layout_width="match_parent"
|
||||||
style="@style/Widget.AppCompat.Button.Colored"
|
android:layout_height="wrap_content"
|
||||||
android:layout_width="match_parent"
|
android:layout_marginTop="20dp"
|
||||||
android:layout_height="60dp"
|
android:textStyle="bold"
|
||||||
android:layout_margin="50dp"
|
android:text="@string/modified" />
|
||||||
android:text="@string/confirm"
|
|
||||||
app:backgroundTint="@color/defaultBrand"
|
<TextView
|
||||||
android:onClick="onSubmit"/>
|
android:id="@+id/modified_tv"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textAlignment="textEnd" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="20dp"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:text="@string/category" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/category_tv"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textAlignment="textEnd" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="20dp"
|
||||||
|
android:text="@string/coords"
|
||||||
|
android:textStyle="bold" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/coords_tv"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textAlignment="textEnd" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/accuracy_tv"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="10dp"
|
||||||
|
android:textAlignment="center"
|
||||||
|
android:text="@string/accuracy"
|
||||||
|
android:textColor="@android:color/white"
|
||||||
|
android:background="@android:color/darker_gray"/>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/submit_bt"
|
||||||
|
style="@style/Widget.AppCompat.Button.Colored"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="60dp"
|
||||||
|
android:layout_margin="50dp"
|
||||||
|
android:text="@string/confirm"
|
||||||
|
app:backgroundTint="@color/defaultBrand"
|
||||||
|
android:onClick="onSubmit"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
</ScrollView>
|
||||||
|
|
||||||
</LinearLayout>
|
<!-- Back button -->
|
||||||
</ScrollView>
|
<ImageView
|
||||||
|
android:id="@+id/back_bt"
|
||||||
|
android:layout_width="48dp"
|
||||||
|
android:layout_height="48dp"
|
||||||
|
android:padding="12dp"
|
||||||
|
android:src="@drawable/ic_back_grey"
|
||||||
|
app:tint="@color/white"
|
||||||
|
android:background="@color/defaultBrandAlpha"/>
|
||||||
|
|
||||||
|
</FrameLayout>
|
||||||
</layout>
|
</layout>
|
@ -1,166 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!--
|
|
||||||
~ Nextcloud Maps Geofavorites for Android
|
|
||||||
~
|
|
||||||
~ This program is free software: you can redistribute it and/or modify
|
|
||||||
~ it under the terms of the GNU General Public License as published by
|
|
||||||
~ the Free Software Foundation, either version 3 of the License, or
|
|
||||||
~ (at your option) any later version.
|
|
||||||
~
|
|
||||||
~ This program is distributed in the hope that it will be useful,
|
|
||||||
~ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
~ GNU General Public License for more details.
|
|
||||||
~
|
|
||||||
~ You should have received a copy of the GNU General Public License
|
|
||||||
~ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
android:id="@+id/activity_list_view"
|
|
||||||
android:background="@color/primary"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent">
|
|
||||||
|
|
||||||
<com.google.android.material.appbar.AppBarLayout
|
|
||||||
android:id="@+id/appBar"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="?attr/actionBarSize"
|
|
||||||
app:elevation="0dp">
|
|
||||||
|
|
||||||
<com.google.android.material.appbar.CollapsingToolbarLayout
|
|
||||||
android:id="@+id/toolbar_layout"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:fitsSystemWindows="true"
|
|
||||||
app:contentScrim="?attr/colorPrimary"
|
|
||||||
app:layout_scrollFlags="scroll|enterAlways"
|
|
||||||
app:toolbarId="@+id/toolbar" >
|
|
||||||
|
|
||||||
<androidx.appcompat.widget.Toolbar
|
|
||||||
android:id="@+id/toolbar"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:visibility="visible"
|
|
||||||
app:contentInsetStartWithNavigation="0dp"
|
|
||||||
app:titleMarginStart="0dp"
|
|
||||||
tools:title="@string/app_name">
|
|
||||||
|
|
||||||
<androidx.appcompat.widget.SearchView
|
|
||||||
android:id="@+id/search_view"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content">
|
|
||||||
</androidx.appcompat.widget.SearchView>
|
|
||||||
|
|
||||||
</androidx.appcompat.widget.Toolbar>
|
|
||||||
|
|
||||||
<com.google.android.material.card.MaterialCardView
|
|
||||||
android:id="@+id/home_toolbar"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginStart="@dimen/spacer_2x"
|
|
||||||
android:layout_marginTop="@dimen/spacer_1hx"
|
|
||||||
android:layout_marginEnd="@dimen/spacer_2x"
|
|
||||||
android:layout_marginBottom="@dimen/spacer_1hx"
|
|
||||||
app:cardBackgroundColor="@color/appbar"
|
|
||||||
app:cardCornerRadius="@dimen/spacer_1x"
|
|
||||||
app:cardElevation="2dp"
|
|
||||||
app:strokeWidth="0dp">
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:orientation="horizontal">
|
|
||||||
|
|
||||||
<androidx.appcompat.widget.AppCompatImageButton
|
|
||||||
android:id="@+id/menu_button"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:background="?attr/selectableItemBackgroundBorderless"
|
|
||||||
android:paddingStart="@dimen/spacer_1x"
|
|
||||||
android:paddingTop="@dimen/spacer_2x"
|
|
||||||
android:paddingEnd="@dimen/spacer_1x"
|
|
||||||
android:paddingBottom="@dimen/spacer_2x"
|
|
||||||
android:tint="?attr/colorAccent"
|
|
||||||
android:src="@drawable/ic_menu_grey"/>
|
|
||||||
<androidx.appcompat.widget.AppCompatTextView
|
|
||||||
android:id="@+id/search_text"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="center_vertical"
|
|
||||||
android:layout_marginStart="@dimen/spacer_1x"
|
|
||||||
android:layout_marginEnd="@dimen/spacer_1x"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:ellipsize="end"
|
|
||||||
android:gravity="start"
|
|
||||||
android:lines="1"
|
|
||||||
android:textSize="16sp"
|
|
||||||
android:text="@string/search_in_all"/>
|
|
||||||
<androidx.appcompat.widget.AppCompatImageView
|
|
||||||
android:id="@+id/sort_mode"
|
|
||||||
android:layout_width="?attr/actionBarSize"
|
|
||||||
android:layout_height="?attr/actionBarSize"
|
|
||||||
android:layout_gravity="center_vertical|end"
|
|
||||||
android:background="?attr/selectableItemBackgroundBorderless"
|
|
||||||
android:contentDescription="@string/list_mode"
|
|
||||||
android:padding="@dimen/spacer_2x"
|
|
||||||
android:tint="?attr/colorAccent"
|
|
||||||
android:translationX="@dimen/spacer_1x"
|
|
||||||
android:src="@drawable/ic_alphabetical_asc" />
|
|
||||||
<androidx.appcompat.widget.AppCompatImageView
|
|
||||||
android:id="@+id/view_mode"
|
|
||||||
android:layout_width="?attr/actionBarSize"
|
|
||||||
android:layout_height="?attr/actionBarSize"
|
|
||||||
android:layout_gravity="center_vertical|end"
|
|
||||||
android:background="?attr/selectableItemBackgroundBorderless"
|
|
||||||
android:contentDescription="@string/list_mode"
|
|
||||||
android:padding="@dimen/spacer_2x"
|
|
||||||
android:tint="?attr/colorAccent"
|
|
||||||
android:translationX="@dimen/spacer_1x"
|
|
||||||
android:src="@drawable/ic_view_module" />
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
</com.google.android.material.card.MaterialCardView>
|
|
||||||
|
|
||||||
</com.google.android.material.appbar.CollapsingToolbarLayout>
|
|
||||||
|
|
||||||
</com.google.android.material.appbar.AppBarLayout>
|
|
||||||
|
|
||||||
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
|
||||||
android:id="@+id/swipe_refresh"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:layout_margin="@dimen/spacer_1hx"
|
|
||||||
app:layout_behavior="@string/appbar_scrolling_view_behavior">
|
|
||||||
|
|
||||||
<androidx.core.widget.NestedScrollView
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent">
|
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
|
||||||
android:id="@+id/recycler_view"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
app:layoutManager="androidx.recyclerview.widget.StaggeredGridLayoutManager"
|
|
||||||
app:spanCount="2"
|
|
||||||
tools:itemCount="3"
|
|
||||||
tools:listitem="@layout/item_note">
|
|
||||||
</androidx.recyclerview.widget.RecyclerView>
|
|
||||||
|
|
||||||
</androidx.core.widget.NestedScrollView>
|
|
||||||
|
|
||||||
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
|
|
||||||
|
|
||||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
|
||||||
android:id="@+id/add"
|
|
||||||
android:layout_margin="16dp"
|
|
||||||
android:layout_gravity="bottom|end"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:src="@drawable/ic_add"
|
|
||||||
app:backgroundTint="@color/defaultBrand"/>
|
|
||||||
|
|
||||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
|
@ -26,12 +26,126 @@
|
|||||||
tools:openDrawer="start"
|
tools:openDrawer="start"
|
||||||
tools:context=".activity.main.MainActivity">
|
tools:context=".activity.main.MainActivity">
|
||||||
|
|
||||||
<include layout="@layout/activity_list_view"
|
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||||
android:id="@+id/activity_list_view"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:background="@color/primary"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"/>
|
android:layout_height="match_parent"
|
||||||
|
android:id="@+id/root">
|
||||||
|
|
||||||
|
<com.google.android.material.appbar.AppBarLayout
|
||||||
|
android:id="@+id/appBar"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="?attr/actionBarSize"
|
||||||
|
app:elevation="0dp">
|
||||||
|
|
||||||
|
<com.google.android.material.appbar.CollapsingToolbarLayout
|
||||||
|
android:id="@+id/toolbar_layout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:fitsSystemWindows="true"
|
||||||
|
app:contentScrim="?attr/colorPrimary"
|
||||||
|
app:layout_scrollFlags="scroll|enterAlways"
|
||||||
|
app:toolbarId="@+id/toolbar" >
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.Toolbar
|
||||||
|
android:id="@+id/toolbar"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:visibility="visible"
|
||||||
|
app:contentInsetStartWithNavigation="0dp"
|
||||||
|
app:titleMarginStart="0dp"
|
||||||
|
tools:title="@string/app_name">
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.SearchView
|
||||||
|
android:id="@+id/search_view"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
</androidx.appcompat.widget.SearchView>
|
||||||
|
|
||||||
|
</androidx.appcompat.widget.Toolbar>
|
||||||
|
|
||||||
|
<com.google.android.material.card.MaterialCardView
|
||||||
|
android:id="@+id/home_toolbar"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="@dimen/spacer_2x"
|
||||||
|
android:layout_marginTop="@dimen/spacer_1hx"
|
||||||
|
android:layout_marginEnd="@dimen/spacer_2x"
|
||||||
|
android:layout_marginBottom="@dimen/spacer_1hx"
|
||||||
|
app:cardBackgroundColor="@color/appbar"
|
||||||
|
app:cardCornerRadius="@dimen/spacer_1x"
|
||||||
|
app:cardElevation="2dp"
|
||||||
|
app:strokeWidth="0dp">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.AppCompatImageButton
|
||||||
|
android:id="@+id/menu_button"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="?attr/selectableItemBackgroundBorderless"
|
||||||
|
android:paddingStart="@dimen/spacer_1x"
|
||||||
|
android:paddingTop="@dimen/spacer_2x"
|
||||||
|
android:paddingEnd="@dimen/spacer_1x"
|
||||||
|
android:paddingBottom="@dimen/spacer_2x"
|
||||||
|
android:tint="?attr/colorAccent"
|
||||||
|
android:src="@drawable/ic_menu_grey"/>
|
||||||
|
<androidx.appcompat.widget.AppCompatTextView
|
||||||
|
android:id="@+id/search_text"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center_vertical"
|
||||||
|
android:layout_marginStart="@dimen/spacer_1x"
|
||||||
|
android:layout_marginEnd="@dimen/spacer_1x"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:ellipsize="end"
|
||||||
|
android:gravity="start"
|
||||||
|
android:lines="1"
|
||||||
|
android:textSize="16sp"
|
||||||
|
android:text="@string/search_in_all"/>
|
||||||
|
<androidx.appcompat.widget.AppCompatImageView
|
||||||
|
android:id="@+id/sort_mode"
|
||||||
|
android:layout_width="?attr/actionBarSize"
|
||||||
|
android:layout_height="?attr/actionBarSize"
|
||||||
|
android:layout_gravity="center_vertical|end"
|
||||||
|
android:background="?attr/selectableItemBackgroundBorderless"
|
||||||
|
android:contentDescription="@string/list_mode"
|
||||||
|
android:padding="@dimen/spacer_2x"
|
||||||
|
android:tint="?attr/colorAccent"
|
||||||
|
android:translationX="@dimen/spacer_1x"
|
||||||
|
android:src="@drawable/ic_alphabetical_asc" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</com.google.android.material.card.MaterialCardView>
|
||||||
|
|
||||||
|
</com.google.android.material.appbar.CollapsingToolbarLayout>
|
||||||
|
|
||||||
|
</com.google.android.material.appbar.AppBarLayout>
|
||||||
|
|
||||||
|
<androidx.fragment.app.FragmentContainerView
|
||||||
|
android:id="@+id/fragment_container"
|
||||||
|
android:name="it.danieleverducci.nextcloudmaps.fragments.GeofavoriteListFragment"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
</androidx.fragment.app.FragmentContainerView>
|
||||||
|
|
||||||
|
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||||
|
android:id="@+id/add"
|
||||||
|
android:layout_margin="16dp"
|
||||||
|
android:layout_gravity="bottom|end"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:src="@drawable/ic_add"
|
||||||
|
app:backgroundTint="@color/defaultBrand"/>
|
||||||
|
|
||||||
|
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||||
|
|
||||||
<!-- TODO: Is use another layout for that is fill screen. -->
|
|
||||||
<com.google.android.material.navigation.NavigationView
|
<com.google.android.material.navigation.NavigationView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
|
55
app/src/main/res/layout/fragment_geofavorite_list.xml
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
~ Nextcloud Maps Geofavorites for Android
|
||||||
|
~
|
||||||
|
~ This program is free software: you can redistribute it and/or modify
|
||||||
|
~ it under the terms of the GNU General Public License as published by
|
||||||
|
~ the Free Software Foundation, either version 3 of the License, or
|
||||||
|
~ (at your option) any later version.
|
||||||
|
~
|
||||||
|
~ This program is distributed in the hope that it will be useful,
|
||||||
|
~ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
~ GNU General Public License for more details.
|
||||||
|
~
|
||||||
|
~ You should have received a copy of the GNU General Public License
|
||||||
|
~ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools">
|
||||||
|
|
||||||
|
<FrameLayout
|
||||||
|
android:id="@+id/root"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||||
|
android:id="@+id/swipe_refresh"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_margin="@dimen/spacer_1hx"
|
||||||
|
app:layout_behavior="@string/appbar_scrolling_view_behavior">
|
||||||
|
|
||||||
|
<androidx.core.widget.NestedScrollView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:id="@+id/recycler_view"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
app:layoutManager="androidx.recyclerview.widget.StaggeredGridLayoutManager"
|
||||||
|
app:spanCount="1"
|
||||||
|
tools:itemCount="3"
|
||||||
|
tools:listitem="@layout/item_geofav">
|
||||||
|
</androidx.recyclerview.widget.RecyclerView>
|
||||||
|
|
||||||
|
</androidx.core.widget.NestedScrollView>
|
||||||
|
|
||||||
|
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
|
||||||
|
|
||||||
|
</FrameLayout>
|
||||||
|
|
||||||
|
</layout>
|
14
app/src/main/res/layout/fragment_map.xml
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
tools:context=".fragments.MapFragment">
|
||||||
|
|
||||||
|
<!-- TODO: Update blank fragment layout -->
|
||||||
|
<TextView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:text="Map fragment" />
|
||||||
|
|
||||||
|
</FrameLayout>
|
@ -18,11 +18,11 @@
|
|||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:orientation="horizontal"
|
android:orientation="horizontal"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="90dp"
|
||||||
|
android:gravity="center_vertical"
|
||||||
android:padding="12dp"
|
android:padding="12dp"
|
||||||
android:clickable="true"
|
android:clickable="true"
|
||||||
android:focusable="true">
|
android:focusable="true">
|
||||||
@ -31,19 +31,19 @@
|
|||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:layout_weight="0"
|
android:layout_weight="0"
|
||||||
android:layout_marginRight="10dp"
|
|
||||||
android:src="@mipmap/ic_launcher"/>
|
android:src="@mipmap/ic_launcher"/>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content">
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="10dp"
|
||||||
|
android:layout_weight="1">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/title"
|
android:id="@+id/title"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_weight="1"
|
|
||||||
android:textSize="@dimen/note_font_size_item_title"
|
android:textSize="@dimen/note_font_size_item_title"
|
||||||
android:textStyle="bold"
|
android:textStyle="bold"
|
||||||
android:singleLine="true"
|
android:singleLine="true"
|
||||||
@ -60,11 +60,28 @@
|
|||||||
android:layout_marginTop="5dp"
|
android:layout_marginTop="5dp"
|
||||||
android:textSize="@dimen/note_font_size_item_content"
|
android:textSize="@dimen/note_font_size_item_content"
|
||||||
android:maxLines="2"
|
android:maxLines="2"
|
||||||
android:lines="2"
|
android:gravity="center_vertical"
|
||||||
tools:text="@tools:sample/lorem/random">
|
tools:text="@tools:sample/lorem/random">
|
||||||
</TextView>
|
</TextView>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/geofav_share_bt"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_weight="0"
|
||||||
|
android:padding="10dp"
|
||||||
|
android:src="@drawable/ic_share"
|
||||||
|
android:tint="@color/list_text" /> <!-- TODO: app:tint is not working -->
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/geofav_context_menu_bt"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_weight="0"
|
||||||
|
android:padding="10dp"
|
||||||
|
android:src="@drawable/ic_more"
|
||||||
|
android:tint="@color/list_text" /> <!-- TODO: app:tint is not working -->
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
12
app/src/main/res/menu/list_context_menu.xml
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
<!-- Detail button -->
|
||||||
|
<item
|
||||||
|
android:id="@+id/list_context_menu_detail"
|
||||||
|
android:title="@string/list_context_menu_detail"/>
|
||||||
|
<!-- Delete button -->
|
||||||
|
<item
|
||||||
|
android:id="@+id/list_context_menu_delete"
|
||||||
|
android:title="@string/list_context_menu_delete"/>
|
||||||
|
</menu>
|
5
app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<background android:drawable="@color/ic_launcher_background"/>
|
||||||
|
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
|
||||||
|
</adaptive-icon>
|
5
app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<background android:drawable="@color/ic_launcher_background"/>
|
||||||
|
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
|
||||||
|
</adaptive-icon>
|
Before Width: | Height: | Size: 4.0 KiB After Width: | Height: | Size: 1.7 KiB |
BIN
app/src/main/res/mipmap-hdpi/ic_launcher_round.png
Normal file
After Width: | Height: | Size: 3.6 KiB |
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 1.2 KiB |
BIN
app/src/main/res/mipmap-mdpi/ic_launcher_round.png
Normal file
After Width: | Height: | Size: 2.2 KiB |
Before Width: | Height: | Size: 5.0 KiB After Width: | Height: | Size: 2.3 KiB |
BIN
app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
Normal file
After Width: | Height: | Size: 5.0 KiB |
Before Width: | Height: | Size: 9.4 KiB After Width: | Height: | Size: 3.5 KiB |
BIN
app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
Normal file
After Width: | Height: | Size: 8.0 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 4.9 KiB |
BIN
app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
Normal file
After Width: | Height: | Size: 12 KiB |
@ -17,15 +17,18 @@
|
|||||||
-->
|
-->
|
||||||
|
|
||||||
<resources>
|
<resources>
|
||||||
<!-- Colors -->
|
<!-- Generic Colors -->
|
||||||
|
|
||||||
<color name="primary">#ffffff</color>
|
<color name="primary">#ffffff</color>
|
||||||
<color name="accent">#121212</color>
|
<color name="accent">#121212</color>
|
||||||
<color name="transparent">#00000000</color>
|
<color name="transparent">#00000000</color>
|
||||||
|
|
||||||
<color name="defaultBrand">#0082C9</color>
|
<color name="defaultBrand">#0082C9</color>
|
||||||
|
<color name="defaultBrandAlpha">#550082C9</color>
|
||||||
<color name="appbar">@android:color/white</color>
|
<color name="appbar">@android:color/white</color>
|
||||||
|
|
||||||
<color name="defaultTint">#202124</color>
|
<color name="defaultTint">#202124</color>
|
||||||
|
|
||||||
|
<!-- List Colors -->
|
||||||
|
<color name="list_text">#aaa</color>
|
||||||
|
|
||||||
|
<!-- Generic Colors -->
|
||||||
|
<color name="white">#fff</color>
|
||||||
</resources>
|
</resources>
|
@ -1,21 +1,4 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<!--
|
|
||||||
~ Nextcloud Maps Geofavorites for Android
|
|
||||||
~
|
|
||||||
~ This program is free software: you can redistribute it and/or modify
|
|
||||||
~ it under the terms of the GNU General Public License as published by
|
|
||||||
~ the Free Software Foundation, either version 3 of the License, or
|
|
||||||
~ (at your option) any later version.
|
|
||||||
~
|
|
||||||
~ This program is distributed in the hope that it will be useful,
|
|
||||||
~ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
~ GNU General Public License for more details.
|
|
||||||
~
|
|
||||||
~ You should have received a copy of the GNU General Public License
|
|
||||||
~ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<resources>
|
<resources>
|
||||||
<color name="ic_launcher_background">#0082C9</color>
|
<color name="ic_launcher_background">#0082C9</color>
|
||||||
</resources>
|
</resources>
|
@ -29,6 +29,16 @@
|
|||||||
<string name="switch_account">Switch account</string>
|
<string name="switch_account">Switch account</string>
|
||||||
<string name="list_mode">List</string>
|
<string name="list_mode">List</string>
|
||||||
<string name="search_in_all">Search by name</string>
|
<string name="search_in_all">Search by name</string>
|
||||||
|
<string name="share_via">Share via</string>
|
||||||
|
<string name="share_message">Check out this place: {lat}°N, {lng}°E https://www.openstreetmap.org/#map=17/{lat}/{lng}</string>
|
||||||
|
<string name="list_context_menu_detail">Details</string>
|
||||||
|
<string name="list_context_menu_delete">Delete</string>
|
||||||
|
<string name="dialog_delete_title">Delete geobookmark</string>
|
||||||
|
<string name="dialog_delete_message">You are about to delete geobookmark {name}. Proceed?</string>
|
||||||
|
<string name="dialog_delete_delete">Delete</string>
|
||||||
|
<string name="dialog_delete_cancel">Maintain</string>
|
||||||
|
<string name="list_geofavorite_deleted">Geofavorite deleted</string>
|
||||||
|
<string name="list_geofavorite_connection_error">Unable to obtain geofavorites list</string>
|
||||||
|
|
||||||
<!-- Sort dialog -->
|
<!-- Sort dialog -->
|
||||||
<string name="sort_by">Sort by</string>
|
<string name="sort_by">Sort by</string>
|
||||||
@ -40,7 +50,10 @@
|
|||||||
<string name="name">Name</string>
|
<string name="name">Name</string>
|
||||||
<string name="description">Description</string>
|
<string name="description">Description</string>
|
||||||
<string name="created">Created</string>
|
<string name="created">Created</string>
|
||||||
|
<string name="modified">Modified</string>
|
||||||
|
<string name="category">Category</string>
|
||||||
<string name="coords">Coordinates</string>
|
<string name="coords">Coordinates</string>
|
||||||
|
<string name="accuracy">Accuracy: {accuracy} m</string>
|
||||||
<string name="location_permission_required">Location permission is required to create a geofavorite.</string>
|
<string name="location_permission_required">Location permission is required to create a geofavorite.</string>
|
||||||
<string name="confirm">Save</string>
|
<string name="confirm">Save</string>
|
||||||
<string name="error_saving_geofavorite">Unable to save geofavorite</string>
|
<string name="error_saving_geofavorite">Unable to save geofavorite</string>
|
||||||
@ -68,6 +81,5 @@
|
|||||||
|
|
||||||
<!-- Settings -->
|
<!-- Settings -->
|
||||||
<string name="setting_sort_by">SETTING_SORT_BY</string>
|
<string name="setting_sort_by">SETTING_SORT_BY</string>
|
||||||
<string name="setting_grid_view_enabled">SETTING_GRID_VIEW_ENABLED</string>
|
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
2
gradle/wrapper/gradle-wrapper.properties
vendored
@ -20,4 +20,4 @@ distributionBase=GRADLE_USER_HOME
|
|||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-all.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-all.zip
|
||||||
|
BIN
screenshots/1.png
Normal file
After Width: | Height: | Size: 51 KiB |
BIN
screenshots/2.png
Normal file
After Width: | Height: | Size: 49 KiB |