Release v0.2

This commit is contained in:
Daniele 2021-09-10 09:45:46 +02:00
parent 809616aefa
commit e558fa28b5
7 changed files with 170 additions and 49 deletions

View File

@ -4,6 +4,7 @@
<option name="filePathToZoomLevelMap"> <option name="filePathToZoomLevelMap">
<map> <map>
<entry key="../../../../layout/custom_preview.xml" value="0.5661458333333333" /> <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_list_view.xml" value="0.5307291666666667" />
<entry key="app/src/main/res/layout/activity_main.xml" value="0.5307291666666667" /> <entry key="app/src/main/res/layout/activity_main.xml" value="0.5307291666666667" />
<entry key="app/src/main/res/layout/item_geofav.xml" value="0.5307291666666667" /> <entry key="app/src/main/res/layout/item_geofav.xml" value="0.5307291666666667" />

View File

@ -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"
} }

View File

@ -0,0 +1,20 @@
{
"version": 3,
"artifactType": {
"type": "APK",
"kind": "Directory"
},
"applicationId": "it.danieleverducci.nextcloudmaps",
"variantName": "release",
"elements": [
{
"type": "SINGLE",
"filters": [],
"attributes": [],
"versionCode": 2,
"versionName": "0.2",
"outputFile": "app-release.apk"
}
],
"elementType": "File"
}

View File

@ -20,11 +20,14 @@ package it.danieleverducci.nextcloudmaps.activity.detail;
import android.Manifest; import android.Manifest;
import android.content.Context; import android.content.Context;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.graphics.Color;
import android.location.Location; import android.location.Location;
import android.location.LocationListener; import android.location.LocationListener;
import android.location.LocationManager; import android.location.LocationManager;
import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.util.Log; import android.util.Log;
import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.widget.Toast; import android.widget.Toast;
@ -33,6 +36,8 @@ import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat; import androidx.core.app.ActivityCompat;
import java.util.Date;
import it.danieleverducci.nextcloudmaps.R; import it.danieleverducci.nextcloudmaps.R;
import it.danieleverducci.nextcloudmaps.api.ApiProvider; import it.danieleverducci.nextcloudmaps.api.ApiProvider;
import it.danieleverducci.nextcloudmaps.databinding.ActivityGeofavoriteDetailBinding; import it.danieleverducci.nextcloudmaps.databinding.ActivityGeofavoriteDetailBinding;
@ -44,32 +49,38 @@ import retrofit2.Response;
public class GeofavoriteDetailActivity extends AppCompatActivity implements LocationListener, ActivityCompat.OnRequestPermissionsResultCallback { public class GeofavoriteDetailActivity extends AppCompatActivity implements LocationListener, ActivityCompat.OnRequestPermissionsResultCallback {
public static final String TAG = "GeofavDetail"; 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"; public static final String ARG_GEOFAVORITE = "geofav";
private static final int PERMISSION_REQUEST_CODE = 9999; private static final int PERMISSION_REQUEST_CODE = 9999;
private ActivityGeofavoriteDetailBinding binding; private ViewHolder mViewHolder;
private Geofavorite mGeofavorite;
@Override @Override
protected void onCreate(@Nullable Bundle savedInstanceState) { protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
binding = ActivityGeofavoriteDetailBinding.inflate(getLayoutInflater()); mViewHolder = new ViewHolder(getLayoutInflater());
setContentView(binding.root); mViewHolder.setOnSubmitListener(this::saveGeofavorite);
setContentView(mViewHolder.getRootView());
if (getIntent().hasExtra(ARG_GEOFAVORITE)) { if (getIntent().hasExtra(ARG_GEOFAVORITE)) {
// Opening geofavorite from list // Opening geofavorite from list
Geofavorite gfFromList = (Geofavorite) getIntent().getSerializableExtra(ARG_GEOFAVORITE); mGeofavorite = (Geofavorite) getIntent().getSerializableExtra(ARG_GEOFAVORITE);
binding.setGeofavorite(gfFromList); mViewHolder.hideAccuracy();
} else { } else {
// New geofavorite // New geofavorite
Geofavorite gf = new Geofavorite(); mGeofavorite = new Geofavorite();
gf.setDateCreated(System.currentTimeMillis()); mGeofavorite.setCategory(DEFAULT_CATEGORY);
gf.setDateModified(System.currentTimeMillis()); mGeofavorite.setDateCreated(System.currentTimeMillis());
binding.setGeofavorite(gf); mGeofavorite.setDateModified(System.currentTimeMillis());
// Precompile location // Precompile location
getLocation(); getLocation();
} }
mViewHolder.updateView(mGeofavorite);
} }
/** /**
@ -84,23 +95,20 @@ public class GeofavoriteDetailActivity extends AppCompatActivity implements Loca
* Checks fields and sends updated geofavorite to Nextcloud instance * Checks fields and sends updated geofavorite to Nextcloud instance
*/ */
private void saveGeofavorite() { private void saveGeofavorite() {
Geofavorite gf = binding.getGeofavorite(); mViewHolder.updateModel(mGeofavorite);
gf.setName(binding.nameEt.getText().toString());
gf.setComment(binding.descriptionEt.getText().toString());
gf.setDateModified(System.currentTimeMillis());
if (!gf.valid()) { if (!mGeofavorite.valid()) {
Toast.makeText(GeofavoriteDetailActivity.this, R.string.incomplete_geofavorite, Toast.LENGTH_SHORT).show(); Toast.makeText(GeofavoriteDetailActivity.this, R.string.incomplete_geofavorite, Toast.LENGTH_SHORT).show();
return; return;
} }
Call<Geofavorite> call; Call<Geofavorite> call;
if (gf.getId() == 0) { if (mGeofavorite.getId() == 0) {
// New geofavorite // New geofavorite
call = ApiProvider.getAPI().createGeofavorite(gf); call = ApiProvider.getAPI().createGeofavorite(mGeofavorite);
} else { } else {
// Update existing geofavorite // Update existing geofavorite
call = ApiProvider.getAPI().updateGeofavorite(gf.getId(), gf); call = ApiProvider.getAPI().updateGeofavorite(mGeofavorite.getId(), mGeofavorite);
} }
call.enqueue(new Callback<Geofavorite>() { call.enqueue(new Callback<Geofavorite>() {
@Override @Override
@ -145,9 +153,12 @@ public class GeofavoriteDetailActivity extends AppCompatActivity implements Loca
* @param location to set in the geofavorite * @param location to set in the geofavorite
*/ */
private void updateLocationField(Location location) { private void updateLocationField(Location location) {
binding.getGeofavorite().setLat(location.getLatitude()); // Update model
binding.getGeofavorite().setLng(location.getLongitude()); mGeofavorite.setLat(location.getLatitude());
binding.notifyChange(); mGeofavorite.setLng(location.getLongitude());
// Update view
mViewHolder.updateViewCoords(mGeofavorite.getCoordinatesString());
mViewHolder.setAccuracy(location.getAccuracy());
} }
@ -185,4 +196,68 @@ public class GeofavoriteDetailActivity extends AppCompatActivity implements Loca
} }
} }
} }
private class ViewHolder implements View.OnClickListener {
private final ActivityGeofavoriteDetailBinding binding;
private OnSubmitListener listener;
public ViewHolder(LayoutInflater inflater) {
this.binding = ActivityGeofavoriteDetailBinding.inflate(inflater);
this.binding.submitBt.setOnClickListener(this);
}
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
binding.coordsTv.setText(item.getCoordinatesString());
}
public void updateViewCoords(String coords) {
binding.coordsTv.setText(coords);
}
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;
}
@Override
public void onClick(View v) {
if (v.getId() == R.id.submit_bt && this.listener != null) {
this.listener.onSubmit();
}
}
}
protected interface OnSubmitListener {
void onSubmit();
}
} }

View File

@ -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;
} }

View File

@ -2,12 +2,6 @@
<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>
<variable
name="geofavorite"
type="it.danieleverducci.nextcloudmaps.model.Geofavorite"/>
</data>
<ScrollView <ScrollView
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
@ -41,8 +35,7 @@
android:lines="1" android:lines="1"
android:maxLines="1" android:maxLines="1"
android:singleLine="true" android:singleLine="true"
android:ellipsize="end" android:ellipsize="end"/>
android:text="@{geofavorite.name}"/>
<EditText <EditText
android:id="@+id/description_et" android:id="@+id/description_et"
@ -51,9 +44,10 @@
android:ems="10" android:ems="10"
android:gravity="start|top" android:gravity="start|top"
android:inputType="textMultiLine" android:inputType="textMultiLine"
android:lines="5"
android:maxLines="10"
android:hint="@string/description" android:hint="@string/description"
android:ellipsize="end" android:ellipsize="end" />
android:text="@{geofavorite.comment}" />
<TextView <TextView
android:layout_width="match_parent" android:layout_width="match_parent"
@ -66,8 +60,33 @@
android:id="@+id/created_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" />
app:formatDate="@{geofavorite.dateCreated}" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:textStyle="bold"
android:text="@string/modified" />
<TextView
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 <TextView
android:layout_width="match_parent" android:layout_width="match_parent"
@ -80,8 +99,17 @@
android:id="@+id/coords_tv" android:id="@+id/coords_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`}" />
<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 <Button
android:id="@+id/submit_bt" android:id="@+id/submit_bt"

View File

@ -49,7 +49,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>