Compare commits
40 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
a0978d8a54 | ||
|
fac521e0e3 | ||
|
5cf1f72d9c | ||
|
ce1b921447 | ||
|
0de02c6d44 | ||
|
1bbf8d0c5c | ||
|
8b470c1927 | ||
|
904cafcf48 | ||
|
3361ec8965 | ||
|
c5e05e4b8a | ||
|
25f7b05fd0 | ||
|
443e954c66 | ||
|
28258d8c15 | ||
|
d74462a66c | ||
|
572095a7c3 | ||
|
32b005599a | ||
|
49e291881a | ||
|
5949099d91 | ||
|
13287f5b05 | ||
|
acf5090489 | ||
|
7b26938efb | ||
|
0e8f9e2dfa | ||
|
513bc368b2 | ||
|
a752a85a3f | ||
|
053f7401b8 | ||
|
b6ce246a74 | ||
|
ae9274d646 | ||
|
739399f54b | ||
fd4a9c1f5d | |||
d762ffe40a | |||
ebbd4c823b | |||
|
e1747b73f3 | ||
|
e1b1adf9ad | ||
|
a396406877 | ||
|
ca2b7a7064 | ||
|
fa65c33ec6 | ||
|
a1d6f1dabe | ||
|
367d6d0a74 | ||
|
b15236580b | ||
|
334b540721 |
7
.gitignore
vendored
@ -96,3 +96,10 @@ lint/generated/
|
||||
lint/outputs/
|
||||
lint/tmp/
|
||||
# lint/reports/
|
||||
|
||||
app/release/output-metadata.json
|
||||
|
||||
.idea/deploymentTargetDropDown.xml
|
||||
.idea/misc.xml
|
||||
.idea/deploymentTargetSelector.xml
|
||||
.idea/other.xml
|
||||
|
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="CompilerConfiguration">
|
||||
<bytecodeTargetLevel target="11" />
|
||||
<bytecodeTargetLevel target="17" />
|
||||
</component>
|
||||
</project>
|
@ -1,17 +0,0 @@
|
||||
<?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_5_API_29.avd" />
|
||||
</Key>
|
||||
</deviceKey>
|
||||
</Target>
|
||||
</targetSelectedWithDropDown>
|
||||
<timeTargetWasSelectedWithDropDown value="2023-02-15T07:23:10.782369Z" />
|
||||
</component>
|
||||
</project>
|
10
.idea/migrations.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectMigrations">
|
||||
<option name="MigrateToGradleLocalJavaHome">
|
||||
<set>
|
||||
<option value="$PROJECT_DIR$" />
|
||||
</set>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
@ -1,30 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="DesignSurface">
|
||||
<option name="filePathToZoomLevelMap">
|
||||
<map>
|
||||
<entry key="../../../../layout/custom_preview.xml" value="0.5661458333333333" />
|
||||
<entry key="app/src/main/res/drawable/category_listitem_background.xml" value="0.35104166666666664" />
|
||||
<entry key="app/src/main/res/drawable/coordinates_label_background.xml" value="0.3614583333333333" />
|
||||
<entry key="app/src/main/res/drawable/floating_semitransparent_button_background.xml" value="0.512962962962963" />
|
||||
<entry key="app/src/main/res/drawable/ic_list_pin.xml" value="0.3614583333333333" />
|
||||
<entry key="app/src/main/res/drawable/ic_map_pin.xml" value="0.6425925925925926" />
|
||||
<entry key="app/src/main/res/drawable/ic_more.xml" value="0.6166666666666667" />
|
||||
<entry key="app/src/main/res/drawable/ic_nav.xml" value="0.6083333333333333" />
|
||||
<entry key="app/src/main/res/drawable/ic_share.xml" value="0.8828125" />
|
||||
<entry key="app/src/main/res/drawable/round_button_background.xml" value="0.3614583333333333" />
|
||||
<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.4" />
|
||||
<entry key="app/src/main/res/layout/activity_login.xml" value="0.2630208333333333" />
|
||||
<entry key="app/src/main/res/layout/activity_main.xml" value="0.5307291666666667" />
|
||||
<entry key="app/src/main/res/layout/activity_map_picker.xml" value="0.33016304347826086" />
|
||||
<entry key="app/src/main/res/layout/item_geofav.xml" value="0.5307291666666667" />
|
||||
<entry key="app/src/main/res/layout/item_navigation.xml" value="0.8" />
|
||||
<entry key="app/src/main/res/layout/sorting_order_fragment.xml" value="0.4740740740740741" />
|
||||
<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_11" default="true" project-jdk-name="11" project-jdk-type="JavaSDK" />
|
||||
</project>
|
@ -8,7 +8,7 @@
|
||||
|
||||
(Always prefer [F-Droid](https://f-droid.org) build, when possible).
|
||||
|
||||
UNOFFICIAL and FOSS Nextcloud Maps client at its earliest stages of developement. Shows your Nextcloud Maps geofavorites list.
|
||||
UNOFFICIAL and FOSS Nextcloud Maps client at its earliest stages of developement. Shows your Nextcloud Maps geofavorites in a list and a map.
|
||||
Geofavorites can be opened in all apps supporting geo links (i.e. Google Maps, Organic Maps etc...).
|
||||
A new geofavorite can be created on current location, by sharing a "geo:" uri from another app or manually picking from the map.
|
||||
|
||||
@ -16,5 +16,5 @@ A new geofavorite can be created on current location, by sharing a "geo:" uri fr
|
||||
|
||||
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).
|
||||
|
||||
![Screenshot 1](screenshots/1.png) ![Screenshot 1](screenshots/2.png)
|
||||
![Screenshot 1](screenshots/1.png) ![Screenshot 2](screenshots/2.png) ![Screenshot 3](screenshots/3.png)
|
||||
|
||||
|
@ -18,14 +18,12 @@
|
||||
apply plugin: 'com.android.application'
|
||||
|
||||
android {
|
||||
compileSdkVersion 31
|
||||
|
||||
defaultConfig {
|
||||
applicationId "it.danieleverducci.nextcloudmaps"
|
||||
minSdkVersion 23
|
||||
targetSdkVersion 31
|
||||
versionCode 8
|
||||
versionName "0.3.6"
|
||||
targetSdkVersion 35
|
||||
versionCode 9
|
||||
versionName "0.4.0"
|
||||
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
@ -37,6 +35,9 @@ android {
|
||||
}
|
||||
}
|
||||
compileOptions {
|
||||
// Flag to enable support for the new language APIs
|
||||
coreLibraryDesugaringEnabled true
|
||||
// Sets Java compatibility to Java 8
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
@ -44,6 +45,7 @@ android {
|
||||
buildFeatures {
|
||||
dataBinding true
|
||||
}
|
||||
namespace 'it.danieleverducci.nextcloudmaps'
|
||||
}
|
||||
|
||||
repositories {
|
||||
@ -54,28 +56,40 @@ repositories {
|
||||
dependencies {
|
||||
implementation fileTree(dir: "libs", include: ["*.jar"])
|
||||
|
||||
implementation 'com.android.support:design:31.0.0'
|
||||
implementation 'androidx.appcompat:appcompat:1.3.1'
|
||||
implementation 'androidx.recyclerview:recyclerview:1.2.1'
|
||||
implementation "androidx.cardview:cardview:1.0.0"
|
||||
implementation 'androidx.constraintlayout:constraintlayout:2.1.0'
|
||||
implementation "androidx.preference:preference:1.1.1"
|
||||
// Desugaring lib: see https://developer.android.com/studio/write/java8-support
|
||||
coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.1.2")
|
||||
|
||||
testImplementation 'junit:junit:4.13.2'
|
||||
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
|
||||
implementation 'com.android.support:design:34.0.0'
|
||||
implementation 'androidx.appcompat:appcompat:1.7.0'
|
||||
implementation 'androidx.recyclerview:recyclerview:1.3.2'
|
||||
implementation "androidx.cardview:cardview:1.0.0"
|
||||
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
|
||||
implementation "androidx.preference:preference:1.2.1"
|
||||
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0'
|
||||
|
||||
// Retrofif2
|
||||
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
|
||||
implementation 'com.squareup.retrofit2:retrofit:2.11.0'
|
||||
implementation 'com.squareup.retrofit2:converter-gson:2.6.1'
|
||||
|
||||
// Nextcloud SSO
|
||||
implementation "com.github.nextcloud:Android-SingleSignOn:0.6.1"
|
||||
implementation "com.github.nextcloud:Android-SingleSignOn:1.3.2"
|
||||
|
||||
// OSMDroid
|
||||
implementation 'org.osmdroid:osmdroid-android:6.1.10'
|
||||
implementation 'org.osmdroid:osmdroid-android:6.1.18'
|
||||
|
||||
//Threeten-Backport (ports Java 8 Date API on Java 6+)
|
||||
implementation 'org.threeten:threetenbp:1.5.1'
|
||||
|
||||
// https://mvnrepository.com/artifact/commons-io/commons-io
|
||||
implementation 'commons-io:commons-io:2.13.0'
|
||||
|
||||
// Picasso (image loader)
|
||||
implementation 'com.squareup.picasso:picasso:2.8'
|
||||
|
||||
configurations.all {
|
||||
resolutionStrategy {
|
||||
force 'commons-io:commons-io:2.11.0'
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -17,8 +17,7 @@
|
||||
-->
|
||||
|
||||
<manifest
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="it.danieleverducci.nextcloudmaps">
|
||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
||||
|
@ -0,0 +1,47 @@
|
||||
package it.danieleverducci.nextcloudmaps.activity.detail;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.graphics.drawable.DrawableCompat;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
|
||||
import it.danieleverducci.nextcloudmaps.R;
|
||||
import it.danieleverducci.nextcloudmaps.model.Geofavorite;
|
||||
|
||||
public class CategoriesAdapter extends ArrayAdapter<String> {
|
||||
|
||||
public CategoriesAdapter(@NonNull Context context) {
|
||||
super(context, R.layout.category_listitem, R.id.category_name, new ArrayList<>());
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
|
||||
View v = super.getView(position, convertView, parent);
|
||||
TextView categoryName = v.findViewById(R.id.category_name);
|
||||
Drawable backgroundDrawable = categoryName.getBackground();
|
||||
DrawableCompat.setTint(
|
||||
backgroundDrawable,
|
||||
Geofavorite.categoryColorFromName(categoryName.getText().toString()) == 0
|
||||
? v.getContext().getColor(R.color.defaultBrand)
|
||||
: Geofavorite.categoryColorFromName(categoryName.getText().toString())
|
||||
);
|
||||
return v;
|
||||
}
|
||||
|
||||
public void setCategoriesList(HashSet<String> categories) {
|
||||
clear();
|
||||
addAll(categories);
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
}
|
@ -1,24 +0,0 @@
|
||||
package it.danieleverducci.nextcloudmaps.activity.detail;
|
||||
|
||||
import android.content.Context;
|
||||
import android.widget.ArrayAdapter;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import java.util.HashSet;
|
||||
|
||||
public class CategoriesSpinnerAdapter extends ArrayAdapter<String> {
|
||||
|
||||
public CategoriesSpinnerAdapter(@NonNull Context context) {
|
||||
super(context, android.R.layout.simple_dropdown_item_1line);
|
||||
}
|
||||
|
||||
// TODO: implement colors
|
||||
|
||||
public void setCategoriesList(HashSet<String> categories) {
|
||||
clear();
|
||||
addAll(categories);
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
}
|
@ -18,14 +18,14 @@
|
||||
package it.danieleverducci.nextcloudmaps.activity.detail;
|
||||
|
||||
import android.Manifest;
|
||||
import android.content.ClipData;
|
||||
import android.content.ClipboardManager;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
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;
|
||||
@ -34,7 +34,6 @@ 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.lifecycle.Observer;
|
||||
@ -43,7 +42,6 @@ import androidx.preference.PreferenceManager;
|
||||
|
||||
import org.osmdroid.api.IMapController;
|
||||
import org.osmdroid.config.Configuration;
|
||||
import org.osmdroid.config.IConfigurationProvider;
|
||||
import org.osmdroid.util.GeoPoint;
|
||||
import org.osmdroid.views.CustomZoomButtonsController;
|
||||
import org.osmdroid.views.overlay.Marker;
|
||||
@ -52,10 +50,8 @@ import org.threeten.bp.format.FormatStyle;
|
||||
|
||||
import java.util.HashSet;
|
||||
|
||||
import it.danieleverducci.nextcloudmaps.BuildConfig;
|
||||
import it.danieleverducci.nextcloudmaps.R;
|
||||
import it.danieleverducci.nextcloudmaps.activity.NextcloudMapsStyledActivity;
|
||||
import it.danieleverducci.nextcloudmaps.activity.mappicker.MapPickerActivity;
|
||||
import it.danieleverducci.nextcloudmaps.databinding.ActivityGeofavoriteDetailBinding;
|
||||
import it.danieleverducci.nextcloudmaps.model.Geofavorite;
|
||||
import it.danieleverducci.nextcloudmaps.utils.GeoUriParser;
|
||||
@ -86,11 +82,6 @@ public class GeofavoriteDetailActivity extends NextcloudMapsStyledActivity imple
|
||||
finish();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMapEditPressed() {
|
||||
//TODO
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActionIconShareClicked() {
|
||||
startActivity(Intent.createChooser(IntentGenerator.newShareIntent(GeofavoriteDetailActivity.this, mGeofavorite), getString(R.string.share_via)));
|
||||
@ -313,9 +304,15 @@ public class GeofavoriteDetailActivity extends NextcloudMapsStyledActivity imple
|
||||
this.binding.actionIconNav.setOnClickListener(this);
|
||||
|
||||
// Set categories adapter
|
||||
CategoriesSpinnerAdapter categoriesAdapter = new CategoriesSpinnerAdapter(binding.root.getContext());
|
||||
CategoriesAdapter categoriesAdapter = new CategoriesAdapter(binding.root.getContext());
|
||||
this.binding.categoryAt.setAdapter(categoriesAdapter);
|
||||
this.binding.categoryAt.setText(Geofavorite.DEFAULT_CATEGORY);
|
||||
this.binding.categoryAtClear.setOnClickListener((v) -> {
|
||||
if (this.binding.categoryAt.getText().toString().isEmpty())
|
||||
this.binding.categoryAt.setText(Geofavorite.DEFAULT_CATEGORY);
|
||||
else
|
||||
this.binding.categoryAt.setText("");
|
||||
});
|
||||
|
||||
// Set map properties
|
||||
this.binding.map.getZoomController().setVisibility(CustomZoomButtonsController.Visibility.NEVER);
|
||||
@ -346,6 +343,12 @@ public class GeofavoriteDetailActivity extends NextcloudMapsStyledActivity imple
|
||||
|
||||
public void updateViewCoords(Geofavorite item) {
|
||||
binding.coordsTv.setText(item.getCoordinatesString());
|
||||
binding.coordsTv.setOnClickListener((v) -> {
|
||||
ClipboardManager clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
|
||||
ClipData clip = ClipData.newPlainText(item.getCoordinatesString(), item.getCoordinatesString());
|
||||
clipboard.setPrimaryClip(clip);
|
||||
Toast.makeText(GeofavoriteDetailActivity.this, R.string.coords_copied, Toast.LENGTH_SHORT).show();
|
||||
});
|
||||
|
||||
// Center map
|
||||
GeoPoint position = new GeoPoint(item.getLat(), item.getLng());
|
||||
@ -378,7 +381,7 @@ public class GeofavoriteDetailActivity extends NextcloudMapsStyledActivity imple
|
||||
}
|
||||
|
||||
public void setCategories(HashSet<String> categories) {
|
||||
((CategoriesSpinnerAdapter)binding.categoryAt.getAdapter()).setCategoriesList(categories);
|
||||
((CategoriesAdapter)binding.categoryAt.getAdapter()).setCategoriesList(categories);
|
||||
}
|
||||
|
||||
public void hideAccuracy() {
|
||||
@ -413,9 +416,6 @@ public class GeofavoriteDetailActivity extends NextcloudMapsStyledActivity imple
|
||||
if (v.getId() == R.id.back_bt && this.listener != null) {
|
||||
this.listener.onBackPressed();
|
||||
}
|
||||
if (v.getId() == R.id.manual_pos_bt && this.listener != null) {
|
||||
this.listener.onMapEditPressed();
|
||||
}
|
||||
|
||||
// Actions
|
||||
if (v.getId() == R.id.action_icon_share && this.listener != null) {
|
||||
@ -434,7 +434,6 @@ public class GeofavoriteDetailActivity extends NextcloudMapsStyledActivity imple
|
||||
void onSubmit();
|
||||
void onMapClicked();
|
||||
void onBackPressed();
|
||||
void onMapEditPressed();
|
||||
void onActionIconShareClicked();
|
||||
void onActionIconNavClicked();
|
||||
void onActionIconDeleteClicked();
|
||||
|
@ -20,6 +20,8 @@ package it.danieleverducci.nextcloudmaps.activity.login;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
import android.widget.ProgressBar;
|
||||
@ -45,6 +47,7 @@ import it.danieleverducci.nextcloudmaps.api.API;
|
||||
import it.danieleverducci.nextcloudmaps.api.ApiProvider;
|
||||
|
||||
public class LoginActivity extends NextcloudMapsStyledActivity {
|
||||
private static final String TAG = "LoginActivity";
|
||||
|
||||
protected ProgressBar progress;
|
||||
protected Button button;
|
||||
@ -63,18 +66,25 @@ public class LoginActivity extends NextcloudMapsStyledActivity {
|
||||
openAccountChooser();
|
||||
});
|
||||
|
||||
Handler h = new Handler();
|
||||
h.post(() -> {
|
||||
try {
|
||||
ssoAccount = SingleAccountHelper.getCurrentSingleSignOnAccount(getApplicationContext());
|
||||
SingleAccountHelper.setCurrentAccount(getApplicationContext(), ssoAccount.name);
|
||||
SingleAccountHelper.applyCurrentAccount(getApplicationContext(), ssoAccount.name);
|
||||
accountAccessDone();
|
||||
} catch (NextcloudFilesAppAccountNotFoundException | NoCurrentAccountSelectedException e) {
|
||||
Log.e(TAG, "Autologin: " + e.toString());
|
||||
}
|
||||
});
|
||||
}
|
||||
private void openAccountChooser() {
|
||||
try {
|
||||
AccountImporter.pickNewAccount(this);
|
||||
} catch (NextcloudFilesAppNotInstalledException | AndroidGetAccountsPermissionNotGranted e) {
|
||||
UiExceptionManager.showDialogForException(this, e);
|
||||
|
||||
Log.e(TAG, "openAccountChooser: " + e.toString());
|
||||
progress.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
@ -98,7 +108,7 @@ public class LoginActivity extends NextcloudMapsStyledActivity {
|
||||
@Override
|
||||
public void accountAccessGranted(SingleSignOnAccount account) {
|
||||
Context l_context = getApplicationContext();
|
||||
SingleAccountHelper.setCurrentAccount(l_context, account.name);
|
||||
SingleAccountHelper.applyCurrentAccount(l_context, account.name);
|
||||
|
||||
accountAccessDone();
|
||||
}
|
||||
|
@ -28,8 +28,6 @@ import android.view.LayoutInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Filter;
|
||||
import android.widget.Filterable;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.PopupMenu;
|
||||
import android.widget.TextView;
|
||||
@ -42,14 +40,13 @@ import org.threeten.bp.format.DateTimeFormatter;
|
||||
import org.threeten.bp.format.FormatStyle;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import it.danieleverducci.nextcloudmaps.R;
|
||||
import it.danieleverducci.nextcloudmaps.model.Geofavorite;
|
||||
|
||||
public class GeofavoriteAdapter extends RecyclerView.Adapter<GeofavoriteAdapter.GeofavoriteViewHolder> implements Filterable {
|
||||
public class GeofavoriteAdapter extends RecyclerView.Adapter<GeofavoriteAdapter.GeofavoriteViewHolder> {
|
||||
|
||||
public static final String TAG = "GeofavoriteAdapter";
|
||||
|
||||
@ -58,12 +55,11 @@ public class GeofavoriteAdapter extends RecyclerView.Adapter<GeofavoriteAdapter.
|
||||
public static final int SORT_BY_CATEGORY = 2;
|
||||
public static final int SORT_BY_DISTANCE = 3;
|
||||
|
||||
private Context context;
|
||||
private ItemClickListener itemClickListener;
|
||||
private DateTimeFormatter dateFormatter = DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT);
|
||||
private final Context context;
|
||||
private final ItemClickListener itemClickListener;
|
||||
private final DateTimeFormatter dateFormatter = DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT);
|
||||
|
||||
private List<Geofavorite> geofavoriteList = new ArrayList<>();
|
||||
private List<Geofavorite> geofavoriteListFiltered = new ArrayList<>();
|
||||
private List<Geofavorite> items = new ArrayList<>();
|
||||
private int sortRule = SORT_BY_CREATED;
|
||||
|
||||
// Contains the position of the element containing the overflow menu clicked
|
||||
@ -75,15 +71,15 @@ public class GeofavoriteAdapter extends RecyclerView.Adapter<GeofavoriteAdapter.
|
||||
}
|
||||
|
||||
public void setGeofavoriteList(@NonNull List<Geofavorite> geofavoriteList) {
|
||||
this.geofavoriteList = geofavoriteList;
|
||||
this.geofavoriteListFiltered = new ArrayList<>(geofavoriteList);
|
||||
this.items.clear();
|
||||
this.items.addAll(geofavoriteList);
|
||||
|
||||
performSort();
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
public Geofavorite get(int position) {
|
||||
return geofavoriteListFiltered.get(position);
|
||||
return items.get(position);
|
||||
}
|
||||
|
||||
public int getSortRule() {
|
||||
@ -106,7 +102,7 @@ public class GeofavoriteAdapter extends RecyclerView.Adapter<GeofavoriteAdapter.
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull GeofavoriteViewHolder holder, int position) {
|
||||
Geofavorite geofavorite = geofavoriteListFiltered.get(position);
|
||||
Geofavorite geofavorite = items.get(position);
|
||||
|
||||
holder.tv_category.setText(geofavorite.categoryLetter());
|
||||
holder.setCategoryColor(
|
||||
@ -118,48 +114,9 @@ public class GeofavoriteAdapter extends RecyclerView.Adapter<GeofavoriteAdapter.
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return geofavoriteListFiltered.size();
|
||||
return items.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Filter getFilter() {
|
||||
return filter;
|
||||
}
|
||||
|
||||
Filter filter = new Filter() {
|
||||
@Override
|
||||
// Run on Background thread.
|
||||
protected FilterResults performFiltering(CharSequence charSequence) {
|
||||
FilterResults filterResults = new FilterResults();
|
||||
List <Geofavorite> filteredGeofavorites = new ArrayList<>();
|
||||
|
||||
if (charSequence.toString().isEmpty()) {
|
||||
filteredGeofavorites.addAll(geofavoriteList);
|
||||
} else {
|
||||
for (Geofavorite geofavorite : geofavoriteList) {
|
||||
String query = charSequence.toString().toLowerCase();
|
||||
if (geofavorite.getName() != null && geofavorite.getName().toLowerCase().contains(query)) {
|
||||
filteredGeofavorites.add(geofavorite);
|
||||
} else if (geofavorite.getComment() != null && geofavorite.getComment().toLowerCase().contains(query)) {
|
||||
filteredGeofavorites.add(geofavorite);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
filterResults.values = filteredGeofavorites;
|
||||
return filterResults;
|
||||
}
|
||||
//Run on ui thread
|
||||
@Override
|
||||
protected void publishResults(CharSequence charSequence, FilterResults filterResults) {
|
||||
geofavoriteListFiltered.clear();
|
||||
geofavoriteListFiltered.addAll((Collection<? extends Geofavorite>) filterResults.values);
|
||||
|
||||
performSort();
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
};
|
||||
|
||||
class GeofavoriteViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
|
||||
TextView tv_category, tv_title, tv_content, tv_date;
|
||||
ImageView bt_context_menu;
|
||||
@ -211,13 +168,13 @@ public class GeofavoriteAdapter extends RecyclerView.Adapter<GeofavoriteAdapter.
|
||||
|
||||
private void performSort() {
|
||||
if (sortRule == SORT_BY_TITLE) {
|
||||
Collections.sort(geofavoriteListFiltered, Geofavorite.ByTitleAZ);
|
||||
Collections.sort(items, Geofavorite.ByTitleAZ);
|
||||
} else if (sortRule == SORT_BY_CREATED) {
|
||||
Collections.sort(geofavoriteListFiltered, Geofavorite.ByLastCreated);
|
||||
Collections.sort(items, Geofavorite.ByLastCreated);
|
||||
} else if (sortRule == SORT_BY_CATEGORY) {
|
||||
Collections.sort(geofavoriteListFiltered, Geofavorite.ByCategory);
|
||||
Collections.sort(items, Geofavorite.ByCategory);
|
||||
} else if (sortRule == SORT_BY_DISTANCE) {
|
||||
Collections.sort(geofavoriteListFiltered, Geofavorite.ByDistance);
|
||||
Collections.sort(items, Geofavorite.ByDistance);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,15 +3,15 @@ package it.danieleverducci.nextcloudmaps.activity.main;
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.lifecycle.LiveData;
|
||||
import androidx.lifecycle.MutableLiveData;
|
||||
import androidx.lifecycle.ViewModel;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
|
||||
import it.danieleverducci.nextcloudmaps.model.Geofavorite;
|
||||
import it.danieleverducci.nextcloudmaps.repository.GeofavoriteRepository;
|
||||
|
||||
public class MainActivityViewModel extends ViewModel {
|
||||
public class GeofavoritesFragmentViewModel extends ViewModel {
|
||||
private GeofavoriteRepository mRepo;
|
||||
|
||||
public void init(Context applicationContext) {
|
||||
@ -27,6 +27,10 @@ public class MainActivityViewModel extends ViewModel {
|
||||
mRepo.updateGeofavorites();
|
||||
}
|
||||
|
||||
public LiveData<HashSet<String>> getCategories(){
|
||||
return mRepo.getCategories();
|
||||
}
|
||||
|
||||
public void deleteGeofavorite(Geofavorite geofav) {
|
||||
mRepo.deleteGeofavorite(geofav);
|
||||
}
|
@ -17,38 +17,25 @@
|
||||
|
||||
package it.danieleverducci.nextcloudmaps.activity.main;
|
||||
|
||||
import android.content.DialogInterface;
|
||||
import android.Manifest;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.Bundle;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.appcompat.widget.AppCompatImageButton;
|
||||
import androidx.appcompat.widget.AppCompatImageView;
|
||||
import androidx.appcompat.widget.SearchView;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.core.app.ActivityCompat;
|
||||
import androidx.core.view.GravityCompat;
|
||||
import androidx.drawerlayout.widget.DrawerLayout;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
import androidx.fragment.app.FragmentTransaction;
|
||||
import androidx.lifecycle.ViewModelProvider;
|
||||
import androidx.preference.PreferenceManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import androidx.recyclerview.widget.StaggeredGridLayoutManager;
|
||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
||||
|
||||
import com.google.android.material.card.MaterialCardView;
|
||||
import com.google.android.material.floatingactionbutton.FloatingActionButton;
|
||||
import com.nextcloud.android.sso.helper.SingleAccountHelper;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import it.danieleverducci.nextcloudmaps.R;
|
||||
import it.danieleverducci.nextcloudmaps.activity.NextcloudMapsStyledActivity;
|
||||
@ -56,124 +43,87 @@ 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.main.NavigationAdapter.NavigationItem;
|
||||
import it.danieleverducci.nextcloudmaps.activity.main.SortingOrderDialogFragment.OnSortingOrderListener;
|
||||
import it.danieleverducci.nextcloudmaps.activity.mappicker.MapPickerActivity;
|
||||
import it.danieleverducci.nextcloudmaps.api.ApiProvider;
|
||||
import it.danieleverducci.nextcloudmaps.model.Geofavorite;
|
||||
import it.danieleverducci.nextcloudmaps.utils.GeoUriParser;
|
||||
import it.danieleverducci.nextcloudmaps.utils.IntentGenerator;
|
||||
import it.danieleverducci.nextcloudmaps.fragments.GeofavoriteListFragment;
|
||||
import it.danieleverducci.nextcloudmaps.fragments.GeofavoriteMapFragment;
|
||||
import it.danieleverducci.nextcloudmaps.repository.GeofavoriteRepository;
|
||||
import it.danieleverducci.nextcloudmaps.utils.SettingsManager;
|
||||
|
||||
import static android.view.View.GONE;
|
||||
import static android.view.View.VISIBLE;
|
||||
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_TITLE;
|
||||
import androidx.lifecycle.Observer;
|
||||
|
||||
public class MainActivity extends NextcloudMapsStyledActivity implements OnSortingOrderListener {
|
||||
public class MainActivity extends NextcloudMapsStyledActivity {
|
||||
|
||||
private static final String TAG = "MainActivity";
|
||||
private static final int PERMISSION_REQUEST_CODE = 3890;
|
||||
|
||||
private static final String NAVIGATION_KEY_ADD_GEOFAVORITE_FROM_GPS = "add_from_gps";
|
||||
private static final String NAVIGATION_KEY_ADD_GEOFAVORITE_FROM_MAP = "add_from_map";
|
||||
private static final String NAVIGATION_KEY_SHOW_ABOUT = "about";
|
||||
private static final String NAVIGATION_KEY_SWITCH_ACCOUNT = "switch_account";
|
||||
|
||||
private SharedPreferences preferences;
|
||||
|
||||
private ArrayList<OnGpsPermissionGrantedListener> onGpsPermissionGrantedListener = new ArrayList<>();
|
||||
private DrawerLayout drawerLayout;
|
||||
private Toolbar toolbar;
|
||||
private MaterialCardView homeToolbar;
|
||||
private SearchView searchView;
|
||||
private SwipeRefreshLayout swipeRefresh;
|
||||
private RecyclerView recyclerView;
|
||||
private StaggeredGridLayoutManager layoutManager;
|
||||
private FloatingActionButton fab;
|
||||
|
||||
private GeofavoriteAdapter geofavoriteAdapter;
|
||||
private ItemClickListener rvItemClickListener;
|
||||
private MainActivityViewModel mMainActivityViewModel;
|
||||
|
||||
private boolean isFabOpen = false;
|
||||
|
||||
NavigationAdapter navigationCommonAdapter;
|
||||
|
||||
public void openDrawer() {
|
||||
drawerLayout.openDrawer(GravityCompat.START);
|
||||
}
|
||||
|
||||
public void showMap() {
|
||||
replaceFragment(new GeofavoriteMapFragment());
|
||||
SettingsManager.setGeofavoriteListShownAsMap(this, true);
|
||||
}
|
||||
|
||||
public void showList() {
|
||||
replaceFragment(new GeofavoriteListFragment());
|
||||
SettingsManager.setGeofavoriteListShownAsMap(this, false);
|
||||
}
|
||||
|
||||
public void addOnGpsPermissionGrantedListener(OnGpsPermissionGrantedListener l) {
|
||||
onGpsPermissionGrantedListener.add(l);
|
||||
}
|
||||
|
||||
public void removeOnGpsPermissionGrantedListener(OnGpsPermissionGrantedListener l) {
|
||||
onGpsPermissionGrantedListener.remove(l);
|
||||
}
|
||||
|
||||
public void requestGpsPermissions() {
|
||||
ActivityCompat.requestPermissions(
|
||||
this,
|
||||
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
|
||||
PERMISSION_REQUEST_CODE
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||
|
||||
if (requestCode == PERMISSION_REQUEST_CODE && permissions[0].equals(Manifest.permission.ACCESS_FINE_LOCATION)) {
|
||||
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
|
||||
for (OnGpsPermissionGrantedListener l : onGpsPermissionGrantedListener) {
|
||||
l.onGpsPermissionGranted();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_main);
|
||||
|
||||
preferences = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
|
||||
boolean showMap = SettingsManager.isGeofavoriteListShownAsMap(this);
|
||||
if (showMap)
|
||||
showMap();
|
||||
else
|
||||
showList();
|
||||
|
||||
int sortRule = preferences.getInt(getString(R.string.setting_sort_by), SORT_BY_CREATED);
|
||||
boolean gridViewEnabled = preferences.getBoolean(getString(R.string.setting_grid_view_enabled), false);
|
||||
|
||||
recyclerView = findViewById(R.id.recycler_view);
|
||||
layoutManager = new StaggeredGridLayoutManager(gridViewEnabled ? 2 : 1, StaggeredGridLayoutManager.VERTICAL);
|
||||
recyclerView.setLayoutManager(layoutManager);
|
||||
|
||||
rvItemClickListener = new ItemClickListener() {
|
||||
@Override
|
||||
public void onItemClick(Geofavorite item) {
|
||||
showGeofavoriteDetailActivity(item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onItemShareClick(Geofavorite item) {
|
||||
startActivity(Intent.createChooser(IntentGenerator.newShareIntent(MainActivity.this, item), getString(R.string.share_via)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onItemNavClick(Geofavorite item) {
|
||||
startActivity(IntentGenerator.newGeoUriIntent(MainActivity.this, item));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onItemDeleteClick(Geofavorite item) {
|
||||
showGeofavoriteDeteleDialog(item);
|
||||
}
|
||||
};
|
||||
|
||||
geofavoriteAdapter = new GeofavoriteAdapter(this, rvItemClickListener);
|
||||
recyclerView.setAdapter(geofavoriteAdapter);
|
||||
geofavoriteAdapter.setSortRule(sortRule);
|
||||
|
||||
|
||||
mMainActivityViewModel = new ViewModelProvider(this).get(MainActivityViewModel.class);
|
||||
mMainActivityViewModel.init(getApplicationContext());
|
||||
mMainActivityViewModel.getIsUpdating().observe(this, new Observer<Boolean>() {
|
||||
@Override
|
||||
public void onChanged(@Nullable Boolean aBoolean) {
|
||||
if(aBoolean){
|
||||
swipeRefresh.setRefreshing(true);
|
||||
}
|
||||
else{
|
||||
swipeRefresh.setRefreshing(false);
|
||||
}
|
||||
}
|
||||
});
|
||||
mMainActivityViewModel.getOnFinished().observe(this, new Observer<Boolean>() {
|
||||
@Override
|
||||
public void onChanged(@Nullable Boolean success) {
|
||||
if(success == null || !success){
|
||||
Toast.makeText(MainActivity.this, R.string.list_geofavorite_connection_error, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
}
|
||||
});
|
||||
mMainActivityViewModel.getGeofavorites().observe(this, new Observer<List<Geofavorite>>() {
|
||||
@Override
|
||||
public void onChanged(List<Geofavorite> geofavorites) {
|
||||
geofavoriteAdapter.setGeofavoriteList(geofavorites);
|
||||
}
|
||||
});
|
||||
mMainActivityViewModel.updateGeofavorites();
|
||||
|
||||
swipeRefresh = findViewById(R.id.swipe_refresh);
|
||||
swipeRefresh.setOnRefreshListener(() ->
|
||||
mMainActivityViewModel.updateGeofavorites());
|
||||
|
||||
fab = findViewById(R.id.open_fab);
|
||||
FloatingActionButton fab = findViewById(R.id.open_fab);
|
||||
fab.setOnClickListener(view -> openFab(!this.isFabOpen));
|
||||
|
||||
fab = findViewById(R.id.add_from_gps);
|
||||
@ -182,51 +132,9 @@ public class MainActivity extends NextcloudMapsStyledActivity implements OnSorti
|
||||
fab = findViewById(R.id.add_from_map);
|
||||
fab.setOnClickListener(view -> addGeofavoriteFromMap());
|
||||
|
||||
toolbar = findViewById(R.id.toolbar);
|
||||
homeToolbar = findViewById(R.id.home_toolbar);
|
||||
|
||||
searchView = findViewById(R.id.search_view);
|
||||
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
|
||||
@Override
|
||||
public boolean onQueryTextSubmit(String query) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onQueryTextChange(String query) {
|
||||
geofavoriteAdapter.getFilter().filter(query);
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
searchView.setOnCloseListener(() -> {
|
||||
if (toolbar.getVisibility() == VISIBLE && TextUtils.isEmpty(searchView.getQuery())) {
|
||||
updateToolbars(true);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
setSupportActionBar(toolbar);
|
||||
setupNavigationMenu();
|
||||
|
||||
homeToolbar.setOnClickListener(view -> updateToolbars(false));
|
||||
|
||||
AppCompatImageView sortButton = findViewById(R.id.sort_mode);
|
||||
sortButton.setOnClickListener(view -> openSortingOrderDialogFragment(getSupportFragmentManager(), geofavoriteAdapter.getSortRule()));
|
||||
|
||||
drawerLayout = findViewById(R.id.drawerLayout);
|
||||
AppCompatImageButton menuButton = findViewById(R.id.menu_button);
|
||||
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);
|
||||
updateGridIcon(gridViewEnabled);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -235,6 +143,13 @@ public class MainActivity extends NextcloudMapsStyledActivity implements OnSorti
|
||||
super.onPause();
|
||||
}
|
||||
|
||||
private void replaceFragment(Fragment fragment) {
|
||||
FragmentManager manager = getSupportFragmentManager();
|
||||
FragmentTransaction transaction = manager.beginTransaction();
|
||||
transaction.replace(R.id.fragment_container, fragment);
|
||||
transaction.commit();
|
||||
}
|
||||
|
||||
private void setupNavigationMenu() {
|
||||
ArrayList<NavigationItem> navItems = new ArrayList<>();
|
||||
|
||||
@ -265,22 +180,6 @@ public class MainActivity extends NextcloudMapsStyledActivity implements OnSorti
|
||||
navigationMenuCommon.setAdapter(navigationCommonAdapter);
|
||||
}
|
||||
|
||||
private void updateToolbars(boolean disableSearch) {
|
||||
homeToolbar.setVisibility(disableSearch ? VISIBLE : GONE);
|
||||
toolbar.setVisibility(disableSearch ? GONE : VISIBLE);
|
||||
if (disableSearch) {
|
||||
searchView.setQuery(null, true);
|
||||
}
|
||||
searchView.setIconified(disableSearch);
|
||||
}
|
||||
|
||||
private void openSortingOrderDialogFragment(FragmentManager supportFragmentManager, int sortOrder) {
|
||||
FragmentTransaction fragmentTransaction = supportFragmentManager.beginTransaction();
|
||||
fragmentTransaction.addToBackStack(null);
|
||||
|
||||
SortingOrderDialogFragment.newInstance(sortOrder).show(fragmentTransaction, SortingOrderDialogFragment.SORTING_ORDER_FRAGMENT);
|
||||
}
|
||||
|
||||
private void addGeofavoriteFromGps() {
|
||||
startActivity(
|
||||
new Intent(this, GeofavoriteDetailActivity.class)
|
||||
@ -297,77 +196,15 @@ public class MainActivity extends NextcloudMapsStyledActivity implements OnSorti
|
||||
startActivity(new Intent(this, AboutActivity.class));
|
||||
}
|
||||
|
||||
private void switch_account() {
|
||||
public void switch_account() {
|
||||
ApiProvider.logout();
|
||||
SingleAccountHelper.setCurrentAccount(this, null);
|
||||
GeofavoriteRepository.resetInstance();
|
||||
SingleAccountHelper.applyCurrentAccount(this, null);
|
||||
Intent intent = new Intent(MainActivity.this, LoginActivity.class);
|
||||
startActivity(intent);
|
||||
finish();
|
||||
}
|
||||
|
||||
@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) {
|
||||
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;
|
||||
case SORT_BY_CATEGORY:
|
||||
sortButton.setImageResource(R.drawable.ic_category_asc);
|
||||
break;
|
||||
case SORT_BY_DISTANCE:
|
||||
sortButton.setImageResource(R.drawable.ic_distance_asc);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void onGridIconChosen(boolean gridEnabled) {
|
||||
layoutManager.setSpanCount(gridEnabled ? 2 : 1);
|
||||
updateGridIcon(gridEnabled);
|
||||
|
||||
preferences.edit().putBoolean(getString(R.string.setting_grid_view_enabled), gridEnabled).apply();
|
||||
}
|
||||
|
||||
public void updateGridIcon(boolean gridEnabled) {
|
||||
AppCompatImageView viewButton = findViewById(R.id.view_mode);
|
||||
viewButton.setImageResource(gridEnabled ? R.drawable.ic_view_list : R.drawable.ic_view_module);
|
||||
}
|
||||
|
||||
private void showGeofavoriteDeteleDialog(Geofavorite item) {
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
|
||||
builder.setMessage(getString(R.string.dialog_delete_message).replace("{name}", item.getName() != null ? item.getName() : ""))
|
||||
.setTitle(R.string.dialog_delete_title)
|
||||
.setPositiveButton(R.string.dialog_delete_delete, new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int id) {
|
||||
mMainActivityViewModel.deleteGeofavorite(item);
|
||||
dialog.dismiss();
|
||||
}
|
||||
})
|
||||
.setNegativeButton(R.string.dialog_delete_cancel, new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int id) {
|
||||
dialog.dismiss();
|
||||
}
|
||||
});
|
||||
AlertDialog ad = builder.create();
|
||||
ad.show();
|
||||
}
|
||||
|
||||
private void showGeofavoriteDetailActivity(Geofavorite item) {
|
||||
Intent i = new Intent(this, GeofavoriteDetailActivity.class);
|
||||
i.putExtra(GeofavoriteDetailActivity.ARG_GEOFAVORITE, item.getId());
|
||||
startActivity(i);
|
||||
}
|
||||
|
||||
private void openFab(boolean open) {
|
||||
View fab = findViewById(R.id.open_fab);
|
||||
View addFromGpsFab = findViewById(R.id.add_from_gps);
|
||||
@ -387,4 +224,8 @@ public class MainActivity extends NextcloudMapsStyledActivity implements OnSorti
|
||||
|
||||
}
|
||||
|
||||
public interface OnGpsPermissionGrantedListener {
|
||||
public void onGpsPermissionGranted();
|
||||
}
|
||||
|
||||
}
|
@ -48,6 +48,7 @@ public class SortingOrderDialogFragment extends DialogFragment {
|
||||
public static final String SORTING_ORDER_FRAGMENT = "SORTING_ORDER_FRAGMENT";
|
||||
private static final String KEY_SORT_ORDER = "SORT_ORDER";
|
||||
|
||||
private OnSortingOrderListener onSortingOrderListener;
|
||||
private View mView;
|
||||
private View[] mTaggedViews;
|
||||
private Button mCancel;
|
||||
@ -90,6 +91,10 @@ public class SortingOrderDialogFragment extends DialogFragment {
|
||||
return mView;
|
||||
}
|
||||
|
||||
public void setOnSortingOrderListener(OnSortingOrderListener listener) {
|
||||
this.onSortingOrderListener = listener;
|
||||
}
|
||||
|
||||
/**
|
||||
* find all relevant UI elements and set their values.
|
||||
* TODO: this is REALLY ugly.
|
||||
@ -171,8 +176,8 @@ public class SortingOrderDialogFragment extends DialogFragment {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
dismissAllowingStateLoss();
|
||||
((SortingOrderDialogFragment.OnSortingOrderListener) getActivity())
|
||||
.onSortingOrderChosen((int) v.getTag());
|
||||
if (onSortingOrderListener != null)
|
||||
onSortingOrderListener.onSortingOrderChosen((int) v.getTag());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,153 @@
|
||||
package it.danieleverducci.nextcloudmaps.fragments;
|
||||
|
||||
import static it.danieleverducci.nextcloudmaps.activity.main.GeofavoriteAdapter.SORT_BY_CATEGORY;
|
||||
import static it.danieleverducci.nextcloudmaps.activity.main.GeofavoriteAdapter.SORT_BY_CREATED;
|
||||
import static it.danieleverducci.nextcloudmaps.activity.main.GeofavoriteAdapter.SORT_BY_DISTANCE;
|
||||
import static it.danieleverducci.nextcloudmaps.activity.main.GeofavoriteAdapter.SORT_BY_TITLE;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.widget.AppCompatImageView;
|
||||
import androidx.fragment.app.FragmentTransaction;
|
||||
import androidx.lifecycle.Observer;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import it.danieleverducci.nextcloudmaps.R;
|
||||
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.model.Geofavorite;
|
||||
import it.danieleverducci.nextcloudmaps.utils.GeofavoritesFilter;
|
||||
import it.danieleverducci.nextcloudmaps.utils.SettingsManager;
|
||||
|
||||
public class GeofavoriteListFragment extends GeofavoritesFragment implements SortingOrderDialogFragment.OnSortingOrderListener {
|
||||
|
||||
private SwipeRefreshLayout swipeRefresh;
|
||||
private GeofavoriteAdapter geofavoriteAdapter;
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
||||
View v = inflater.inflate(R.layout.fragment_geofavorite_list, container, false);
|
||||
|
||||
// Setup list
|
||||
int sortRule = SettingsManager.getGeofavoriteListSortBy(requireContext());
|
||||
|
||||
RecyclerView recyclerView = v.findViewById(R.id.recycler_view);
|
||||
LinearLayoutManager layoutManager = new LinearLayoutManager(requireContext());
|
||||
recyclerView.setLayoutManager(layoutManager);
|
||||
|
||||
GeofavoriteAdapter.ItemClickListener rvItemClickListener = new GeofavoriteAdapter.ItemClickListener() {
|
||||
@Override
|
||||
public void onItemClick(Geofavorite item) {
|
||||
openGeofavorite(item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onItemShareClick(Geofavorite item) {
|
||||
shareGeofavorite(item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onItemNavClick(Geofavorite item) {
|
||||
navigateToGeofavorite(item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onItemDeleteClick(Geofavorite item) {
|
||||
deleteGeofavorite(item);
|
||||
}
|
||||
};
|
||||
|
||||
geofavoriteAdapter = new GeofavoriteAdapter(requireContext(), rvItemClickListener);
|
||||
recyclerView.setAdapter(geofavoriteAdapter);
|
||||
geofavoriteAdapter.setSortRule(sortRule);
|
||||
|
||||
// Register for data source events
|
||||
mGeofavoritesFragmentViewModel.getIsUpdating().observe(getViewLifecycleOwner(), new Observer<Boolean>() {
|
||||
@Override
|
||||
public void onChanged(@Nullable Boolean changed) {
|
||||
if(Boolean.TRUE.equals(changed)){
|
||||
swipeRefresh.setRefreshing(true);
|
||||
}
|
||||
else{
|
||||
swipeRefresh.setRefreshing(false);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Setup view listeners
|
||||
swipeRefresh = v.findViewById(R.id.swipe_refresh);
|
||||
swipeRefresh.setOnRefreshListener(() ->
|
||||
mGeofavoritesFragmentViewModel.updateGeofavorites());
|
||||
|
||||
AppCompatImageView sortButton = v.findViewById(R.id.sort_mode);
|
||||
sortButton.setOnClickListener(view -> openSortingOrderDialogFragment(geofavoriteAdapter.getSortRule()));
|
||||
|
||||
View showMapButton = v.findViewById(R.id.view_mode_map);
|
||||
showMapButton.setOnClickListener(View -> ((MainActivity)requireActivity()).showMap());
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
|
||||
// Set icons
|
||||
int sortRule = SettingsManager.getGeofavoriteListSortBy(requireContext());
|
||||
updateSortingIcon(sortRule);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDatasetChange(List<Geofavorite> items) {
|
||||
// Called when the items are loaded or a filtering happens
|
||||
geofavoriteAdapter.setGeofavoriteList(items);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSortingOrderChosen(int sortSelection) {
|
||||
geofavoriteAdapter.setSortRule(sortSelection);
|
||||
updateSortingIcon(sortSelection);
|
||||
|
||||
SettingsManager.setGeofavoriteListSortBy(requireContext(), sortSelection);
|
||||
}
|
||||
|
||||
private void openSortingOrderDialogFragment(int sortOrder) {
|
||||
FragmentTransaction fragmentTransaction = requireActivity().getSupportFragmentManager().beginTransaction();
|
||||
fragmentTransaction.addToBackStack(null);
|
||||
|
||||
SortingOrderDialogFragment sodf = SortingOrderDialogFragment.newInstance(sortOrder);
|
||||
sodf.setOnSortingOrderListener(this);
|
||||
sodf.show(fragmentTransaction, SortingOrderDialogFragment.SORTING_ORDER_FRAGMENT);
|
||||
}
|
||||
|
||||
private void updateSortingIcon(int sortSelection) {
|
||||
AppCompatImageView sortButton = requireView().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;
|
||||
case SORT_BY_CATEGORY:
|
||||
sortButton.setImageResource(R.drawable.ic_category_asc);
|
||||
break;
|
||||
case SORT_BY_DISTANCE:
|
||||
sortButton.setImageResource(R.drawable.ic_distance_asc);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,240 @@
|
||||
package it.danieleverducci.nextcloudmaps.fragments;
|
||||
|
||||
import android.Manifest;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.content.res.AppCompatResources;
|
||||
import androidx.core.app.ActivityCompat;
|
||||
import androidx.core.content.res.ResourcesCompat;
|
||||
import androidx.core.graphics.drawable.DrawableCompat;
|
||||
import androidx.lifecycle.Observer;
|
||||
|
||||
import org.osmdroid.api.IMapController;
|
||||
import org.osmdroid.events.MapEventsReceiver;
|
||||
import org.osmdroid.util.GeoPoint;
|
||||
import org.osmdroid.views.CustomZoomButtonsController;
|
||||
import org.osmdroid.views.MapView;
|
||||
import org.osmdroid.views.overlay.MapEventsOverlay;
|
||||
import org.osmdroid.views.overlay.Marker;
|
||||
import org.osmdroid.views.overlay.Overlay;
|
||||
import org.osmdroid.views.overlay.infowindow.InfoWindow;
|
||||
import org.osmdroid.views.overlay.mylocation.GpsMyLocationProvider;
|
||||
import org.osmdroid.views.overlay.mylocation.MyLocationNewOverlay;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import it.danieleverducci.nextcloudmaps.R;
|
||||
import it.danieleverducci.nextcloudmaps.activity.detail.GeofavoriteDetailActivity;
|
||||
import it.danieleverducci.nextcloudmaps.activity.main.MainActivity;
|
||||
import it.danieleverducci.nextcloudmaps.activity.mappicker.MapPickerActivity;
|
||||
import it.danieleverducci.nextcloudmaps.model.Geofavorite;
|
||||
import it.danieleverducci.nextcloudmaps.utils.GeoUriParser;
|
||||
import it.danieleverducci.nextcloudmaps.utils.MapUtils;
|
||||
import it.danieleverducci.nextcloudmaps.utils.SettingsManager;
|
||||
import it.danieleverducci.nextcloudmaps.views.GeofavMarkerInfoWindow;
|
||||
|
||||
public class GeofavoriteMapFragment extends GeofavoritesFragment implements MainActivity.OnGpsPermissionGrantedListener {
|
||||
|
||||
private MapView map;
|
||||
private MyLocationNewOverlay mLocationOverlay;
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
MapUtils.configOsmdroid(requireContext());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
||||
View v = inflater.inflate(R.layout.fragment_geofavorite_map, container, false);
|
||||
|
||||
// Register listeners
|
||||
v.findViewById(R.id.center_position).setOnClickListener((cpv) -> moveToUserPosition());
|
||||
|
||||
// Setup map
|
||||
map = v.findViewById(R.id.map);
|
||||
map.getZoomController().setVisibility(CustomZoomButtonsController.Visibility.NEVER);
|
||||
map.setMultiTouchControls(true);
|
||||
MapUtils.setTheme(map);
|
||||
MapEventsOverlay meo = new MapEventsOverlay(new MapEventsReceiver() {
|
||||
@Override
|
||||
public boolean singleTapConfirmedHelper(GeoPoint p) {
|
||||
InfoWindow.closeAllInfoWindowsOn(map);
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean longPressHelper(GeoPoint p) {
|
||||
// Create new geofavorite (go to geofav creation activity)
|
||||
Uri geoUri = GeoUriParser.createGeoUri(p.getLatitude(), p.getLongitude(), null);
|
||||
Intent i = new Intent(requireActivity(), GeofavoriteDetailActivity.class);
|
||||
i.setData(geoUri);
|
||||
startActivity(i);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
map.getOverlays().add(0, meo);
|
||||
showUserPosition();
|
||||
|
||||
// Setup view listeners
|
||||
View showListButton = v.findViewById(R.id.view_mode_list);
|
||||
showListButton.setOnClickListener(View -> ((MainActivity)requireActivity()).showList());
|
||||
|
||||
View loadingWall = v.findViewById(R.id.loading_wall);
|
||||
|
||||
// Register for data source events
|
||||
mGeofavoritesFragmentViewModel.getIsUpdating().observe(getViewLifecycleOwner(), new Observer<Boolean>() {
|
||||
@Override
|
||||
public void onChanged(@Nullable Boolean changed) {
|
||||
if(Boolean.TRUE.equals(changed)){
|
||||
loadingWall.setVisibility(View.VISIBLE);
|
||||
}
|
||||
else{
|
||||
loadingWall.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
|
||||
((MainActivity)requireActivity()).addOnGpsPermissionGrantedListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDatasetChange(List<Geofavorite> items) {
|
||||
clearAllMarkers();
|
||||
for(Geofavorite gf : items)
|
||||
addMarker(gf);
|
||||
map.invalidate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStop() {
|
||||
super.onStop();
|
||||
|
||||
((MainActivity)requireActivity()).removeOnGpsPermissionGrantedListener(this);
|
||||
SettingsManager.setLastMapPosition(
|
||||
requireContext(),
|
||||
map.getMapCenter().getLatitude(),
|
||||
map.getMapCenter().getLongitude(),
|
||||
map.getZoomLevelDouble()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onGpsPermissionGranted() {
|
||||
showUserPosition();
|
||||
}
|
||||
|
||||
private void showUserPosition() {
|
||||
// Center map on last position
|
||||
double[] pos = SettingsManager.getLastMapPosition(requireContext());
|
||||
IMapController mapController = map.getController();
|
||||
mapController.setCenter(new GeoPoint(pos[0], pos[1]));
|
||||
mapController.setZoom(pos[2]);
|
||||
|
||||
// Check if user granted location permission
|
||||
if (ActivityCompat.checkSelfPermission(requireContext(), Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
|
||||
ActivityCompat.checkSelfPermission(requireContext(), Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED
|
||||
) {
|
||||
// User didn't grant permission. Ask it.
|
||||
((MainActivity)requireActivity()).requestGpsPermissions();
|
||||
return;
|
||||
}
|
||||
|
||||
// Display user position on screen
|
||||
mLocationOverlay = new MyLocationNewOverlay(new GpsMyLocationProvider(requireContext()), map);
|
||||
Bitmap personIcon = ((BitmapDrawable)AppCompatResources.getDrawable(requireContext(), R.mipmap.ic_person)).getBitmap();
|
||||
mLocationOverlay.setPersonIcon(personIcon);
|
||||
mLocationOverlay.setDirectionIcon(personIcon);
|
||||
mLocationOverlay.setPersonAnchor(.5f, .5f);
|
||||
mLocationOverlay.setDirectionAnchor(.5f, .5f);
|
||||
// On first gps fix, show "center to my position" icon
|
||||
mLocationOverlay.runOnFirstFix(() -> {
|
||||
if(getActivity() != null) {
|
||||
getActivity().runOnUiThread(() -> {
|
||||
getView().findViewById(R.id.center_position).setVisibility(View.VISIBLE);
|
||||
});
|
||||
}
|
||||
});
|
||||
mLocationOverlay.enableMyLocation();
|
||||
map.getOverlays().add(mLocationOverlay);
|
||||
}
|
||||
|
||||
void moveToUserPosition() {
|
||||
if (mLocationOverlay != null)
|
||||
map.getController().animateTo(mLocationOverlay.getMyLocation());
|
||||
}
|
||||
|
||||
private void addMarker(Geofavorite geofavorite){
|
||||
GeoPoint pos = new GeoPoint(geofavorite.getLat(), geofavorite.getLng());
|
||||
|
||||
// Set icon and color
|
||||
Drawable icon = DrawableCompat.wrap(AppCompatResources.getDrawable(requireContext(), R.drawable.ic_map_pin));
|
||||
DrawableCompat.setTint(icon, geofavorite.categoryColor() == 0 ? requireContext().getColor(R.color.defaultBrand) : geofavorite.categoryColor());
|
||||
|
||||
// Set infowindow (popup opened on marker click) and its listeners
|
||||
GeofavMarkerInfoWindow iw = new GeofavMarkerInfoWindow(map, geofavorite);
|
||||
iw.setOnGeofavMarkerInfoWindowClickListener(new GeofavMarkerInfoWindow.OnGeofavMarkerInfoWindowClickListener() {
|
||||
@Override
|
||||
public void onGeofavMarkerInfoWindowEditClick() {
|
||||
openGeofavorite(geofavorite);
|
||||
}
|
||||
@Override
|
||||
public void onGeofavMarkerInfoWindowShareClick() {
|
||||
shareGeofavorite(geofavorite);
|
||||
}
|
||||
@Override
|
||||
public void onGeofavMarkerInfoWindowNavClick() {
|
||||
navigateToGeofavorite(geofavorite);
|
||||
|
||||
}
|
||||
@Override
|
||||
public void onGeofavMarkerInfoWindowDeleteClick() {
|
||||
deleteGeofavorite(geofavorite);
|
||||
}
|
||||
});
|
||||
|
||||
// Set marker
|
||||
Marker m = new Marker(map);
|
||||
m.setPosition(pos);
|
||||
m.setAnchor(Marker.ANCHOR_CENTER, Marker.ANCHOR_BOTTOM);
|
||||
m.setIcon(icon);
|
||||
m.setTitle(geofavorite.getName());
|
||||
m.setSnippet(geofavorite.getComment());
|
||||
m.setSubDescription(geofavorite.getCategory());
|
||||
m.setInfoWindow(iw);
|
||||
map.getOverlays().add(m);
|
||||
}
|
||||
|
||||
private void clearAllMarkers() {
|
||||
// Close any open infowindow before removing related marker
|
||||
InfoWindow.closeAllInfoWindowsOn(map);
|
||||
// Remove all markers, leaving the other overlays (user position and tap listener ones)
|
||||
for(Overlay o : map.getOverlays()) {
|
||||
if (o instanceof Marker) {
|
||||
map.getOverlays().remove(o);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,270 @@
|
||||
package it.danieleverducci.nextcloudmaps.fragments;
|
||||
|
||||
import static android.view.View.GONE;
|
||||
import static android.view.View.VISIBLE;
|
||||
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.widget.ImageButton;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.appcompat.widget.AppCompatImageButton;
|
||||
import androidx.appcompat.widget.AppCompatImageView;
|
||||
import androidx.appcompat.widget.SearchView;
|
||||
import androidx.core.graphics.drawable.DrawableCompat;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.lifecycle.Observer;
|
||||
import androidx.lifecycle.ViewModelProvider;
|
||||
import com.nextcloud.android.sso.helper.SingleAccountHelper;
|
||||
import com.nextcloud.android.sso.model.SingleSignOnAccount;
|
||||
import com.squareup.picasso.Picasso;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
|
||||
import it.danieleverducci.nextcloudmaps.R;
|
||||
import it.danieleverducci.nextcloudmaps.activity.detail.CategoriesAdapter;
|
||||
import it.danieleverducci.nextcloudmaps.activity.detail.GeofavoriteDetailActivity;
|
||||
import it.danieleverducci.nextcloudmaps.activity.main.GeofavoritesFragmentViewModel;
|
||||
import it.danieleverducci.nextcloudmaps.activity.main.MainActivity;
|
||||
import it.danieleverducci.nextcloudmaps.model.Geofavorite;
|
||||
import it.danieleverducci.nextcloudmaps.utils.GeofavoritesFilter;
|
||||
import it.danieleverducci.nextcloudmaps.utils.IntentGenerator;
|
||||
|
||||
/**
|
||||
* Separates the specific list/map implementation details providing a standard interface
|
||||
* to communicate with the activity
|
||||
*/
|
||||
public abstract class GeofavoritesFragment extends Fragment {
|
||||
private final String TAG = "GeofavoritesFragment";
|
||||
|
||||
protected GeofavoritesFragmentViewModel mGeofavoritesFragmentViewModel;
|
||||
private View toolbar;
|
||||
private View homeToolbar;
|
||||
private SearchView searchView;
|
||||
private ImageButton filterButton;
|
||||
private List<Geofavorite> geofavorites = new ArrayList<>();
|
||||
private HashSet<String> categories = new HashSet<>();
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
// Load data
|
||||
mGeofavoritesFragmentViewModel = new ViewModelProvider(this).get(GeofavoritesFragmentViewModel.class);
|
||||
mGeofavoritesFragmentViewModel.init(requireContext());
|
||||
|
||||
mGeofavoritesFragmentViewModel.getOnFinished().observe(this, new Observer<Boolean>() {
|
||||
@Override
|
||||
public void onChanged(@Nullable Boolean success) {
|
||||
if(success == null || !success){
|
||||
Toast.makeText(requireContext(), R.string.list_geofavorite_connection_error, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
|
||||
// Set views
|
||||
AppCompatImageButton menuButton = view.findViewById(R.id.menu_button);
|
||||
menuButton.setOnClickListener(v -> ((MainActivity)requireActivity()).openDrawer());
|
||||
|
||||
View userBadgeContainer = view.findViewById(R.id.user_badge_container);
|
||||
userBadgeContainer.setOnClickListener(v -> showSwitchAccountDialog());
|
||||
|
||||
// Setup toolbar/searchbar
|
||||
toolbar = view.findViewById(R.id.toolbar);
|
||||
homeToolbar = view.findViewById(R.id.home_toolbar);
|
||||
filterButton = view.findViewById(R.id.search_filter);
|
||||
filterButton.setOnClickListener(v -> showCategoryFilterDialog());
|
||||
|
||||
searchView = view.findViewById(R.id.search_view);
|
||||
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
|
||||
@Override
|
||||
public boolean onQueryTextSubmit(String query) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onQueryTextChange(String query) {
|
||||
onDatasetChange(
|
||||
(new GeofavoritesFilter(geofavorites)).byText(query)
|
||||
);
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
mGeofavoritesFragmentViewModel.getGeofavorites().observe(getViewLifecycleOwner(), new Observer<List<Geofavorite>>() {
|
||||
@Override
|
||||
public void onChanged(List<Geofavorite> geofavorites) {
|
||||
GeofavoritesFragment.this.geofavorites = geofavorites;
|
||||
onDatasetChange(geofavorites);
|
||||
}
|
||||
});
|
||||
mGeofavoritesFragmentViewModel.getCategories().observe(getViewLifecycleOwner(), new Observer<HashSet<String>>() {
|
||||
@Override
|
||||
public void onChanged(HashSet<String> categories) {
|
||||
GeofavoritesFragment.this.categories = categories;
|
||||
}
|
||||
});
|
||||
|
||||
searchView.setOnCloseListener(() -> {
|
||||
if (toolbar.getVisibility() == VISIBLE && TextUtils.isEmpty(searchView.getQuery())) {
|
||||
updateToolbars(true);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
homeToolbar.setOnClickListener(v -> updateToolbars(false));
|
||||
// Set user badge (async)
|
||||
Handler h = new Handler();
|
||||
h.post(() -> {
|
||||
try {
|
||||
SingleSignOnAccount ssoAccount = SingleAccountHelper.getCurrentSingleSignOnAccount(requireContext());
|
||||
String userBadgePath = ssoAccount.url + "/index.php/avatar/" + ssoAccount.userId + "/64";
|
||||
if (getActivity() != null)
|
||||
getActivity().runOnUiThread(
|
||||
() -> Picasso.get().load(userBadgePath).into((AppCompatImageView)userBadgeContainer.findViewById(R.id.user_badge))
|
||||
);
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Unable to load user image: " + e.toString());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
|
||||
// Reset filter and update data
|
||||
filterButton.setImageResource(R.drawable.ic_filter_off);
|
||||
mGeofavoritesFragmentViewModel.updateGeofavorites();
|
||||
}
|
||||
|
||||
|
||||
abstract public void onDatasetChange(List<Geofavorite> items);
|
||||
|
||||
|
||||
protected void openGeofavorite(Geofavorite item) {
|
||||
showGeofavoriteDetailActivity(item);
|
||||
}
|
||||
|
||||
protected void shareGeofavorite(Geofavorite item) {
|
||||
startActivity(Intent.createChooser(IntentGenerator.newShareIntent(requireActivity(), item), getString(R.string.share_via)));
|
||||
}
|
||||
|
||||
protected void navigateToGeofavorite(Geofavorite item) {
|
||||
startActivity(IntentGenerator.newGeoUriIntent(requireActivity(), item));
|
||||
}
|
||||
|
||||
protected void deleteGeofavorite(Geofavorite item) {
|
||||
showGeofavoriteDeteleDialog(item);
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void showGeofavoriteDetailActivity(Geofavorite item) {
|
||||
Intent i = new Intent(requireContext(), GeofavoriteDetailActivity.class);
|
||||
i.putExtra(GeofavoriteDetailActivity.ARG_GEOFAVORITE, item.getId());
|
||||
startActivity(i);
|
||||
}
|
||||
|
||||
private void showGeofavoriteDeteleDialog(Geofavorite item) {
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(requireContext());
|
||||
builder.setMessage(getString(R.string.dialog_delete_message).replace("{name}", item.getName() != null ? item.getName() : ""))
|
||||
.setTitle(R.string.dialog_delete_title)
|
||||
.setPositiveButton(R.string.dialog_delete_delete, new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int id) {
|
||||
mGeofavoritesFragmentViewModel.deleteGeofavorite(item);
|
||||
dialog.dismiss();
|
||||
}
|
||||
})
|
||||
.setNegativeButton(R.string.dialog_delete_cancel, new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int id) {
|
||||
dialog.dismiss();
|
||||
}
|
||||
});
|
||||
AlertDialog ad = builder.create();
|
||||
ad.show();
|
||||
}
|
||||
|
||||
private void showSwitchAccountDialog() {
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(requireContext());
|
||||
builder.setMessage(R.string.dialog_logout_message)
|
||||
.setTitle(R.string.dialog_logout_title)
|
||||
.setPositiveButton(android.R.string.yes, (dialog, id) -> {
|
||||
if (getActivity() != null)
|
||||
((MainActivity) getActivity()).switch_account();
|
||||
dialog.dismiss();
|
||||
})
|
||||
.setNegativeButton(android.R.string.no, (dialog, id) -> dialog.dismiss());
|
||||
AlertDialog ad = builder.create();
|
||||
ad.show();
|
||||
}
|
||||
|
||||
private void showCategoryFilterDialog() {
|
||||
if (categories.isEmpty()) {
|
||||
Toast.makeText(requireContext(), R.string.filtering_unavailable, Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(requireContext());
|
||||
builder.setTitle(R.string.filtering_dialog_title);
|
||||
CategoriesAdapter ca = new CategoriesAdapter(requireContext());
|
||||
ca.setCategoriesList(categories);
|
||||
builder.setAdapter(ca, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
// Set filter button enabled icon and color
|
||||
String categoryName = ca.getItem(which);
|
||||
filterButton.setImageResource(R.drawable.ic_filter);
|
||||
Drawable d = filterButton.getDrawable();
|
||||
DrawableCompat.setTint(
|
||||
d,
|
||||
Geofavorite.categoryColorFromName(categoryName) == 0
|
||||
? requireContext().getColor(R.color.defaultBrand)
|
||||
: Geofavorite.categoryColorFromName(categoryName)
|
||||
);
|
||||
filterByCategory(categoryName);
|
||||
}
|
||||
});
|
||||
|
||||
builder.setPositiveButton(R.string.filtering_dialog_cancel, (dialog, id) -> {
|
||||
dialog.dismiss();
|
||||
filterButton.setImageResource(R.drawable.ic_filter_off);
|
||||
filterByCategory(null);
|
||||
});
|
||||
AlertDialog dialog = builder.create();
|
||||
dialog.show();
|
||||
}
|
||||
|
||||
private void updateToolbars(boolean disableSearch) {
|
||||
homeToolbar.setVisibility(disableSearch ? VISIBLE : GONE);
|
||||
toolbar.setVisibility(disableSearch ? GONE : VISIBLE);
|
||||
if (disableSearch) {
|
||||
searchView.setQuery(null, true);
|
||||
}
|
||||
searchView.setIconified(disableSearch);
|
||||
}
|
||||
|
||||
private void filterByCategory(String category) {
|
||||
onDatasetChange(
|
||||
(new GeofavoritesFilter(geofavorites)).byCategory(category)
|
||||
);
|
||||
}
|
||||
|
||||
}
|
@ -22,6 +22,7 @@ package it.danieleverducci.nextcloudmaps.model;
|
||||
|
||||
import android.graphics.Color;
|
||||
import android.net.Uri;
|
||||
import android.widget.Filter;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
@ -34,7 +35,9 @@ import org.threeten.bp.LocalDate;
|
||||
import org.threeten.bp.ZoneId;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
import it.danieleverducci.nextcloudmaps.utils.GeoUriParser;
|
||||
|
||||
@ -201,17 +204,7 @@ public class Geofavorite implements Serializable {
|
||||
* @return the generated color or null for the default category
|
||||
*/
|
||||
public int categoryColor() {
|
||||
// If category is default, return null: will be used Nextcloud's accent
|
||||
if (this.category == null || this.category.equals(DEFAULT_CATEGORY) || this.category.length() == 0)
|
||||
return 0;
|
||||
|
||||
float letter1Index = this.category.toLowerCase().charAt(0);
|
||||
float letter2Index = this.category.toLowerCase().charAt(1);
|
||||
float letterCoef = ((letter1Index * letter2Index) % 100) / 100;
|
||||
float h = letterCoef * 360;
|
||||
float s = 75 + letterCoef * 10;
|
||||
float l = 50 + letterCoef * 10;
|
||||
return Color.HSVToColor( new float[]{ Math.round(h), Math.round(s), Math.round(l) });
|
||||
return categoryColorFromName(this.category);
|
||||
}
|
||||
|
||||
public String categoryLetter() {
|
||||
@ -226,4 +219,27 @@ public class Geofavorite implements Serializable {
|
||||
return "[" + getName() + " (" + getLat() + "," + getLng() + ")]";
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Based on Nextcloud Maps's getLetterColor util.
|
||||
* Assigns a color to a category based on its two first letters.
|
||||
*
|
||||
* @see "https://github.com/nextcloud/maps/blob/master/src/utils.js"
|
||||
* @return the generated color or null for the default category
|
||||
*/
|
||||
public static int categoryColorFromName(String category) {
|
||||
// If category is default, return null: will be used Nextcloud's accent
|
||||
if (category == null || category.equals(DEFAULT_CATEGORY) || category.length() == 0)
|
||||
return 0;
|
||||
|
||||
float letter1Index = category.toLowerCase().charAt(0);
|
||||
float letter2Index = category.toLowerCase().charAt(1);
|
||||
float letterCoef = ((letter1Index * letter2Index) % 100) / 100;
|
||||
float h = letterCoef * 360;
|
||||
float s = 75 + letterCoef * 10;
|
||||
float l = 50 + letterCoef * 10;
|
||||
return Color.HSVToColor( new float[]{ Math.round(h), Math.round(s), Math.round(l) });
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -42,6 +42,10 @@ public class GeofavoriteRepository {
|
||||
return instance;
|
||||
}
|
||||
|
||||
public static void resetInstance() {
|
||||
instance = null;
|
||||
}
|
||||
|
||||
public MutableLiveData<List<Geofavorite>> getGeofavorites(){
|
||||
if (mGeofavorites == null) {
|
||||
mGeofavorites = new MutableLiveData<>();
|
||||
|
@ -0,0 +1,47 @@
|
||||
package it.danieleverducci.nextcloudmaps.utils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import it.danieleverducci.nextcloudmaps.model.Geofavorite;
|
||||
|
||||
public class GeofavoritesFilter {
|
||||
List<Geofavorite> items;
|
||||
public GeofavoritesFilter(List<Geofavorite> items) {
|
||||
this.items = items;
|
||||
}
|
||||
|
||||
public List<Geofavorite> byText(String text) {
|
||||
List<Geofavorite> filteredGeofavorites = new ArrayList<>();
|
||||
|
||||
if (text.isEmpty()) {
|
||||
return items;
|
||||
} else {
|
||||
for (Geofavorite geofavorite : items) {
|
||||
String query = text.toLowerCase();
|
||||
if (geofavorite.getName() != null && geofavorite.getName().toLowerCase().contains(query)) {
|
||||
filteredGeofavorites.add(geofavorite);
|
||||
} else if (geofavorite.getComment() != null && geofavorite.getComment().toLowerCase().contains(query)) {
|
||||
filteredGeofavorites.add(geofavorite);
|
||||
}
|
||||
}
|
||||
}
|
||||
return filteredGeofavorites;
|
||||
}
|
||||
|
||||
public List<Geofavorite> byCategory(String category) {
|
||||
List<Geofavorite> filteredGeofavorites = new ArrayList<>();
|
||||
|
||||
if (category == null) {
|
||||
return items;
|
||||
} else {
|
||||
for (Geofavorite geofavorite : items) {
|
||||
if (geofavorite.getCategory().equals(category)) {
|
||||
filteredGeofavorites.add(geofavorite);
|
||||
}
|
||||
}
|
||||
}
|
||||
return filteredGeofavorites;
|
||||
|
||||
}
|
||||
}
|
@ -14,6 +14,7 @@ public class IntentGenerator {
|
||||
i.setAction(Intent.ACTION_SEND);
|
||||
i.setType("text/plain");
|
||||
String shareMessage = context.getString(R.string.share_message)
|
||||
.replace("{title}", item.getName() == null ? context.getString(R.string.share_message_default_title) : item.getName())
|
||||
.replace("{lat}", ""+item.getLat())
|
||||
.replace("{lng}", ""+item.getLng());
|
||||
i.putExtra(Intent.EXTRA_TEXT, shareMessage );
|
||||
|
@ -0,0 +1,57 @@
|
||||
package it.danieleverducci.nextcloudmaps.utils;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
|
||||
import androidx.preference.PreferenceManager;
|
||||
import it.danieleverducci.nextcloudmaps.activity.main.GeofavoriteAdapter;
|
||||
|
||||
public class SettingsManager {
|
||||
static private final String SETTING_SORT_BY = "SETTING_SORT_BY";
|
||||
static private final String SETTING_LAST_SELECTED_LIST_VIEW = "SETTING_LAST_SELECTED_LIST_VIEW";
|
||||
static private final String SETTING_LAST_MAP_POSITION_LAT = "SETTING_LAST_MAP_POSITION_LAT";
|
||||
static private final String SETTING_LAST_MAP_POSITION_LNG = "SETTING_LAST_MAP_POSITION_LNG";
|
||||
static private final String SETTING_LAST_MAP_POSITION_ZOOM = "SETTING_LAST_MAP_POSITION_ZOOM";
|
||||
|
||||
public static int getGeofavoriteListSortBy(Context context) {
|
||||
return PreferenceManager.getDefaultSharedPreferences(context)
|
||||
.getInt(SETTING_SORT_BY, GeofavoriteAdapter.SORT_BY_CREATED);
|
||||
}
|
||||
|
||||
public static void setGeofavoriteListSortBy(Context context, int value) {
|
||||
PreferenceManager.getDefaultSharedPreferences(context)
|
||||
.edit().putInt(SETTING_SORT_BY, value).apply();
|
||||
}
|
||||
|
||||
public static boolean isGeofavoriteListShownAsMap(Context context) {
|
||||
return PreferenceManager.getDefaultSharedPreferences(context)
|
||||
.getBoolean(SETTING_LAST_SELECTED_LIST_VIEW, false);
|
||||
}
|
||||
|
||||
public static void setGeofavoriteListShownAsMap(Context context, boolean value) {
|
||||
PreferenceManager.getDefaultSharedPreferences(context)
|
||||
.edit().putBoolean(SETTING_LAST_SELECTED_LIST_VIEW, value).apply();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the last saved position
|
||||
* @param context
|
||||
* @return double[lat,lng,zoom]
|
||||
*/
|
||||
public static double[] getLastMapPosition(Context context) {
|
||||
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
return new double[] {
|
||||
(double) sp.getFloat(SETTING_LAST_MAP_POSITION_LAT, 0.0f),
|
||||
(double) sp.getFloat(SETTING_LAST_MAP_POSITION_LNG, 0.0f),
|
||||
(double) sp.getFloat(SETTING_LAST_MAP_POSITION_ZOOM, 10.0f),
|
||||
};
|
||||
}
|
||||
|
||||
public static void setLastMapPosition(Context context, double lat, double lng, double zoom) {
|
||||
PreferenceManager.getDefaultSharedPreferences(context).edit()
|
||||
.putFloat(SETTING_LAST_MAP_POSITION_LAT, (float)lat)
|
||||
.putFloat(SETTING_LAST_MAP_POSITION_LNG, (float)lng)
|
||||
.putFloat(SETTING_LAST_MAP_POSITION_ZOOM, (float)zoom)
|
||||
.apply();
|
||||
}
|
||||
}
|
@ -0,0 +1,72 @@
|
||||
package it.danieleverducci.nextcloudmaps.views;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.appcompat.content.res.AppCompatResources;
|
||||
import androidx.core.graphics.drawable.DrawableCompat;
|
||||
|
||||
import org.osmdroid.views.MapView;
|
||||
import org.osmdroid.views.overlay.infowindow.InfoWindow;
|
||||
import org.osmdroid.views.overlay.infowindow.MarkerInfoWindow;
|
||||
|
||||
import it.danieleverducci.nextcloudmaps.R;
|
||||
import it.danieleverducci.nextcloudmaps.model.Geofavorite;
|
||||
|
||||
public class GeofavMarkerInfoWindow extends MarkerInfoWindow implements View.OnClickListener {
|
||||
private OnGeofavMarkerInfoWindowClickListener onGeofavMarkerInfoWindowClickListener;
|
||||
|
||||
public GeofavMarkerInfoWindow(MapView mapView, Geofavorite geofavorite) {
|
||||
super(R.layout.infowindow_geofav, mapView);
|
||||
Context context = getView().getContext();
|
||||
|
||||
// Set category color
|
||||
View category = getView().findViewById(R.id.bubble_subdescription);
|
||||
Drawable backgroundDrawable = category.getBackground();
|
||||
DrawableCompat.setTint(backgroundDrawable, geofavorite.categoryColor() == 0 ? context.getColor(R.color.defaultBrand) : geofavorite.categoryColor());
|
||||
|
||||
// Set listeners
|
||||
getView().findViewById(R.id.action_icon_share).setOnClickListener(this);
|
||||
getView().findViewById(R.id.action_icon_nav).setOnClickListener(this);
|
||||
getView().findViewById(R.id.action_icon_delete).setOnClickListener(this);
|
||||
getView().findViewById(R.id.action_icon_edit).setOnClickListener(this);
|
||||
}
|
||||
|
||||
public void setOnGeofavMarkerInfoWindowClickListener(OnGeofavMarkerInfoWindowClickListener l) {
|
||||
this.onGeofavMarkerInfoWindowClickListener = l;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onOpen(Object item) {
|
||||
InfoWindow.closeAllInfoWindowsOn(getMapView());
|
||||
super.onOpen(item);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (onGeofavMarkerInfoWindowClickListener == null)
|
||||
return;
|
||||
|
||||
if (v.getId() == R.id.action_icon_share)
|
||||
onGeofavMarkerInfoWindowClickListener.onGeofavMarkerInfoWindowShareClick();
|
||||
|
||||
if (v.getId() == R.id.action_icon_nav)
|
||||
onGeofavMarkerInfoWindowClickListener.onGeofavMarkerInfoWindowNavClick();
|
||||
|
||||
if (v.getId() == R.id.action_icon_delete)
|
||||
onGeofavMarkerInfoWindowClickListener.onGeofavMarkerInfoWindowDeleteClick();
|
||||
|
||||
if (v.getId() == R.id.action_icon_edit)
|
||||
onGeofavMarkerInfoWindowClickListener.onGeofavMarkerInfoWindowEditClick();
|
||||
}
|
||||
|
||||
|
||||
public interface OnGeofavMarkerInfoWindowClickListener {
|
||||
public void onGeofavMarkerInfoWindowEditClick();
|
||||
public void onGeofavMarkerInfoWindowShareClick();
|
||||
public void onGeofavMarkerInfoWindowNavClick();
|
||||
public void onGeofavMarkerInfoWindowDeleteClick();
|
||||
}
|
||||
}
|
@ -1,10 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item
|
||||
android:left="8dp"
|
||||
android:right="8dp"
|
||||
android:top="8dp"
|
||||
android:bottom="8dp">
|
||||
<item>
|
||||
<shape
|
||||
android:shape="oval">
|
||||
<solid android:color="@color/defaultBrandAlpha"/>
|
||||
|
13
app/src/main/res/drawable/geofav_infowindow_pointer.xml
Normal file
@ -0,0 +1,13 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="209.21dp"
|
||||
android:height="45.14dp"
|
||||
android:viewportWidth="209.21"
|
||||
android:viewportHeight="45.14">
|
||||
<path
|
||||
android:pathData="m204.31,0.14c-0.97,0.02 -2.1,0.07 -3.3,0.15l8.18,-0.01c0,0 -1.81,-0.2 -4.89,-0.14zM201.01,0.29 L0.02,0.46c0,0 32.67,5.29 57.83,17.7 25.15,12.42 45.33,26.81 45.33,26.81 0,0 18.75,-13.75 38.46,-26.28 20.46,-13 49.14,-17.73 59.37,-18.41z"
|
||||
android:strokeLineJoin="miter"
|
||||
android:strokeWidth="0.264583"
|
||||
android:fillColor="#000000"
|
||||
android:strokeColor="#00000000"
|
||||
android:strokeLineCap="butt"/>
|
||||
</vector>
|
@ -3,7 +3,7 @@
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
android:tint="?android:attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M20.94,11c-0.46,-4.17 -3.77,-7.48 -7.94,-7.94L13,1h-2v2.06c-1.13,0.12 -2.19,0.46 -3.16,0.97l1.5,1.5C10.16,5.19 11.06,5 12,5c3.87,0 7,3.13 7,7 0,0.94 -0.19,1.84 -0.52,2.65l1.5,1.5c0.5,-0.96 0.84,-2.02 0.97,-3.15L23,13v-2h-2.06zM3,4.27l2.04,2.04C3.97,7.62 3.25,9.23 3.06,11L1,11v2h2.06c0.46,4.17 3.77,7.48 7.94,7.94L11,23h2v-2.06c1.77,-0.2 3.38,-0.91 4.69,-1.98L19.73,21 21,19.73 4.27,3 3,4.27zM16.27,17.54C15.09,18.45 13.61,19 12,19c-3.87,0 -7,-3.13 -7,-7 0,-1.61 0.55,-3.09 1.46,-4.27l9.81,9.81z"/>
|
||||
|
@ -3,7 +3,7 @@
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
android:tint="?android:attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M12,8c-2.21,0 -4,1.79 -4,4s1.79,4 4,4 4,-1.79 4,-4 -1.79,-4 -4,-4zM20.94,11c-0.46,-4.17 -3.77,-7.48 -7.94,-7.94L13,1h-2v2.06C6.83,3.52 3.52,6.83 3.06,11L1,11v2h2.06c0.46,4.17 3.77,7.48 7.94,7.94L11,23h2v-2.06c4.17,-0.46 7.48,-3.77 7.94,-7.94L23,13v-2h-2.06zM12,19c-3.87,0 -7,-3.13 -7,-7s3.13,-7 7,-7 7,3.13 7,7 -3.13,7 -7,7z"/>
|
||||
|
@ -3,7 +3,7 @@
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
android:tint="?android:attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M12,2l-5.5,9h11z"/>
|
||||
|
5
app/src/main/res/drawable/ic_clear.xml
Normal file
@ -0,0 +1,5 @@
|
||||
<vector android:height="24dp" android:tint="#000000"
|
||||
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="M19,6.41L17.59,5 12,10.59 6.41,5 5,6.41 10.59,12 5,17.59 6.41,19 12,13.41 17.59,19 19,17.59 13.41,12z"/>
|
||||
</vector>
|
5
app/src/main/res/drawable/ic_copy.xml
Normal file
@ -0,0 +1,5 @@
|
||||
<vector android:height="24dp" android:tint="#000000"
|
||||
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="M16,1L4,1c-1.1,0 -2,0.9 -2,2v14h2L4,3h12L16,1zM19,5L8,5c-1.1,0 -2,0.9 -2,2v14c0,1.1 0.9,2 2,2h11c1.1,0 2,-0.9 2,-2L21,7c0,-1.1 -0.9,-2 -2,-2zM19,21L8,21L8,7h11v14z"/>
|
||||
</vector>
|
@ -3,7 +3,7 @@
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
android:tint="?android:attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M21,3L3,10.53v0.98l6.84,2.65L12.48,21h0.98L21,3z"/>
|
||||
|
5
app/src/main/res/drawable/ic_filter.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="M4.25,5.61C6.27,8.2 10,13 10,13v6c0,0.55 0.45,1 1,1h2c0.55,0 1,-0.45 1,-1v-6c0,0 3.72,-4.8 5.74,-7.39C20.25,4.95 19.78,4 18.95,4H5.04C4.21,4 3.74,4.95 4.25,5.61z"/>
|
||||
</vector>
|
6
app/src/main/res/drawable/ic_filter_off.xml
Normal file
@ -0,0 +1,6 @@
|
||||
<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="M19.79,5.61C20.3,4.95 19.83,4 19,4H6.83l7.97,7.97L19.79,5.61z"/>
|
||||
<path android:fillColor="@android:color/white" android:pathData="M2.81,2.81L1.39,4.22L10,13v6c0,0.55 0.45,1 1,1h2c0.55,0 1,-0.45 1,-1v-2.17l5.78,5.78l1.41,-1.41L2.81,2.81z"/>
|
||||
</vector>
|
@ -1,16 +0,0 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M13.95,13H9V8.05l5.61,-5.61C13.78,2.16 12.9,2 12,2c-4.2,0 -8,3.22 -8,8.2c0,3.32 2.67,7.25 8,11.8c5.33,-4.55 8,-8.48 8,-11.8c0,-1.01 -0.16,-1.94 -0.45,-2.8L13.95,13z"/>
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M11,11l2.12,0l6.16,-6.16l-2.12,-2.12l-6.16,6.16z"/>
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M20.71,2L20,1.29C19.8,1.1 19.55,1 19.29,1c-0.13,0 -0.48,0.07 -0.71,0.29l-0.72,0.72l2.12,2.12l0.72,-0.72C21.1,3.02 21.1,2.39 20.71,2z"/>
|
||||
</vector>
|
@ -3,7 +3,7 @@
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
android:tint="?android:attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M9,16.17L4.83,12l-1.42,1.41L9,19 21,7l-1.41,-1.41z"/>
|
||||
|
5
app/src/main/res/drawable/ic_view_map.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="M20.5,3l-0.16,0.03L15,5.1 9,3 3.36,4.9c-0.21,0.07 -0.36,0.25 -0.36,0.48V20.5c0,0.28 0.22,0.5 0.5,0.5l0.16,-0.03L9,18.9l6,2.1 5.64,-1.9c0.21,-0.07 0.36,-0.25 0.36,-0.48V3.5c0,-0.28 -0.22,-0.5 -0.5,-0.5zM15,19l-6,-2.11V5l6,2.11V19z"/>
|
||||
</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>
|
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="@color/defaultBackground"/>
|
||||
<stroke android:width="7dp" android:color="@color/defaultBrand" />
|
||||
<corners android:radius="20dp"/>
|
||||
</shape>
|
6
app/src/main/res/drawable/rounded_label_background.xml
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="#000" />
|
||||
<padding android:left="10dp" android:top="3dp" android:right="10dp" android:bottom="3dp" />
|
||||
<corners android:radius="20dp" />
|
||||
</shape>
|
@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item>
|
||||
<shape
|
||||
android:shape="oval">
|
||||
<solid android:color="@color/translucent"/>
|
||||
</shape>
|
||||
</item>
|
||||
</layer-list>
|
15
app/src/main/res/drawable/user_badge_mask.xml
Normal file
@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<item>
|
||||
<shape
|
||||
android:innerRadius="0dp"
|
||||
android:shape="oval"
|
||||
android:useLevel="false">
|
||||
<solid android:color="@android:color/transparent" />
|
||||
<stroke
|
||||
android:width="10dp"
|
||||
android:color="@color/toolbar_background" />
|
||||
</shape>
|
||||
</item>
|
||||
</layer-list>
|
@ -32,7 +32,7 @@
|
||||
<androidx.appcompat.widget.Toolbar
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
android:layout_height="?android:attr/actionBarSize"
|
||||
app:contentInsetStartWithNavigation="0dp"
|
||||
app:navigationIcon="@drawable/ic_back_grey"
|
||||
app:titleMarginStart="0dp"/>
|
||||
|
@ -43,7 +43,7 @@
|
||||
<androidx.appcompat.widget.Toolbar
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
android:layout_height="?android:attr/actionBarSize"
|
||||
app:contentInsetStart="0dp"
|
||||
app:layout_collapseMode="pin"
|
||||
android:background="@android:color/transparent">
|
||||
@ -51,25 +51,26 @@
|
||||
<!-- Back button -->
|
||||
<ImageView
|
||||
android:id="@+id/back_bt"
|
||||
android:layout_width="?attr/actionBarSize"
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"
|
||||
android:layout_gravity="start"
|
||||
android:padding="16dp"
|
||||
android:layout_margin="8dp"
|
||||
android:padding="8dp"
|
||||
android:src="@drawable/ic_back_grey"
|
||||
app:tint="@color/white"
|
||||
android:background="@drawable/floating_semitransparent_button_background"/>
|
||||
|
||||
<!-- Manual position button -->
|
||||
<!-- Save button -->
|
||||
<ImageView
|
||||
android:id="@+id/manual_pos_bt"
|
||||
android:layout_width="?attr/actionBarSize"
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
android:id="@+id/submit_bt"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"
|
||||
android:layout_gravity="end"
|
||||
android:padding="16dp"
|
||||
android:src="@drawable/ic_manual_pos"
|
||||
android:layout_margin="8dp"
|
||||
android:padding="8dp"
|
||||
android:src="@drawable/ic_ok"
|
||||
app:tint="@color/white"
|
||||
android:background="@drawable/floating_semitransparent_button_background"
|
||||
android:visibility="gone"/> <!-- TODO: Implement edit -->
|
||||
android:background="@drawable/round_button_background"/>
|
||||
|
||||
</androidx.appcompat.widget.Toolbar>
|
||||
|
||||
@ -197,20 +198,40 @@
|
||||
android:drawableTint="@color/defaultBrand"
|
||||
android:hint="@string/description"/>
|
||||
|
||||
<AutoCompleteTextView
|
||||
android:id="@+id/category_at"
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="20dp"
|
||||
android:ems="10"
|
||||
android:gravity="start|top"
|
||||
android:inputType="textMultiLine"
|
||||
android:maxLines="10"
|
||||
android:orientation="horizontal"
|
||||
android:layout_marginTop="20dp">
|
||||
|
||||
<AutoCompleteTextView
|
||||
android:id="@+id/category_at"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:maxLines="1"
|
||||
android:background="@android:color/transparent"
|
||||
android:drawableLeft="@drawable/ic_category_asc"
|
||||
android:drawablePadding="5dp"
|
||||
android:drawableTint="@color/defaultBrand"
|
||||
android:hint="@string/category"/>
|
||||
android:hint="@string/category"
|
||||
android:completionThreshold="0"/>
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/category_at_clear"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="3dp"
|
||||
android:background="@color/transparent"
|
||||
android:src="@drawable/ic_clear"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:text="@string/category_hint"
|
||||
android:textSize="12sp"/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
@ -249,7 +270,9 @@
|
||||
android:id="@+id/coords_tv"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAlignment="textEnd" />
|
||||
android:textAlignment="textEnd"
|
||||
app:drawableEndCompat="@drawable/ic_copy"
|
||||
android:drawablePadding="10sp"/>
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progress"
|
||||
@ -258,16 +281,6 @@
|
||||
android:indeterminate="true"
|
||||
android:visibility="gone"/>
|
||||
|
||||
<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>
|
||||
|
||||
</androidx.core.widget.NestedScrollView>
|
||||
|
@ -15,160 +15,34 @@
|
||||
~ 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
|
||||
<FrameLayout
|
||||
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: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"
|
||||
<androidx.fragment.app.FragmentContainerView
|
||||
android:id="@+id/fragment_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:visibility="visible"
|
||||
app:contentInsetStartWithNavigation="0dp"
|
||||
app:titleMarginStart="0dp"
|
||||
tools:title="@string/app_name">
|
||||
android:name="it.danieleverducci.nextcloudmaps.fragments.GeofavoriteListFragment"
|
||||
tools:layout="@layout/fragment_geofavorite_list" />
|
||||
|
||||
<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: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="?attr/actionBarSize"
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:layout_gravity="center_vertical|start"
|
||||
android:paddingStart="@dimen/spacer_1x"
|
||||
android:paddingTop="@dimen/spacer_2x"
|
||||
android:paddingEnd="@dimen/spacer_1x"
|
||||
android:paddingBottom="@dimen/spacer_2x"
|
||||
android:tint="@color/text_color"
|
||||
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:paddingStart="@dimen/spacer_1x"
|
||||
android:paddingTop="@dimen/spacer_2x"
|
||||
android:paddingEnd="@dimen/spacer_1x"
|
||||
android:paddingBottom="@dimen/spacer_2x"
|
||||
android:tint="@color/text_color"
|
||||
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:paddingStart="@dimen/spacer_1x"
|
||||
android:paddingTop="@dimen/spacer_2x"
|
||||
android:paddingEnd="@dimen/spacer_1x"
|
||||
android:paddingBottom="@dimen/spacer_2x" android:tint="@color/text_color"
|
||||
android:translationX="@dimen/spacer_1x"
|
||||
android:src="@drawable/ic_view_module"
|
||||
android:visibility="gone"/> <!-- TODO: Replace with Map View icon -->
|
||||
</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="1"
|
||||
tools:itemCount="3"
|
||||
tools:listitem="@layout/item_geofav">
|
||||
</androidx.recyclerview.widget.RecyclerView>
|
||||
|
||||
</androidx.core.widget.NestedScrollView>
|
||||
|
||||
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
|
||||
|
||||
<!-- Add from map FAB -->
|
||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
android:id="@+id/add_from_map"
|
||||
android:layout_margin="24dp"
|
||||
android:layout_gravity="bottom|end"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:fabSize="mini"
|
||||
android:layout_gravity="bottom|end"
|
||||
android:layout_margin="24dp"
|
||||
android:src="@drawable/ic_add_map"
|
||||
app:backgroundTint="@color/defaultBrand"/>
|
||||
app:backgroundTint="@color/defaultBrand"
|
||||
app:fabSize="mini"
|
||||
app:tint="@color/white"
|
||||
tools:ignore="DuplicateClickableBoundsCheck"
|
||||
android:contentDescription="@string/add_from_map" />
|
||||
|
||||
<!-- Add from current position FAB -->
|
||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
@ -179,7 +53,9 @@
|
||||
android:layout_height="wrap_content"
|
||||
app:fabSize="mini"
|
||||
android:src="@drawable/ic_add_gps"
|
||||
app:backgroundTint="@color/defaultBrand"/>
|
||||
app:backgroundTint="@color/defaultBrand"
|
||||
app:tint="@color/white"
|
||||
android:contentDescription="@string/add_from_gps"/>
|
||||
|
||||
<!-- Main FAB -->
|
||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
@ -189,6 +65,8 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:src="@drawable/ic_add"
|
||||
app:backgroundTint="@color/defaultBrand"/>
|
||||
app:backgroundTint="@color/defaultBrand"
|
||||
app:tint="@color/white"
|
||||
android:contentDescription="@string/open_fab"/>
|
||||
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
</FrameLayout>
|
@ -42,7 +42,7 @@
|
||||
android:id="@+id/scrollView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="?attr/colorPrimary">
|
||||
android:background="?android:attr/colorPrimary">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
@ -68,9 +68,11 @@
|
||||
android:id="@+id/app_name"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginRight="20dp"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_toEndOf="@id/logo"
|
||||
android:ellipsize="end"
|
||||
android:lines="2"
|
||||
android:fontFamily="sans-serif-light"
|
||||
android:gravity="center_vertical"
|
||||
android:text="@string/app_name"
|
||||
|
@ -16,27 +16,30 @@
|
||||
android:layout_height="48dp"
|
||||
android:layout_marginBottom="24dp"
|
||||
android:layout_gravity="center"
|
||||
android:src="@drawable/ic_map_pin"/>
|
||||
android:src="@drawable/ic_map_pin"
|
||||
app:tint="@color/defaultBrand"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/back_bt"
|
||||
android:layout_width="?attr/actionBarSize"
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
android:layout_width="?android:attr/actionBarSize"
|
||||
android:layout_height="?android:attr/actionBarSize"
|
||||
android:layout_margin="16dp"
|
||||
android:layout_gravity="start"
|
||||
android:padding="16dp"
|
||||
android:src="@drawable/ic_back_grey"
|
||||
app:tint="@color/white"
|
||||
android:background="@drawable/floating_semitransparent_button_background"/>
|
||||
app:tint="@color/text_color"
|
||||
android:background="@drawable/unselected_floating_semitransparent_button_background"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/ok_bt"
|
||||
android:layout_width="?attr/actionBarSize"
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
android:layout_width="?android:attr/actionBarSize"
|
||||
android:layout_height="?android:attr/actionBarSize"
|
||||
android:layout_margin="16dp"
|
||||
android:layout_gravity="end"
|
||||
android:padding="16dp"
|
||||
android:src="@drawable/ic_ok"
|
||||
app:tint="@color/white"
|
||||
android:background="@drawable/floating_semitransparent_button_background"/>
|
||||
android:background="@drawable/round_button_background"/>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
|
102
app/src/main/res/layout/app_toolbar.xml
Normal file
@ -0,0 +1,102 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout
|
||||
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:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="10dp">
|
||||
|
||||
<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"
|
||||
android:layout_marginStart="30dp"
|
||||
android:layout_marginEnd="30dp"
|
||||
android:background="@color/translucent">
|
||||
</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/toolbar_background"
|
||||
app:cardCornerRadius="30dp"
|
||||
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="?android:attr/actionBarSize"
|
||||
android:layout_height="?android:attr/actionBarSize"
|
||||
android:background="?android:attr/selectableItemBackgroundBorderless"
|
||||
android:layout_gravity="center_vertical|start"
|
||||
android:paddingStart="@dimen/spacer_1x"
|
||||
android:paddingTop="@dimen/spacer_2x"
|
||||
android:paddingEnd="@dimen/spacer_1x"
|
||||
android:paddingBottom="@dimen/spacer_2x"
|
||||
android:tint="@color/text_color"
|
||||
android:src="@drawable/ic_menu_grey"
|
||||
android:contentDescription="@string/menu"/>
|
||||
<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"/>
|
||||
|
||||
<!-- Filter button -->
|
||||
<ImageButton
|
||||
android:id="@+id/search_filter"
|
||||
android:layout_width="?android:attr/actionBarSize"
|
||||
android:layout_height="?android:attr/actionBarSize"
|
||||
android:src="@drawable/ic_filter_off"
|
||||
app:tint="@color/inactive"
|
||||
android:background="@color/transparent"/>
|
||||
|
||||
<!-- User badge -->
|
||||
<FrameLayout
|
||||
android:id="@+id/user_badge_container"
|
||||
android:layout_width="?android:attr/actionBarSize"
|
||||
android:layout_height="?android:attr/actionBarSize">
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:id="@+id/user_badge"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:padding="10dp"/>
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@drawable/user_badge_mask"/>
|
||||
</FrameLayout>
|
||||
</LinearLayout>
|
||||
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
</FrameLayout>
|
27
app/src/main/res/layout/category_listitem.xml
Normal file
@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingLeft="20dp"
|
||||
android:paddingRight="20dp"
|
||||
android:paddingTop="10dp"
|
||||
android:paddingBottom="10dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/category_name"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="30dp"
|
||||
android:gravity="center_vertical"
|
||||
android:lines="1"
|
||||
android:ellipsize="end"
|
||||
android:text="Lorem ipsum"
|
||||
app:drawableLeftCompat="@drawable/ic_category_asc"
|
||||
android:drawablePadding="8sp"
|
||||
android:drawableTint="@color/white"
|
||||
android:textColor="@color/white"
|
||||
android:textStyle="bold"
|
||||
android:background="@drawable/rounded_label_background"/>
|
||||
|
||||
</FrameLayout>
|
90
app/src/main/res/layout/fragment_geofavorite_list.xml
Normal file
@ -0,0 +1,90 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<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: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="wrap_content"
|
||||
app:elevation="0dp">
|
||||
|
||||
<com.google.android.material.appbar.CollapsingToolbarLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:fitsSystemWindows="true"
|
||||
app:contentScrim="?android:attr/colorPrimary"
|
||||
app:layout_scrollFlags="scroll|enterAlways"
|
||||
app:toolbarId="@+id/toolbar" >
|
||||
|
||||
<include layout="@layout/app_toolbar"/>
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:layout_marginTop="?android:attr/actionBarSize"
|
||||
android:paddingTop="20dp"
|
||||
android:paddingStart="5dp"
|
||||
android:paddingEnd="5dp">
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:id="@+id/sort_mode"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="@dimen/floating_bar_height"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:background="?android:attr/selectableItemBackgroundBorderless"
|
||||
android:contentDescription="@string/list_mode"
|
||||
android:paddingStart="@dimen/spacer_2x"
|
||||
android:paddingEnd="@dimen/spacer_2x"
|
||||
android:tint="@color/text_color"
|
||||
android:src="@drawable/ic_alphabetical_asc" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:id="@+id/view_mode_map"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="@dimen/floating_bar_height"
|
||||
android:layout_alignParentRight="true"
|
||||
android:background="?android:attr/selectableItemBackgroundBorderless"
|
||||
android:contentDescription="@string/list_mode"
|
||||
android:paddingStart="@dimen/spacer_2x"
|
||||
android:paddingEnd="@dimen/spacer_2x"
|
||||
android:tint="@color/text_color"
|
||||
android:src="@drawable/ic_view_map" />
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
</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"
|
||||
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>
|
||||
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
69
app/src/main/res/layout/fragment_geofavorite_map.xml
Normal file
@ -0,0 +1,69 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<FrameLayout
|
||||
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:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<org.osmdroid.views.MapView
|
||||
android:id="@+id/map"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"/>
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/loading_wall"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/translucent"
|
||||
android:visibility="gone">
|
||||
|
||||
<ProgressBar
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:indeterminate="true"
|
||||
android:layout_gravity="center"/>
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
<androidx.appcompat.widget.LinearLayoutCompat
|
||||
android:id="@+id/appBar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:elevation="0dp"
|
||||
android:orientation="vertical">
|
||||
|
||||
<include layout="@layout/app_toolbar"/>
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:id="@+id/view_mode_list"
|
||||
android:layout_width="@dimen/floating_bar_height"
|
||||
android:layout_height="@dimen/floating_bar_height"
|
||||
android:layout_marginTop="2dp"
|
||||
android:layout_marginEnd="@dimen/spacer_2x"
|
||||
android:layout_gravity="right"
|
||||
android:background="@drawable/unselected_floating_semitransparent_button_background"
|
||||
android:contentDescription="@string/list_mode"
|
||||
android:paddingStart="5dp"
|
||||
android:paddingEnd="5dp"
|
||||
android:tint="@color/text_color"
|
||||
android:src="@drawable/ic_view_list" />
|
||||
|
||||
</androidx.appcompat.widget.LinearLayoutCompat>
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:id="@+id/center_position"
|
||||
android:layout_width="@dimen/floating_bar_height"
|
||||
android:layout_height="@dimen/floating_bar_height"
|
||||
android:layout_marginRight="100dp"
|
||||
android:layout_marginBottom="25dp"
|
||||
android:layout_gravity="bottom|right"
|
||||
android:background="@drawable/unselected_floating_semitransparent_button_background"
|
||||
android:padding="5dp"
|
||||
android:tint="@color/text_color"
|
||||
android:src="@drawable/ic_add_gps"
|
||||
android:visibility="gone"/>
|
||||
|
||||
</FrameLayout>
|
119
app/src/main/res/layout/infowindow_geofav.xml
Normal file
@ -0,0 +1,119 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:minWidth="250dp"
|
||||
android:background="@drawable/infowindow_geofav_background"
|
||||
android:padding="7dp"
|
||||
android:orientation="vertical">
|
||||
|
||||
<!-- Geofavorite title -->
|
||||
<TextView
|
||||
android:id="@+id/bubble_title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@color/defaultBrand"
|
||||
android:padding="10dp"
|
||||
android:lines="1"
|
||||
android:ellipsize="end"
|
||||
style="@style/TextAppearance.GeofavoriteInfowindow"
|
||||
android:text="Lorem"/>
|
||||
|
||||
<!-- Geofavorite description -->
|
||||
<TextView
|
||||
android:id="@+id/bubble_description"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="20dp"
|
||||
android:layout_marginBottom="10dp"
|
||||
android:layout_marginLeft="10dp"
|
||||
android:layout_marginRight="10dp"
|
||||
android:text="Lorem ipsum"/>
|
||||
|
||||
<!-- Geofavorite category -->
|
||||
<TextView
|
||||
android:id="@+id/bubble_subdescription"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="30dp"
|
||||
android:layout_marginStart="10dp"
|
||||
android:layout_marginEnd="10dp"
|
||||
android:layout_marginBottom="10dp"
|
||||
android:gravity="center_vertical"
|
||||
android:lines="1"
|
||||
android:ellipsize="end"
|
||||
android:text="Lorem ipsum"
|
||||
app:drawableLeftCompat="@drawable/ic_category_asc"
|
||||
android:drawablePadding="8sp"
|
||||
android:drawableTint="@color/white"
|
||||
android:textColor="@color/white"
|
||||
android:textStyle="bold"
|
||||
android:background="@drawable/rounded_label_background"/>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
|
||||
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/action_icon_share"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:padding="10dp"
|
||||
android:src="@drawable/ic_share"
|
||||
app:tint="@color/defaultBrand"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/action_icon_nav"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:padding="10dp"
|
||||
android:src="@drawable/ic_nav"
|
||||
app:tint="@color/defaultBrand"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/action_icon_delete"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:padding="10dp"
|
||||
android:src="@drawable/ic_delete_grey"
|
||||
app:tint="@color/defaultBrand"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/action_icon_edit"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:padding="10dp"
|
||||
android:src="@drawable/ic_edit"
|
||||
app:tint="@color/defaultBrand"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/bubble_image"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="gone"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<ImageView
|
||||
android:layout_width="50dp"
|
||||
android:layout_height="10dp"
|
||||
android:layout_marginTop="-1dp"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:src="@drawable/geofav_infowindow_pointer"
|
||||
app:tint="@color/defaultBrand" />
|
||||
|
||||
</LinearLayout>
|
BIN
app/src/main/res/mipmap-hdpi/ic_person.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
app/src/main/res/mipmap-mdpi/ic_person.png
Normal file
After Width: | Height: | Size: 962 B |
BIN
app/src/main/res/mipmap-xhdpi/ic_person.png
Normal file
After Width: | Height: | Size: 1.5 KiB |
BIN
app/src/main/res/mipmap-xxhdpi/ic_person.png
Normal file
After Width: | Height: | Size: 2.2 KiB |
BIN
app/src/main/res/mipmap-xxxhdpi/ic_person.png
Normal file
After Width: | Height: | Size: 2.3 KiB |
@ -31,15 +31,21 @@
|
||||
<string name="list_mode">Lista</string>
|
||||
<string name="search_in_all">Cerca per nome</string>
|
||||
<string name="share_via">Condividi via</string>
|
||||
<string name="share_message">Posizione condivisa: {lat}°N, {lng}°E https://www.openstreetmap.org/#map=17/{lat}/{lng}</string>
|
||||
<string name="share_message">{title}: {lat}°N, {lng}°E https://www.openstreetmap.org/#map=17/{lat}/{lng}</string>
|
||||
<string name="share_message_default_title">Posizione condivisa:</string>
|
||||
<string name="list_context_menu_share">Condividi</string>
|
||||
<string name="list_context_menu_delete">Elimina</string>
|
||||
<string name="dialog_delete_title">Elimina geosegnalibro</string>
|
||||
<string name="dialog_delete_message">Stai per eliminare il geosegnalibro {name}. Procedere?</string>
|
||||
<string name="dialog_delete_delete">Elimina</string>
|
||||
<string name="dialog_delete_cancel">Mantieni</string>
|
||||
<string name="dialog_logout_title">Cambia account</string>
|
||||
<string name="dialog_logout_message">Vuoi cambiare account?</string>
|
||||
<string name="list_geofavorite_deleted">Geosegnalibro eliminato</string>
|
||||
<string name="list_geofavorite_connection_error">Impossibile ottenere la lista dei geosegnalibri</string>
|
||||
<string name="filtering_unavailable">Il filtro per categoria non è disponibile al momento</string>
|
||||
<string name="filtering_dialog_title">Filtra per categoria</string>
|
||||
<string name="filtering_dialog_cancel">Mostra tutti</string>
|
||||
|
||||
<!-- Sort dialog -->
|
||||
<string name="sort_by">Ordina per</string>
|
||||
@ -58,11 +64,12 @@
|
||||
<string name="accuracy">Accuratezza: {accuracy} m</string>
|
||||
<string name="accuracy_nosignal">Nessun segnale GPS!</string>
|
||||
<string name="location_permission_required">Per creare un geosegnalibro è necessario consentire l\'accesso alla posizione.</string>
|
||||
<string name="confirm">Salva</string>
|
||||
<string name="category_hint">Scrivi il nome per creare una nuova categoria</string>
|
||||
<string name="error_saving_geofavorite">Impossibile salvare il geosegnalibro</string>
|
||||
<string name="error_unsupported_uri">Impossibile ottenere le coordinate dai dati ricevuti</string>
|
||||
<string name="geofavorite_saved">Geosegnalibro salvato</string>
|
||||
<string name="incomplete_geofavorite">Geosegnalibro incompleto: nome e categoria sono obbligatori</string>
|
||||
<string name="coords_copied">Coordinate copiate nella clipboard</string>
|
||||
|
||||
<!-- Map picker activity -->
|
||||
<string name="coordinates_parse_error">Le coordinate dovrebbero essere nel formato xx.xxxxxx</string>
|
||||
@ -93,12 +100,13 @@
|
||||
<string name="url_license" translatable="false">https://raw.githubusercontent.com/penguin86/nextcloud-maps-client/master/LICENSE</string>
|
||||
<string name="url_maps" translatable="false">https://donate.openstreetmap.org</string>
|
||||
|
||||
<!-- Settings -->
|
||||
<string name="setting_sort_by">SETTING_SORT_BY</string>
|
||||
<string name="setting_grid_view_enabled">SETTING_GRID_VIEW_ENABLED</string>
|
||||
|
||||
<!-- Menu -->
|
||||
<string name="new_geobookmark_gps">Crea dalla posizione corrente</string>
|
||||
<string name="new_geobookmark_map">Crea dalla mappa</string>
|
||||
|
||||
<!-- Accessibility (content descriptions) -->
|
||||
<string name="open_fab">Aggiungi</string>
|
||||
<string name="add_from_gps">Crea dalla posizione corrente</string>
|
||||
<string name="add_from_map">Crea dalla mappa</string>
|
||||
|
||||
</resources>
|
||||
|
@ -3,4 +3,8 @@
|
||||
<color name="text_color">#eee</color>
|
||||
<color name="disabled">#888</color>
|
||||
<color name="defaultBackground">#000</color>
|
||||
<color name="translucent">#C000</color>
|
||||
|
||||
<!-- Toolbar -->
|
||||
<color name="toolbar_background">#211e28</color>
|
||||
</resources>
|
@ -19,7 +19,7 @@
|
||||
<resources>
|
||||
|
||||
<style name="AppTheme" parent="BaseTheme">
|
||||
<item name="android:statusBarColor">?attr/colorPrimary</item>
|
||||
<item name="android:statusBarColor">?android:attr/colorPrimary</item>
|
||||
<item name="android:windowLightStatusBar">true</item>
|
||||
</style>
|
||||
|
||||
|
@ -19,9 +19,9 @@
|
||||
<resources>
|
||||
|
||||
<style name="AppTheme" parent="BaseTheme">
|
||||
<item name="android:statusBarColor">?attr/colorPrimary</item>
|
||||
<item name="android:statusBarColor">?android:attr/colorPrimary</item>
|
||||
<item name="android:windowLightStatusBar">true</item>
|
||||
<item name="android:navigationBarColor">?attr/colorPrimary</item>
|
||||
<item name="android:navigationBarColor">?android:attr/colorPrimary</item>
|
||||
<item name="android:windowLightNavigationBar">true</item>
|
||||
</style>
|
||||
|
||||
|
@ -20,11 +20,13 @@
|
||||
<!-- Generic Colors -->
|
||||
<color name="primary">#ffffff</color>
|
||||
<color name="transparent">#00000000</color>
|
||||
<color name="translucent">#AEFFFFFF</color>
|
||||
<color name="defaultBrand">#0082C9</color>
|
||||
<color name="defaultBrandAlpha">#550082C9</color>
|
||||
<color name="disabled">#666</color>
|
||||
<color name="systemBar">@color/defaultBackground</color>
|
||||
<color name="defaultBackground">#fff</color>
|
||||
<color name="inactive">#ccc</color>
|
||||
|
||||
<!-- List Colors -->
|
||||
<color name="text_color">#333</color>
|
||||
@ -36,4 +38,7 @@
|
||||
|
||||
<!-- Generic Colors -->
|
||||
<color name="white">#fff</color>
|
||||
|
||||
<!-- Toolbar -->
|
||||
<color name="toolbar_background">@color/defaultBackground</color>
|
||||
</resources>
|
@ -39,4 +39,7 @@
|
||||
<!-- FAB dimensions -->
|
||||
<dimen name="fab_vertical_offset">75dp</dimen>
|
||||
|
||||
<!-- Floating bar below search bar -->
|
||||
<dimen name="floating_bar_height">36dp</dimen>
|
||||
|
||||
</resources>
|
||||
|
@ -30,15 +30,21 @@
|
||||
<string name="list_mode">List</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="share_message">{title}: {lat}°N, {lng}°E https://www.openstreetmap.org/#map=17/{lat}/{lng}</string>
|
||||
<string name="share_message_default_title">Check out this place:</string>
|
||||
<string name="list_context_menu_share">Share</string>
|
||||
<string name="list_context_menu_delete">Delete</string>
|
||||
<string name="dialog_delete_title">Delete geofavorite</string>
|
||||
<string name="dialog_delete_message">You are about to delete geofavorite {name}. Proceed?</string>
|
||||
<string name="dialog_delete_delete">Delete</string>
|
||||
<string name="dialog_delete_cancel">Maintain</string>
|
||||
<string name="dialog_logout_title">Switch account</string>
|
||||
<string name="dialog_logout_message">Do you want to switch account?</string>
|
||||
<string name="list_geofavorite_deleted">Geofavorite deleted</string>
|
||||
<string name="list_geofavorite_connection_error">Unable to obtain geofavorites list</string>
|
||||
<string name="filtering_unavailable">Category filtering is unavailable at the moment</string>
|
||||
<string name="filtering_dialog_title">Filter by category</string>
|
||||
<string name="filtering_dialog_cancel">Show all</string>
|
||||
|
||||
<!-- Sort dialog -->
|
||||
<string name="sort_by">Sort by</string>
|
||||
@ -57,11 +63,12 @@
|
||||
<string name="accuracy">Accuracy: {accuracy} m</string>
|
||||
<string name="accuracy_nosignal">No GPS signal!</string>
|
||||
<string name="location_permission_required">Location permission is required to create a geofavorite.</string>
|
||||
<string name="confirm">Save</string>
|
||||
<string name="category_hint">Write the name to create a new category</string>
|
||||
<string name="error_saving_geofavorite">Unable to save geofavorite</string>
|
||||
<string name="error_unsupported_uri">Unable to obtain coordinates from shared data</string>
|
||||
<string name="geofavorite_saved">Geofavorite saved</string>
|
||||
<string name="incomplete_geofavorite">Incomplete geofavorite: Name and category are mandatory</string>
|
||||
<string name="coords_copied">Coordinates have been copied to the clipboard</string>
|
||||
|
||||
<!-- Map picker activity -->
|
||||
<string name="coordinates_parse_error">Coordinates should be in format xx.xxxxxx</string>
|
||||
@ -92,12 +99,13 @@
|
||||
<string name="url_license" translatable="false">https://raw.githubusercontent.com/penguin86/nextcloud-maps-client/master/LICENSE</string>
|
||||
<string name="url_maps" translatable="false">https://donate.openstreetmap.org</string>
|
||||
|
||||
<!-- Settings -->
|
||||
<string name="setting_sort_by">SETTING_SORT_BY</string>
|
||||
<string name="setting_grid_view_enabled">SETTING_GRID_VIEW_ENABLED</string>
|
||||
|
||||
<!-- Menu -->
|
||||
<string name="new_geobookmark_gps">New from current position</string>
|
||||
<string name="new_geobookmark_map">New from map</string>
|
||||
|
||||
<!-- Accessibility (content descriptions) -->
|
||||
<string name="open_fab">Add geofavorite</string>
|
||||
<string name="add_from_gps">Add geofavorite at current GPS position</string>
|
||||
<string name="add_from_map">Add geofavorite from map</string>
|
||||
<string name="menu">Open menu</string>
|
||||
</resources>
|
||||
|
@ -17,15 +17,17 @@
|
||||
|
||||
<resources>
|
||||
<!-- Base application theme. -->
|
||||
<style name="BaseTheme" parent="Theme.AppCompat.DayNight.NoActionBar">
|
||||
<style name="BaseTheme" parent="Theme.MaterialComponents.DayNight.NoActionBar">
|
||||
<item name="colorAccent">@color/defaultBrand</item>
|
||||
<item name="colorControlNormal">?attr/colorAccent</item>
|
||||
<item name="colorControlNormal">?android:attr/colorAccent</item>
|
||||
<item name="windowActionModeOverlay">true</item>
|
||||
<!-- App bar -->
|
||||
<item name="colorPrimary">@color/systemBar</item>
|
||||
<!-- Generic background -->
|
||||
<item name="android:windowBackground">@color/defaultBackground</item>
|
||||
|
||||
<item name="alertDialogTheme">@style/AlertDialogTheme</item>
|
||||
|
||||
</style>
|
||||
|
||||
<style name="AppTheme" parent="BaseTheme"/>
|
||||
@ -48,4 +50,22 @@
|
||||
<item name="android:textColor">@color/white</item>
|
||||
</style>
|
||||
|
||||
<style name="TextAppearance.GeofavoriteInfowindow" parent="TextAppearance.AppCompat.Title">
|
||||
<item name="android:textColor">@color/white</item>
|
||||
</style>
|
||||
|
||||
<!-- Alertdialogs -->
|
||||
<style name="AlertDialogTheme" parent="ThemeOverlay.MaterialComponents.Dialog.Alert">
|
||||
<item name="buttonBarNegativeButtonStyle">@style/NegativeButtonStyle</item>
|
||||
<item name="buttonBarPositiveButtonStyle">@style/PositiveButtonStyle</item>
|
||||
</style>
|
||||
|
||||
<style name="NegativeButtonStyle" parent="Widget.MaterialComponents.Button.TextButton.Dialog">
|
||||
<item name="android:textColor">@color/inactive</item>
|
||||
</style>
|
||||
|
||||
<style name="PositiveButtonStyle" parent="Widget.MaterialComponents.Button.TextButton.Dialog">
|
||||
<item name="android:textColor">@color/defaultBrand</item>
|
||||
</style>
|
||||
|
||||
</resources>
|
@ -25,7 +25,7 @@ buildscript {
|
||||
jcenter()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:7.1.1'
|
||||
classpath 'com.android.tools.build:gradle:8.5.1'
|
||||
|
||||
// NOTE: Do not place your application dependencies here; they belong
|
||||
// in the individual module build.gradle files
|
||||
|
Before Width: | Height: | Size: 129 KiB |
Before Width: | Height: | Size: 49 KiB |
Before Width: | Height: | Size: 57 KiB |
Before Width: | Height: | Size: 108 KiB |
Before Width: | Height: | Size: 63 KiB |
Before Width: | Height: | Size: 64 KiB |
5
fastlane/metadata/android/en-US/changelogs/9.txt
Normal file
@ -0,0 +1,5 @@
|
||||
Map view
|
||||
Filter by category
|
||||
Button to copy coordinates to clipboard
|
||||
Faster autocomplete
|
||||
Graphics restyling to match new Nextcloud style
|
@ -1,4 +1,4 @@
|
||||
UNOFFICIAL and FOSS Nextcloud Maps client at its earliest stages of developement. Shows your Nextcloud Maps geofavorites list.
|
||||
UNOFFICIAL and FOSS Nextcloud Maps client. Shows your Nextcloud Maps geofavorites in a list or a map.
|
||||
Geofavorites can be opened in all apps supporting geo links (i.e. Google Maps, Organic Maps etc...).
|
||||
A new geofavorite can be created on current location, by sharing a "geo:" uri from another app or manually picking from the map.
|
||||
|
||||
|
Before Width: | Height: | Size: 118 KiB After Width: | Height: | Size: 154 KiB |
Before Width: | Height: | Size: 105 KiB After Width: | Height: | Size: 2.8 MiB |
Before Width: | Height: | Size: 114 KiB After Width: | Height: | Size: 229 KiB |
Before Width: | Height: | Size: 108 KiB |
@ -1,3 +1,3 @@
|
||||
Client per Nextcloud Maps non ufficiale e FOSS al suo stato iniziale di sviluppo.
|
||||
Mostra la lista dei geosegnalibri di Nextcloud Maps e permette di aprirli in qualunque app supporti i "geo:" urls (i.e. Google Maps, Organic Maps etc...).
|
||||
Mostra i geosegnalibri di Nextcloud Maps in lista o in mappa e permette di aprirli in qualunque app supporti i "geo:" urls (i.e. Google Maps, Organic Maps etc...).
|
||||
È possibile creare nuovi geosegnalibri nella posizione GPS attuale, scegliendo la posizione dalla mappa o condividendola da altre app sotto forma di "geo:" uri.
|
||||
|
@ -37,3 +37,6 @@ org.gradle.jvmargs=-Xmx2048m
|
||||
android.useAndroidX=true
|
||||
# Automatically convert third-party libraries to use AndroidX
|
||||
android.enableJetifier=true
|
||||
android.defaults.buildfeatures.buildconfig=true
|
||||
android.nonTransitiveRClass=false
|
||||
android.nonFinalResIds=false
|
2
gradle/wrapper/gradle-wrapper.properties
vendored
@ -1,6 +1,6 @@
|
||||
#Sun Feb 20 08:50:37 CET 2022
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
|
||||
distributionPath=wrapper/dists
|
||||
zipStorePath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
|
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 44 KiB |
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 178 KiB |
BIN
screenshots/3.png
Normal file
After Width: | Height: | Size: 53 KiB |
Before Width: | Height: | Size: 118 KiB After Width: | Height: | Size: 154 KiB |
Before Width: | Height: | Size: 105 KiB After Width: | Height: | Size: 2.8 MiB |
Before Width: | Height: | Size: 114 KiB After Width: | Height: | Size: 229 KiB |
Before Width: | Height: | Size: 108 KiB |