Compare commits
57 Commits
v0.3.4
...
f0d8e30d39
| Author | SHA1 | Date | |
|---|---|---|---|
|
f0d8e30d39
|
|||
|
096cb18415
|
|||
| d929397492 | |||
| 2217f80f72 | |||
| d062158c7c | |||
| 26dcfb8f34 | |||
| 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 | |||
| cd576ada12 | |||
| cf7d38d872 | |||
| a13e601eea | |||
| 7efd2a2f8b | |||
| 4f64ef00b9 | |||
| e595b12705 | |||
| 73f597fb54 | |||
| 3ac332535d | |||
| 4f59359f5e | |||
| 713e47b20a | |||
| 9dfcfa064a |
@@ -96,3 +96,10 @@ lint/generated/
|
|||||||
lint/outputs/
|
lint/outputs/
|
||||||
lint/tmp/
|
lint/tmp/
|
||||||
# lint/reports/
|
# 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"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="CompilerConfiguration">
|
<component name="CompilerConfiguration">
|
||||||
<bytecodeTargetLevel target="11" />
|
<bytecodeTargetLevel target="21" />
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
||||||
@@ -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>
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||

|

|
||||||
|
|
||||||
# Nextcloud Maps Geobookmarks Android app
|
# Nextcloud Maps Geofavorites Android app
|
||||||
|
|
||||||
[<img src="https://fdroid.gitlab.io/artwork/badge/get-it-on.png" alt="Get it on F-Droid" height="80">](https://f-droid.org/it/packages/it.danieleverducci.nextcloudmaps)
|
[<img src="https://fdroid.gitlab.io/artwork/badge/get-it-on.png" alt="Get it on F-Droid" height="80">](https://f-droid.org/it/packages/it.danieleverducci.nextcloudmaps)
|
||||||
[<img src="https://cdn.rawgit.com/steverichey/google-play-badge-svg/master/img/en_get.svg" height="80">](https://play.google.com/store/apps/details?id=it.danieleverducci.nextcloudmaps)
|
[<img src="https://cdn.rawgit.com/steverichey/google-play-badge-svg/master/img/en_get.svg" height="80">](https://play.google.com/store/apps/details?id=it.danieleverducci.nextcloudmaps)
|
||||||
@@ -8,13 +8,29 @@
|
|||||||
|
|
||||||
(Always prefer [F-Droid](https://f-droid.org) build, when possible).
|
(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 geobookmarks list.
|
UNOFFICIAL and FOSS Nextcloud Maps client at its earliest stages of developement. Shows your Nextcloud Maps geofavorites in a list and a map.
|
||||||
Geobookmarks can be opened in all apps supporting geo links (i.e. Google Maps, Organic Maps etc...).
|
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.
|
A new geofavorite can be created on current location, by sharing a "geo:" uri from another app or manually picking from the map.
|
||||||
|
|
||||||
**Requires Maps app to be installed on the Nextcloud instance.**
|
**Requires Maps app to be installed on the Nextcloud instance.**
|
||||||
|
|
||||||
This work is heavily based on [matiasdelellis's Nextcloud SSO example](https://github.com/matiasdelellis/app-tutorial-android) to implement [Nextcloud single sign on](https://github.com/nextcloud/Android-SingleSignOn).
|
This work is heavily based on [matiasdelellis's Nextcloud SSO example](https://github.com/matiasdelellis/app-tutorial-android) to implement [Nextcloud single sign on](https://github.com/nextcloud/Android-SingleSignOn).
|
||||||
|
|
||||||
 
|
  
|
||||||
|
|
||||||
|
## Contributions
|
||||||
|
|
||||||
|
### Why isn't this hosted on GitHub?
|
||||||
|
|
||||||
|
I'm using a private git server just because I'm worried for the vast majority of open source code being hosted in a server property of Microsoft and being used to train theirs AI.
|
||||||
|
I didn't find a better option, BTW the Gitea project is working on implementing federation, so soon it will be possible to contribute using any other gitea server, selfhosted or not.
|
||||||
|
|
||||||
|
### How to contribute
|
||||||
|
|
||||||
|
The project is open to contribution, but with some limits:
|
||||||
|
|
||||||
|
- I'm sorry I can't accept AI-generated contributions. Reviewing a contribution requires time and effort from my side, while generating code with AI requires very little time and produces non reliable code that must be reviewed in detail. This is effectively shifting the work on my side, and in a forced way. If you feel you need a feature but you're not able to implement it by yourself, I prefer you to create an issue in the repository so I can implement it when I can, in a more mantainable way.
|
||||||
|
- I prefer to make project-wide changes (i.e. updating Android target, app name and icon, release number...) by myself.
|
||||||
|
|
||||||
|
To contribute, you'll have to create an account on this git instance. Unfortunately, I had to disable registration to avoid huge waves of fake accounts created by bots.
|
||||||
|
You can request an account writing to daniele.verducci@ichibi.eu
|
||||||
|
|||||||
@@ -18,14 +18,13 @@
|
|||||||
apply plugin: 'com.android.application'
|
apply plugin: 'com.android.application'
|
||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdkVersion 30
|
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId "it.danieleverducci.nextcloudmaps"
|
applicationId "it.danieleverducci.nextcloudmaps"
|
||||||
minSdkVersion 23
|
minSdkVersion 23
|
||||||
targetSdkVersion 30
|
targetSdkVersion 34
|
||||||
versionCode 6
|
compileSdkVersion 34
|
||||||
versionName "0.3.4"
|
versionCode 9
|
||||||
|
versionName "0.4.0"
|
||||||
|
|
||||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||||
}
|
}
|
||||||
@@ -37,13 +36,18 @@ android {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
compileOptions {
|
compileOptions {
|
||||||
|
// Flag to enable support for the new language APIs
|
||||||
|
coreLibraryDesugaringEnabled true
|
||||||
|
// Sets Java compatibility to Java 8
|
||||||
sourceCompatibility JavaVersion.VERSION_1_8
|
sourceCompatibility JavaVersion.VERSION_1_8
|
||||||
targetCompatibility JavaVersion.VERSION_1_8
|
targetCompatibility JavaVersion.VERSION_1_8
|
||||||
}
|
}
|
||||||
|
|
||||||
buildFeatures {
|
buildFeatures {
|
||||||
dataBinding true
|
dataBinding true
|
||||||
|
buildConfig true
|
||||||
}
|
}
|
||||||
|
namespace 'it.danieleverducci.nextcloudmaps'
|
||||||
}
|
}
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
@@ -54,28 +58,40 @@ repositories {
|
|||||||
dependencies {
|
dependencies {
|
||||||
implementation fileTree(dir: "libs", include: ["*.jar"])
|
implementation fileTree(dir: "libs", include: ["*.jar"])
|
||||||
|
|
||||||
implementation 'com.android.support:design:30.0.1'
|
// Desugaring lib: see https://developer.android.com/studio/write/java8-support
|
||||||
implementation 'androidx.appcompat:appcompat:1.3.1'
|
coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.1.2")
|
||||||
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"
|
|
||||||
|
|
||||||
testImplementation 'junit:junit:4.13.2'
|
implementation 'com.android.support:design:34.0.0'
|
||||||
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
|
implementation 'androidx.appcompat:appcompat:1.7.0'
|
||||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.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
|
// 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'
|
implementation 'com.squareup.retrofit2:converter-gson:2.6.1'
|
||||||
|
|
||||||
// Nextcloud SSO
|
// Nextcloud SSO
|
||||||
implementation "com.github.nextcloud:Android-SingleSignOn:0.5.6"
|
implementation "com.github.nextcloud:Android-SingleSignOn:1.3.2"
|
||||||
|
|
||||||
// OSMDroid
|
// 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+)
|
//Threeten-Backport (ports Java 8 Date API on Java 6+)
|
||||||
implementation 'org.threeten:threetenbp:1.5.1'
|
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'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,18 +0,0 @@
|
|||||||
{
|
|
||||||
"version": 2,
|
|
||||||
"artifactType": {
|
|
||||||
"type": "APK",
|
|
||||||
"kind": "Directory"
|
|
||||||
},
|
|
||||||
"applicationId": "it.danieleverducci.nextcloudmaps",
|
|
||||||
"variantName": "release",
|
|
||||||
"elements": [
|
|
||||||
{
|
|
||||||
"type": "SINGLE",
|
|
||||||
"filters": [],
|
|
||||||
"versionCode": 6,
|
|
||||||
"versionName": "0.3.4",
|
|
||||||
"outputFile": "app-release.apk"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -17,10 +17,10 @@
|
|||||||
-->
|
-->
|
||||||
|
|
||||||
<manifest
|
<manifest
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
package="it.danieleverducci.nextcloudmaps">
|
|
||||||
|
|
||||||
<uses-permission android:name="android.permission.INTERNET" />
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
|
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
||||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
||||||
|
|
||||||
<queries>
|
<queries>
|
||||||
@@ -35,21 +35,24 @@
|
|||||||
android:supportsRtl="true"
|
android:supportsRtl="true"
|
||||||
android:theme="@style/AppTheme">
|
android:theme="@style/AppTheme">
|
||||||
|
|
||||||
<activity android:name=".activity.login.LoginActivity">
|
<activity android:name=".activity.login.LoginActivity"
|
||||||
|
android:exported="true">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.MAIN" />
|
<action android:name="android.intent.action.MAIN" />
|
||||||
<category android:name="android.intent.category.LAUNCHER" />
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<activity android:name=".activity.main.MainActivity">
|
<activity android:name=".activity.main.MainActivity"
|
||||||
|
android:exported="true">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.VIEW" />
|
<action android:name="android.intent.action.VIEW" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".activity.detail.GeofavoriteDetailActivity">
|
android:name=".activity.detail.GeofavoriteDetailActivity"
|
||||||
|
android:exported="true">
|
||||||
<!-- standard "geo" scheme -->
|
<!-- standard "geo" scheme -->
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.VIEW"/>
|
<action android:name="android.intent.action.VIEW"/>
|
||||||
@@ -82,19 +85,35 @@
|
|||||||
<category android:name="android.intent.category.DEFAULT"/>
|
<category android:name="android.intent.category.DEFAULT"/>
|
||||||
<category android:name="android.intent.category.BROWSABLE"/>
|
<category android:name="android.intent.category.BROWSABLE"/>
|
||||||
<data
|
<data
|
||||||
android:host="maps.google.com"
|
android:host="www.google.com"
|
||||||
android:scheme="http"/>
|
android:pathPrefix="/maps"
|
||||||
|
android:scheme="https"/>
|
||||||
|
</intent-filter>
|
||||||
|
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.VIEW"/>
|
||||||
|
<category android:name="android.intent.category.DEFAULT"/>
|
||||||
|
<category android:name="android.intent.category.BROWSABLE"/>
|
||||||
|
<data
|
||||||
|
android:host="www.openstreetmap.org"
|
||||||
|
android:scheme="https"/>
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
|
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<activity android:name=".activity.mappicker.MapPickerActivity"
|
<activity android:name=".activity.mappicker.MapPickerActivity"
|
||||||
|
android:exported="true"
|
||||||
android:theme="@style/AppTheme">
|
android:theme="@style/AppTheme">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.VIEW" />
|
<action android:name="android.intent.action.VIEW" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
|
<activity
|
||||||
|
android:name=".activity.settings.SettingsActivity"
|
||||||
|
android:launchMode="singleTask"
|
||||||
|
android:theme="@style/AppTheme"/>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".activity.about.AboutActivity"
|
android:name=".activity.about.AboutActivity"
|
||||||
android:launchMode="singleTask"
|
android:launchMode="singleTask"
|
||||||
|
|||||||
@@ -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,22 +18,22 @@
|
|||||||
package it.danieleverducci.nextcloudmaps.activity.detail;
|
package it.danieleverducci.nextcloudmaps.activity.detail;
|
||||||
|
|
||||||
import android.Manifest;
|
import android.Manifest;
|
||||||
|
import android.content.ClipData;
|
||||||
|
import android.content.ClipboardManager;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.graphics.Color;
|
|
||||||
import android.location.Location;
|
import android.location.Location;
|
||||||
import android.location.LocationListener;
|
import android.location.LocationListener;
|
||||||
import android.location.LocationManager;
|
import android.location.LocationManager;
|
||||||
import android.os.Build;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.util.Log;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
|
||||||
import androidx.appcompat.content.res.AppCompatResources;
|
import androidx.appcompat.content.res.AppCompatResources;
|
||||||
import androidx.core.app.ActivityCompat;
|
import androidx.core.app.ActivityCompat;
|
||||||
import androidx.lifecycle.Observer;
|
import androidx.lifecycle.Observer;
|
||||||
@@ -42,7 +42,6 @@ import androidx.preference.PreferenceManager;
|
|||||||
|
|
||||||
import org.osmdroid.api.IMapController;
|
import org.osmdroid.api.IMapController;
|
||||||
import org.osmdroid.config.Configuration;
|
import org.osmdroid.config.Configuration;
|
||||||
import org.osmdroid.config.IConfigurationProvider;
|
|
||||||
import org.osmdroid.util.GeoPoint;
|
import org.osmdroid.util.GeoPoint;
|
||||||
import org.osmdroid.views.CustomZoomButtonsController;
|
import org.osmdroid.views.CustomZoomButtonsController;
|
||||||
import org.osmdroid.views.overlay.Marker;
|
import org.osmdroid.views.overlay.Marker;
|
||||||
@@ -51,10 +50,8 @@ import org.threeten.bp.format.FormatStyle;
|
|||||||
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
|
||||||
import it.danieleverducci.nextcloudmaps.BuildConfig;
|
|
||||||
import it.danieleverducci.nextcloudmaps.R;
|
import it.danieleverducci.nextcloudmaps.R;
|
||||||
import it.danieleverducci.nextcloudmaps.activity.NextcloudMapsStyledActivity;
|
import it.danieleverducci.nextcloudmaps.activity.NextcloudMapsStyledActivity;
|
||||||
import it.danieleverducci.nextcloudmaps.activity.mappicker.MapPickerActivity;
|
|
||||||
import it.danieleverducci.nextcloudmaps.databinding.ActivityGeofavoriteDetailBinding;
|
import it.danieleverducci.nextcloudmaps.databinding.ActivityGeofavoriteDetailBinding;
|
||||||
import it.danieleverducci.nextcloudmaps.model.Geofavorite;
|
import it.danieleverducci.nextcloudmaps.model.Geofavorite;
|
||||||
import it.danieleverducci.nextcloudmaps.utils.GeoUriParser;
|
import it.danieleverducci.nextcloudmaps.utils.GeoUriParser;
|
||||||
@@ -64,7 +61,6 @@ import it.danieleverducci.nextcloudmaps.utils.MapUtils;
|
|||||||
public class GeofavoriteDetailActivity extends NextcloudMapsStyledActivity implements LocationListener, ActivityCompat.OnRequestPermissionsResultCallback {
|
public class GeofavoriteDetailActivity extends NextcloudMapsStyledActivity implements LocationListener, ActivityCompat.OnRequestPermissionsResultCallback {
|
||||||
|
|
||||||
public static final String TAG = "GeofavDetail";
|
public static final String TAG = "GeofavDetail";
|
||||||
public static final int MINIMUM_ACCEPTABLE_ACCURACY = 50; // In meters
|
|
||||||
public static final String ARG_GEOFAVORITE = "geofav";
|
public static final String ARG_GEOFAVORITE = "geofav";
|
||||||
private static final int PERMISSION_REQUEST_CODE = 9999;
|
private static final int PERMISSION_REQUEST_CODE = 9999;
|
||||||
|
|
||||||
@@ -86,11 +82,6 @@ public class GeofavoriteDetailActivity extends NextcloudMapsStyledActivity imple
|
|||||||
finish();
|
finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onMapEditPressed() {
|
|
||||||
//TODO
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onActionIconShareClicked() {
|
public void onActionIconShareClicked() {
|
||||||
startActivity(Intent.createChooser(IntentGenerator.newShareIntent(GeofavoriteDetailActivity.this, mGeofavorite), getString(R.string.share_via)));
|
startActivity(Intent.createChooser(IntentGenerator.newShareIntent(GeofavoriteDetailActivity.this, mGeofavorite), getString(R.string.share_via)));
|
||||||
@@ -119,7 +110,7 @@ public class GeofavoriteDetailActivity extends NextcloudMapsStyledActivity imple
|
|||||||
});
|
});
|
||||||
|
|
||||||
mViewModel = new ViewModelProvider(this).get(GeofavoriteDetailActivityViewModel.class);
|
mViewModel = new ViewModelProvider(this).get(GeofavoriteDetailActivityViewModel.class);
|
||||||
mViewModel.init();
|
mViewModel.init(getApplicationContext());
|
||||||
mViewModel.getCategories().observe(this, new Observer<HashSet<String>>() {
|
mViewModel.getCategories().observe(this, new Observer<HashSet<String>>() {
|
||||||
@Override
|
@Override
|
||||||
public void onChanged(HashSet<String> categories) {
|
public void onChanged(HashSet<String> categories) {
|
||||||
@@ -161,11 +152,12 @@ public class GeofavoriteDetailActivity extends NextcloudMapsStyledActivity imple
|
|||||||
if (getIntent().getData() != null) {
|
if (getIntent().getData() != null) {
|
||||||
// Opened by external generic intent: parse URI
|
// Opened by external generic intent: parse URI
|
||||||
try {
|
try {
|
||||||
double[] coords = GeoUriParser.parseUri(getIntent().getData());
|
double[] coords = GeoUriParser.parseUri(getIntent().getData(), false);
|
||||||
mGeofavorite.setLat(coords[0]);
|
mGeofavorite.setLat(coords[0]);
|
||||||
mGeofavorite.setLng(coords[1]);
|
mGeofavorite.setLng(coords[1]);
|
||||||
mViewHolder.hideAccuracy();
|
mViewHolder.hideAccuracy();
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (IllegalArgumentException e) {
|
||||||
|
Log.e(TAG, e.getMessage());
|
||||||
Toast.makeText(this, R.string.error_unsupported_uri, Toast.LENGTH_SHORT).show();
|
Toast.makeText(this, R.string.error_unsupported_uri, Toast.LENGTH_SHORT).show();
|
||||||
finish();
|
finish();
|
||||||
}
|
}
|
||||||
@@ -312,9 +304,15 @@ public class GeofavoriteDetailActivity extends NextcloudMapsStyledActivity imple
|
|||||||
this.binding.actionIconNav.setOnClickListener(this);
|
this.binding.actionIconNav.setOnClickListener(this);
|
||||||
|
|
||||||
// Set categories adapter
|
// 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.setAdapter(categoriesAdapter);
|
||||||
this.binding.categoryAt.setText(Geofavorite.DEFAULT_CATEGORY);
|
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
|
// Set map properties
|
||||||
this.binding.map.getZoomController().setVisibility(CustomZoomButtonsController.Visibility.NEVER);
|
this.binding.map.getZoomController().setVisibility(CustomZoomButtonsController.Visibility.NEVER);
|
||||||
@@ -335,16 +333,22 @@ public class GeofavoriteDetailActivity extends NextcloudMapsStyledActivity imple
|
|||||||
|
|
||||||
public void updateView(Geofavorite item) {
|
public void updateView(Geofavorite item) {
|
||||||
binding.collapsingToolbar.setTitle(item.getName() != null ? item.getName() : getString(R.string.new_geobookmark));
|
binding.collapsingToolbar.setTitle(item.getName() != null ? item.getName() : getString(R.string.new_geobookmark));
|
||||||
binding.nameEt.setText(item.getName());
|
binding.nameEt.setText(item.getName() != null ? item.getName() : "");
|
||||||
binding.descriptionEt.setText(item.getComment());
|
binding.descriptionEt.setText(item.getComment() != null ? item.getComment() : "");
|
||||||
binding.createdTv.setText(item.getLocalDateCreated().format(dateFormatter));
|
binding.createdTv.setText(item.getLocalDateCreated().format(dateFormatter));
|
||||||
binding.modifiedTv.setText(item.getLocalDateCreated().format(dateFormatter));
|
binding.modifiedTv.setText(item.getLocalDateCreated().format(dateFormatter));
|
||||||
binding.categoryAt.setText(item.getCategory());
|
binding.categoryAt.setText(item.getCategory() != null ? item.getCategory() : Geofavorite.DEFAULT_CATEGORY);
|
||||||
updateViewCoords(item);
|
updateViewCoords(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateViewCoords(Geofavorite item) {
|
public void updateViewCoords(Geofavorite item) {
|
||||||
binding.coordsTv.setText(item.getCoordinatesString());
|
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
|
// Center map
|
||||||
GeoPoint position = new GeoPoint(item.getLat(), item.getLng());
|
GeoPoint position = new GeoPoint(item.getLat(), item.getLng());
|
||||||
@@ -377,7 +381,7 @@ public class GeofavoriteDetailActivity extends NextcloudMapsStyledActivity imple
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void setCategories(HashSet<String> categories) {
|
public void setCategories(HashSet<String> categories) {
|
||||||
((CategoriesSpinnerAdapter)binding.categoryAt.getAdapter()).setCategoriesList(categories);
|
((CategoriesAdapter)binding.categoryAt.getAdapter()).setCategoriesList(categories);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void hideAccuracy() {
|
public void hideAccuracy() {
|
||||||
@@ -412,9 +416,6 @@ public class GeofavoriteDetailActivity extends NextcloudMapsStyledActivity imple
|
|||||||
if (v.getId() == R.id.back_bt && this.listener != null) {
|
if (v.getId() == R.id.back_bt && this.listener != null) {
|
||||||
this.listener.onBackPressed();
|
this.listener.onBackPressed();
|
||||||
}
|
}
|
||||||
if (v.getId() == R.id.manual_pos_bt && this.listener != null) {
|
|
||||||
this.listener.onMapEditPressed();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Actions
|
// Actions
|
||||||
if (v.getId() == R.id.action_icon_share && this.listener != null) {
|
if (v.getId() == R.id.action_icon_share && this.listener != null) {
|
||||||
@@ -433,7 +434,6 @@ public class GeofavoriteDetailActivity extends NextcloudMapsStyledActivity imple
|
|||||||
void onSubmit();
|
void onSubmit();
|
||||||
void onMapClicked();
|
void onMapClicked();
|
||||||
void onBackPressed();
|
void onBackPressed();
|
||||||
void onMapEditPressed();
|
|
||||||
void onActionIconShareClicked();
|
void onActionIconShareClicked();
|
||||||
void onActionIconNavClicked();
|
void onActionIconNavClicked();
|
||||||
void onActionIconDeleteClicked();
|
void onActionIconDeleteClicked();
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
package it.danieleverducci.nextcloudmaps.activity.detail;
|
package it.danieleverducci.nextcloudmaps.activity.detail;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
|
||||||
import androidx.lifecycle.LiveData;
|
import androidx.lifecycle.LiveData;
|
||||||
import androidx.lifecycle.MutableLiveData;
|
import androidx.lifecycle.MutableLiveData;
|
||||||
import androidx.lifecycle.ViewModel;
|
import androidx.lifecycle.ViewModel;
|
||||||
@@ -14,8 +16,8 @@ import it.danieleverducci.nextcloudmaps.repository.GeofavoriteRepository;
|
|||||||
public class GeofavoriteDetailActivityViewModel extends ViewModel {
|
public class GeofavoriteDetailActivityViewModel extends ViewModel {
|
||||||
private GeofavoriteRepository mRepo;
|
private GeofavoriteRepository mRepo;
|
||||||
|
|
||||||
public void init() {
|
public void init(Context applicationContext) {
|
||||||
mRepo = GeofavoriteRepository.getInstance();
|
mRepo = GeofavoriteRepository.getInstance(applicationContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Geofavorite getGeofavorite(int id) {
|
public Geofavorite getGeofavorite(int id) {
|
||||||
|
|||||||
@@ -20,6 +20,8 @@ package it.danieleverducci.nextcloudmaps.activity.login;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.util.Log;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.Button;
|
import android.widget.Button;
|
||||||
import android.widget.ProgressBar;
|
import android.widget.ProgressBar;
|
||||||
@@ -41,11 +43,12 @@ import com.nextcloud.android.sso.ui.UiExceptionManager;
|
|||||||
import it.danieleverducci.nextcloudmaps.R;
|
import it.danieleverducci.nextcloudmaps.R;
|
||||||
import it.danieleverducci.nextcloudmaps.activity.NextcloudMapsStyledActivity;
|
import it.danieleverducci.nextcloudmaps.activity.NextcloudMapsStyledActivity;
|
||||||
import it.danieleverducci.nextcloudmaps.activity.main.MainActivity;
|
import it.danieleverducci.nextcloudmaps.activity.main.MainActivity;
|
||||||
|
import it.danieleverducci.nextcloudmaps.api.API;
|
||||||
import it.danieleverducci.nextcloudmaps.api.ApiProvider;
|
import it.danieleverducci.nextcloudmaps.api.ApiProvider;
|
||||||
|
|
||||||
public class LoginActivity extends NextcloudMapsStyledActivity {
|
public class LoginActivity extends NextcloudMapsStyledActivity {
|
||||||
|
private static final String TAG = "LoginActivity";
|
||||||
|
|
||||||
protected ApiProvider mApi;
|
|
||||||
protected ProgressBar progress;
|
protected ProgressBar progress;
|
||||||
protected Button button;
|
protected Button button;
|
||||||
|
|
||||||
@@ -63,18 +66,25 @@ public class LoginActivity extends NextcloudMapsStyledActivity {
|
|||||||
openAccountChooser();
|
openAccountChooser();
|
||||||
});
|
});
|
||||||
|
|
||||||
try {
|
Handler h = new Handler();
|
||||||
ssoAccount = SingleAccountHelper.getCurrentSingleSignOnAccount(getApplicationContext());
|
h.post(() -> {
|
||||||
SingleAccountHelper.setCurrentAccount(getApplicationContext(), ssoAccount.name);
|
try {
|
||||||
accountAccessDone();
|
ssoAccount = SingleAccountHelper.getCurrentSingleSignOnAccount(getApplicationContext());
|
||||||
} catch (NextcloudFilesAppAccountNotFoundException | NoCurrentAccountSelectedException e) {
|
SingleAccountHelper.applyCurrentAccount(getApplicationContext(), ssoAccount.name);
|
||||||
}
|
accountAccessDone();
|
||||||
|
} catch (NextcloudFilesAppAccountNotFoundException | NoCurrentAccountSelectedException e) {
|
||||||
|
Log.e(TAG, "Autologin: " + e.toString());
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
private void openAccountChooser() {
|
private void openAccountChooser() {
|
||||||
try {
|
try {
|
||||||
AccountImporter.pickNewAccount(this);
|
AccountImporter.pickNewAccount(this);
|
||||||
} catch (NextcloudFilesAppNotInstalledException | AndroidGetAccountsPermissionNotGranted e) {
|
} catch (NextcloudFilesAppNotInstalledException | AndroidGetAccountsPermissionNotGranted e) {
|
||||||
UiExceptionManager.showDialogForException(this, 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
|
@Override
|
||||||
public void accountAccessGranted(SingleSignOnAccount account) {
|
public void accountAccessGranted(SingleSignOnAccount account) {
|
||||||
Context l_context = getApplicationContext();
|
Context l_context = getApplicationContext();
|
||||||
SingleAccountHelper.setCurrentAccount(l_context, account.name);
|
SingleAccountHelper.applyCurrentAccount(l_context, account.name);
|
||||||
|
|
||||||
accountAccessDone();
|
accountAccessDone();
|
||||||
}
|
}
|
||||||
@@ -115,9 +125,6 @@ public class LoginActivity extends NextcloudMapsStyledActivity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void accountAccessDone() {
|
private void accountAccessDone() {
|
||||||
Context l_context = getApplicationContext();
|
|
||||||
mApi = new ApiProvider(l_context);
|
|
||||||
|
|
||||||
Intent intent = new Intent(LoginActivity.this, MainActivity.class);
|
Intent intent = new Intent(LoginActivity.this, MainActivity.class);
|
||||||
startActivity(intent);
|
startActivity(intent);
|
||||||
|
|
||||||
|
|||||||
@@ -28,8 +28,6 @@ import android.view.LayoutInflater;
|
|||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.Filter;
|
|
||||||
import android.widget.Filterable;
|
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.PopupMenu;
|
import android.widget.PopupMenu;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
@@ -42,14 +40,13 @@ import org.threeten.bp.format.DateTimeFormatter;
|
|||||||
import org.threeten.bp.format.FormatStyle;
|
import org.threeten.bp.format.FormatStyle;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import it.danieleverducci.nextcloudmaps.R;
|
import it.danieleverducci.nextcloudmaps.R;
|
||||||
import it.danieleverducci.nextcloudmaps.model.Geofavorite;
|
import it.danieleverducci.nextcloudmaps.model.Geofavorite;
|
||||||
|
|
||||||
public class GeofavoriteAdapter extends RecyclerView.Adapter<GeofavoriteAdapter.GeofavoriteViewHolder> implements Filterable {
|
public class GeofavoriteAdapter extends RecyclerView.Adapter<GeofavoriteAdapter.GeofavoriteViewHolder> {
|
||||||
|
|
||||||
public static final String TAG = "GeofavoriteAdapter";
|
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_CATEGORY = 2;
|
||||||
public static final int SORT_BY_DISTANCE = 3;
|
public static final int SORT_BY_DISTANCE = 3;
|
||||||
|
|
||||||
private Context context;
|
private final Context context;
|
||||||
private ItemClickListener itemClickListener;
|
private final ItemClickListener itemClickListener;
|
||||||
private DateTimeFormatter dateFormatter = DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT);
|
private final DateTimeFormatter dateFormatter = DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT);
|
||||||
|
|
||||||
private List<Geofavorite> geofavoriteList = new ArrayList<>();
|
private List<Geofavorite> items = new ArrayList<>();
|
||||||
private List<Geofavorite> geofavoriteListFiltered = new ArrayList<>();
|
|
||||||
private int sortRule = SORT_BY_CREATED;
|
private int sortRule = SORT_BY_CREATED;
|
||||||
|
|
||||||
// Contains the position of the element containing the overflow menu clicked
|
// 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) {
|
public void setGeofavoriteList(@NonNull List<Geofavorite> geofavoriteList) {
|
||||||
this.geofavoriteList = geofavoriteList;
|
this.items.clear();
|
||||||
this.geofavoriteListFiltered = new ArrayList<>(geofavoriteList);
|
this.items.addAll(geofavoriteList);
|
||||||
|
|
||||||
performSort();
|
performSort();
|
||||||
notifyDataSetChanged();
|
notifyDataSetChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Geofavorite get(int position) {
|
public Geofavorite get(int position) {
|
||||||
return geofavoriteListFiltered.get(position);
|
return items.get(position);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getSortRule() {
|
public int getSortRule() {
|
||||||
@@ -106,60 +102,21 @@ public class GeofavoriteAdapter extends RecyclerView.Adapter<GeofavoriteAdapter.
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBindViewHolder(@NonNull GeofavoriteViewHolder holder, int position) {
|
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.tv_category.setText(geofavorite.categoryLetter());
|
||||||
holder.setCategoryColor(
|
holder.setCategoryColor(
|
||||||
geofavorite.categoryColor() == 0 ? context.getColor(R.color.defaultBrand) : geofavorite.categoryColor());
|
geofavorite.categoryColor() == 0 ? context.getColor(R.color.defaultBrand) : geofavorite.categoryColor());
|
||||||
holder.tv_title.setText(Html.fromHtml(geofavorite.getName()));
|
holder.tv_title.setText(Html.fromHtml(geofavorite.getName() == null ? "" : geofavorite.getName()));
|
||||||
holder.tv_content.setText(geofavorite.getComment());
|
holder.tv_content.setText(geofavorite.getComment() == null ? "" : geofavorite.getComment());
|
||||||
holder.tv_date.setText(geofavorite.getLocalDateCreated().format(dateFormatter));
|
holder.tv_date.setText(geofavorite.getLocalDateCreated().format(dateFormatter));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getItemCount() {
|
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 {
|
class GeofavoriteViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
|
||||||
TextView tv_category, tv_title, tv_content, tv_date;
|
TextView tv_category, tv_title, tv_content, tv_date;
|
||||||
ImageView bt_context_menu;
|
ImageView bt_context_menu;
|
||||||
@@ -211,13 +168,13 @@ public class GeofavoriteAdapter extends RecyclerView.Adapter<GeofavoriteAdapter.
|
|||||||
|
|
||||||
private void performSort() {
|
private void performSort() {
|
||||||
if (sortRule == SORT_BY_TITLE) {
|
if (sortRule == SORT_BY_TITLE) {
|
||||||
Collections.sort(geofavoriteListFiltered, Geofavorite.ByTitleAZ);
|
Collections.sort(items, Geofavorite.ByTitleAZ);
|
||||||
} else if (sortRule == SORT_BY_CREATED) {
|
} else if (sortRule == SORT_BY_CREATED) {
|
||||||
Collections.sort(geofavoriteListFiltered, Geofavorite.ByLastCreated);
|
Collections.sort(items, Geofavorite.ByLastCreated);
|
||||||
} else if (sortRule == SORT_BY_CATEGORY) {
|
} else if (sortRule == SORT_BY_CATEGORY) {
|
||||||
Collections.sort(geofavoriteListFiltered, Geofavorite.ByCategory);
|
Collections.sort(items, Geofavorite.ByCategory);
|
||||||
} else if (sortRule == SORT_BY_DISTANCE) {
|
} else if (sortRule == SORT_BY_DISTANCE) {
|
||||||
Collections.sort(geofavoriteListFiltered, Geofavorite.ByDistance);
|
Collections.sort(items, Geofavorite.ByDistance);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,19 +1,21 @@
|
|||||||
package it.danieleverducci.nextcloudmaps.activity.main;
|
package it.danieleverducci.nextcloudmaps.activity.main;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
|
||||||
import androidx.lifecycle.LiveData;
|
import androidx.lifecycle.LiveData;
|
||||||
import androidx.lifecycle.MutableLiveData;
|
|
||||||
import androidx.lifecycle.ViewModel;
|
import androidx.lifecycle.ViewModel;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import it.danieleverducci.nextcloudmaps.model.Geofavorite;
|
import it.danieleverducci.nextcloudmaps.model.Geofavorite;
|
||||||
import it.danieleverducci.nextcloudmaps.repository.GeofavoriteRepository;
|
import it.danieleverducci.nextcloudmaps.repository.GeofavoriteRepository;
|
||||||
|
|
||||||
public class MainActivityViewModel extends ViewModel {
|
public class GeofavoritesFragmentViewModel extends ViewModel {
|
||||||
private GeofavoriteRepository mRepo;
|
private GeofavoriteRepository mRepo;
|
||||||
|
|
||||||
public void init() {
|
public void init(Context applicationContext) {
|
||||||
mRepo = GeofavoriteRepository.getInstance();
|
mRepo = GeofavoriteRepository.getInstance(applicationContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
public LiveData<List<Geofavorite>> getGeofavorites(){
|
public LiveData<List<Geofavorite>> getGeofavorites(){
|
||||||
@@ -25,6 +27,10 @@ public class MainActivityViewModel extends ViewModel {
|
|||||||
mRepo.updateGeofavorites();
|
mRepo.updateGeofavorites();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public LiveData<HashSet<String>> getCategories(){
|
||||||
|
return mRepo.getCategories();
|
||||||
|
}
|
||||||
|
|
||||||
public void deleteGeofavorite(Geofavorite geofav) {
|
public void deleteGeofavorite(Geofavorite geofav) {
|
||||||
mRepo.deleteGeofavorite(geofav);
|
mRepo.deleteGeofavorite(geofav);
|
||||||
}
|
}
|
||||||
@@ -17,162 +17,115 @@
|
|||||||
|
|
||||||
package it.danieleverducci.nextcloudmaps.activity.main;
|
package it.danieleverducci.nextcloudmaps.activity.main;
|
||||||
|
|
||||||
import android.content.DialogInterface;
|
import android.Manifest;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.SharedPreferences;
|
import android.content.pm.PackageManager;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.text.TextUtils;
|
|
||||||
import android.util.Log;
|
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.Toast;
|
|
||||||
|
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.appcompat.app.AlertDialog;
|
import androidx.core.app.ActivityCompat;
|
||||||
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.core.view.GravityCompat;
|
import androidx.core.view.GravityCompat;
|
||||||
import androidx.drawerlayout.widget.DrawerLayout;
|
import androidx.drawerlayout.widget.DrawerLayout;
|
||||||
|
import androidx.fragment.app.Fragment;
|
||||||
import androidx.fragment.app.FragmentManager;
|
import androidx.fragment.app.FragmentManager;
|
||||||
import androidx.fragment.app.FragmentTransaction;
|
import androidx.fragment.app.FragmentTransaction;
|
||||||
import androidx.lifecycle.ViewModelProvider;
|
|
||||||
import androidx.preference.PreferenceManager;
|
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
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.google.android.material.floatingactionbutton.FloatingActionButton;
|
||||||
import com.nextcloud.android.sso.helper.SingleAccountHelper;
|
import com.nextcloud.android.sso.helper.SingleAccountHelper;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import it.danieleverducci.nextcloudmaps.R;
|
import it.danieleverducci.nextcloudmaps.R;
|
||||||
import it.danieleverducci.nextcloudmaps.activity.NextcloudMapsStyledActivity;
|
import it.danieleverducci.nextcloudmaps.activity.NextcloudMapsStyledActivity;
|
||||||
import it.danieleverducci.nextcloudmaps.activity.about.AboutActivity;
|
import it.danieleverducci.nextcloudmaps.activity.about.AboutActivity;
|
||||||
import it.danieleverducci.nextcloudmaps.activity.detail.GeofavoriteDetailActivity;
|
import it.danieleverducci.nextcloudmaps.activity.detail.GeofavoriteDetailActivity;
|
||||||
|
import it.danieleverducci.nextcloudmaps.activity.settings.SettingsActivity;
|
||||||
import it.danieleverducci.nextcloudmaps.activity.login.LoginActivity;
|
import it.danieleverducci.nextcloudmaps.activity.login.LoginActivity;
|
||||||
import it.danieleverducci.nextcloudmaps.activity.main.NavigationAdapter.NavigationItem;
|
import it.danieleverducci.nextcloudmaps.activity.main.NavigationAdapter.NavigationItem;
|
||||||
import it.danieleverducci.nextcloudmaps.activity.main.SortingOrderDialogFragment.OnSortingOrderListener;
|
|
||||||
import it.danieleverducci.nextcloudmaps.activity.mappicker.MapPickerActivity;
|
import it.danieleverducci.nextcloudmaps.activity.mappicker.MapPickerActivity;
|
||||||
import it.danieleverducci.nextcloudmaps.model.Geofavorite;
|
import it.danieleverducci.nextcloudmaps.api.ApiProvider;
|
||||||
import it.danieleverducci.nextcloudmaps.utils.GeoUriParser;
|
import it.danieleverducci.nextcloudmaps.fragments.GeofavoriteListFragment;
|
||||||
import it.danieleverducci.nextcloudmaps.utils.IntentGenerator;
|
import it.danieleverducci.nextcloudmaps.fragments.GeofavoriteMapFragment;
|
||||||
|
import it.danieleverducci.nextcloudmaps.repository.GeofavoriteRepository;
|
||||||
|
import it.danieleverducci.nextcloudmaps.utils.SettingsManager;
|
||||||
|
|
||||||
import static android.view.View.GONE;
|
public class MainActivity extends NextcloudMapsStyledActivity {
|
||||||
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 {
|
|
||||||
|
|
||||||
private static final String TAG = "MainActivity";
|
private static final String TAG = "MainActivity";
|
||||||
|
private static final int PERMISSION_REQUEST_CODE = 3890;
|
||||||
|
|
||||||
private static final String NAVIGATION_KEY_ADD_GEOFAVORITE_FROM_GPS = "add_from_gps";
|
private static final String NAVIGATION_KEY_ADD_GEOFAVORITE_FROM_GPS = "add_from_gps";
|
||||||
private static final String NAVIGATION_KEY_ADD_GEOFAVORITE_FROM_MAP = "add_from_map";
|
private static final String NAVIGATION_KEY_ADD_GEOFAVORITE_FROM_MAP = "add_from_map";
|
||||||
private static final String NAVIGATION_KEY_SHOW_ABOUT = "about";
|
private static final String NAVIGATION_KEY_SHOW_ABOUT = "about";
|
||||||
|
private static final String NAVIGATION_KEY_SETTINGS = "settings";
|
||||||
private static final String NAVIGATION_KEY_SWITCH_ACCOUNT = "switch_account";
|
private static final String NAVIGATION_KEY_SWITCH_ACCOUNT = "switch_account";
|
||||||
|
|
||||||
private SharedPreferences preferences;
|
private ArrayList<OnGpsPermissionGrantedListener> onGpsPermissionGrantedListener = new ArrayList<>();
|
||||||
|
|
||||||
private DrawerLayout drawerLayout;
|
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;
|
private boolean isFabOpen = false;
|
||||||
|
|
||||||
NavigationAdapter navigationCommonAdapter;
|
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
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
setContentView(R.layout.activity_main);
|
setContentView(R.layout.activity_main);
|
||||||
|
|
||||||
preferences = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
|
boolean showMap = SettingsManager.isGeofavoriteListShownAsMap(this);
|
||||||
|
if (showMap)
|
||||||
|
showMap();
|
||||||
|
else
|
||||||
|
showList();
|
||||||
|
|
||||||
int sortRule = preferences.getInt(getString(R.string.setting_sort_by), SORT_BY_CREATED);
|
FloatingActionButton fab = findViewById(R.id.open_fab);
|
||||||
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();
|
|
||||||
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){
|
|
||||||
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);
|
|
||||||
fab.setOnClickListener(view -> openFab(!this.isFabOpen));
|
fab.setOnClickListener(view -> openFab(!this.isFabOpen));
|
||||||
|
|
||||||
fab = findViewById(R.id.add_from_gps);
|
fab = findViewById(R.id.add_from_gps);
|
||||||
@@ -181,51 +134,9 @@ public class MainActivity extends NextcloudMapsStyledActivity implements OnSorti
|
|||||||
fab = findViewById(R.id.add_from_map);
|
fab = findViewById(R.id.add_from_map);
|
||||||
fab.setOnClickListener(view -> addGeofavoriteFromMap());
|
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();
|
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);
|
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
|
@Override
|
||||||
@@ -234,6 +145,13 @@ public class MainActivity extends NextcloudMapsStyledActivity implements OnSorti
|
|||||||
super.onPause();
|
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() {
|
private void setupNavigationMenu() {
|
||||||
ArrayList<NavigationItem> navItems = new ArrayList<>();
|
ArrayList<NavigationItem> navItems = new ArrayList<>();
|
||||||
|
|
||||||
@@ -248,6 +166,9 @@ public class MainActivity extends NextcloudMapsStyledActivity implements OnSorti
|
|||||||
case NAVIGATION_KEY_SHOW_ABOUT:
|
case NAVIGATION_KEY_SHOW_ABOUT:
|
||||||
show_about();
|
show_about();
|
||||||
break;
|
break;
|
||||||
|
case NAVIGATION_KEY_SETTINGS:
|
||||||
|
show_settings();
|
||||||
|
break;
|
||||||
case NAVIGATION_KEY_SWITCH_ACCOUNT:
|
case NAVIGATION_KEY_SWITCH_ACCOUNT:
|
||||||
switch_account();
|
switch_account();
|
||||||
break;
|
break;
|
||||||
@@ -257,6 +178,7 @@ public class MainActivity extends NextcloudMapsStyledActivity implements OnSorti
|
|||||||
navItems.add(new NavigationItem(NAVIGATION_KEY_ADD_GEOFAVORITE_FROM_GPS, getString(R.string.new_geobookmark_gps), R.drawable.ic_add_gps));
|
navItems.add(new NavigationItem(NAVIGATION_KEY_ADD_GEOFAVORITE_FROM_GPS, getString(R.string.new_geobookmark_gps), R.drawable.ic_add_gps));
|
||||||
navItems.add(new NavigationItem(NAVIGATION_KEY_ADD_GEOFAVORITE_FROM_MAP, getString(R.string.new_geobookmark_map), R.drawable.ic_add_map));
|
navItems.add(new NavigationItem(NAVIGATION_KEY_ADD_GEOFAVORITE_FROM_MAP, getString(R.string.new_geobookmark_map), R.drawable.ic_add_map));
|
||||||
navItems.add(new NavigationItem(NAVIGATION_KEY_SHOW_ABOUT, getString(R.string.about), R.drawable.ic_info_grey));
|
navItems.add(new NavigationItem(NAVIGATION_KEY_SHOW_ABOUT, getString(R.string.about), R.drawable.ic_info_grey));
|
||||||
|
navItems.add(new NavigationItem(NAVIGATION_KEY_SETTINGS, getString(R.string.settings), R.drawable.ic_settings_grey));
|
||||||
navItems.add(new NavigationItem(NAVIGATION_KEY_SWITCH_ACCOUNT, getString(R.string.switch_account), R.drawable.ic_logout_grey));
|
navItems.add(new NavigationItem(NAVIGATION_KEY_SWITCH_ACCOUNT, getString(R.string.switch_account), R.drawable.ic_logout_grey));
|
||||||
navigationCommonAdapter.setItems(navItems);
|
navigationCommonAdapter.setItems(navItems);
|
||||||
|
|
||||||
@@ -264,22 +186,6 @@ public class MainActivity extends NextcloudMapsStyledActivity implements OnSorti
|
|||||||
navigationMenuCommon.setAdapter(navigationCommonAdapter);
|
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() {
|
private void addGeofavoriteFromGps() {
|
||||||
startActivity(
|
startActivity(
|
||||||
new Intent(this, GeofavoriteDetailActivity.class)
|
new Intent(this, GeofavoriteDetailActivity.class)
|
||||||
@@ -292,77 +198,21 @@ public class MainActivity extends NextcloudMapsStyledActivity implements OnSorti
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void show_settings() {
|
||||||
|
startActivity(new Intent(this, SettingsActivity.class));
|
||||||
|
}
|
||||||
|
|
||||||
private void show_about() {
|
private void show_about() {
|
||||||
startActivity(new Intent(this, AboutActivity.class));
|
startActivity(new Intent(this, AboutActivity.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void switch_account() {
|
public void switch_account() {
|
||||||
SingleAccountHelper.setCurrentAccount(this, null);
|
ApiProvider.logout();
|
||||||
|
GeofavoriteRepository.resetInstance();
|
||||||
|
SingleAccountHelper.applyCurrentAccount(this, null);
|
||||||
Intent intent = new Intent(MainActivity.this, LoginActivity.class);
|
Intent intent = new Intent(MainActivity.this, LoginActivity.class);
|
||||||
startActivity(intent);
|
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()))
|
|
||||||
.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) {
|
private void openFab(boolean open) {
|
||||||
@@ -384,4 +234,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";
|
public static final String SORTING_ORDER_FRAGMENT = "SORTING_ORDER_FRAGMENT";
|
||||||
private static final String KEY_SORT_ORDER = "SORT_ORDER";
|
private static final String KEY_SORT_ORDER = "SORT_ORDER";
|
||||||
|
|
||||||
|
private OnSortingOrderListener onSortingOrderListener;
|
||||||
private View mView;
|
private View mView;
|
||||||
private View[] mTaggedViews;
|
private View[] mTaggedViews;
|
||||||
private Button mCancel;
|
private Button mCancel;
|
||||||
@@ -90,6 +91,10 @@ public class SortingOrderDialogFragment extends DialogFragment {
|
|||||||
return mView;
|
return mView;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setOnSortingOrderListener(OnSortingOrderListener listener) {
|
||||||
|
this.onSortingOrderListener = listener;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* find all relevant UI elements and set their values.
|
* find all relevant UI elements and set their values.
|
||||||
* TODO: this is REALLY ugly.
|
* TODO: this is REALLY ugly.
|
||||||
@@ -171,8 +176,8 @@ public class SortingOrderDialogFragment extends DialogFragment {
|
|||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
dismissAllowingStateLoss();
|
dismissAllowingStateLoss();
|
||||||
((SortingOrderDialogFragment.OnSortingOrderListener) getActivity())
|
if (onSortingOrderListener != null)
|
||||||
.onSortingOrderChosen((int) v.getTag());
|
onSortingOrderListener.onSortingOrderChosen((int) v.getTag());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,25 +15,19 @@ import android.view.inputmethod.InputMethodManager;
|
|||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
|
||||||
import androidx.core.app.ActivityCompat;
|
import androidx.core.app.ActivityCompat;
|
||||||
import androidx.preference.PreferenceManager;
|
|
||||||
|
|
||||||
import org.osmdroid.api.IGeoPoint;
|
import org.osmdroid.api.IGeoPoint;
|
||||||
import org.osmdroid.api.IMapController;
|
import org.osmdroid.api.IMapController;
|
||||||
import org.osmdroid.config.Configuration;
|
|
||||||
import org.osmdroid.config.IConfigurationProvider;
|
|
||||||
import org.osmdroid.events.MapListener;
|
import org.osmdroid.events.MapListener;
|
||||||
import org.osmdroid.events.ScrollEvent;
|
import org.osmdroid.events.ScrollEvent;
|
||||||
import org.osmdroid.events.ZoomEvent;
|
import org.osmdroid.events.ZoomEvent;
|
||||||
import org.osmdroid.util.GeoPoint;
|
import org.osmdroid.util.GeoPoint;
|
||||||
import org.osmdroid.views.CustomZoomButtonsController;
|
import org.osmdroid.views.CustomZoomButtonsController;
|
||||||
import org.osmdroid.views.MapView;
|
import org.osmdroid.views.MapView;
|
||||||
import org.osmdroid.views.Projection;
|
|
||||||
|
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
import it.danieleverducci.nextcloudmaps.BuildConfig;
|
|
||||||
import it.danieleverducci.nextcloudmaps.R;
|
import it.danieleverducci.nextcloudmaps.R;
|
||||||
import it.danieleverducci.nextcloudmaps.activity.NextcloudMapsStyledActivity;
|
import it.danieleverducci.nextcloudmaps.activity.NextcloudMapsStyledActivity;
|
||||||
import it.danieleverducci.nextcloudmaps.activity.detail.GeofavoriteDetailActivity;
|
import it.danieleverducci.nextcloudmaps.activity.detail.GeofavoriteDetailActivity;
|
||||||
@@ -64,7 +58,7 @@ public class MapPickerActivity extends NextcloudMapsStyledActivity {
|
|||||||
@Override
|
@Override
|
||||||
public void onConfirmButtonPressed() {
|
public void onConfirmButtonPressed() {
|
||||||
double[] coords = mViewHolder.getCurrentCoordinates();
|
double[] coords = mViewHolder.getCurrentCoordinates();
|
||||||
Uri geoUri = GeoUriParser.createUri(coords[0], coords[1], null);
|
Uri geoUri = GeoUriParser.createGeoUri(coords[0], coords[1], null);
|
||||||
Intent i = new Intent(MapPickerActivity.this, GeofavoriteDetailActivity.class);
|
Intent i = new Intent(MapPickerActivity.this, GeofavoriteDetailActivity.class);
|
||||||
i.setData(geoUri);
|
i.setData(geoUri);
|
||||||
startActivity(i);
|
startActivity(i);
|
||||||
|
|||||||
@@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
* Nextcloud Maps Geofavorites for Android
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package it.danieleverducci.nextcloudmaps.activity.settings;
|
||||||
|
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.widget.Switch;
|
||||||
|
|
||||||
|
import androidx.appcompat.app.ActionBar;
|
||||||
|
import androidx.appcompat.widget.Toolbar;
|
||||||
|
|
||||||
|
import it.danieleverducci.nextcloudmaps.R;
|
||||||
|
import it.danieleverducci.nextcloudmaps.activity.NextcloudMapsStyledActivity;
|
||||||
|
import it.danieleverducci.nextcloudmaps.utils.SettingsManager;
|
||||||
|
|
||||||
|
public class SettingsActivity extends NextcloudMapsStyledActivity {
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
setContentView(R.layout.activity_settings);
|
||||||
|
|
||||||
|
Toolbar toolbar = findViewById(R.id.toolbar);
|
||||||
|
setSupportActionBar(toolbar);
|
||||||
|
|
||||||
|
ActionBar actionBar = getSupportActionBar();
|
||||||
|
if (actionBar != null) {
|
||||||
|
actionBar.setDisplayShowTitleEnabled(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
Switch useGoogleMapsSwitch = findViewById(R.id.use_google_maps_switch);
|
||||||
|
useGoogleMapsSwitch.setChecked(SettingsManager.isUseGoogleMaps(this));
|
||||||
|
useGoogleMapsSwitch.setOnCheckedChangeListener((buttonView, isChecked) ->
|
||||||
|
SettingsManager.setUseGoogleMaps(SettingsActivity.this, isChecked)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onSupportNavigateUp() {
|
||||||
|
finish();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -24,6 +24,7 @@ import android.content.Context;
|
|||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
import com.google.gson.GsonBuilder;
|
import com.google.gson.GsonBuilder;
|
||||||
import com.nextcloud.android.sso.api.NextcloudAPI;
|
import com.nextcloud.android.sso.api.NextcloudAPI;
|
||||||
@@ -35,47 +36,27 @@ import com.nextcloud.android.sso.model.SingleSignOnAccount;
|
|||||||
import retrofit2.NextcloudRetrofitApiBuilder;
|
import retrofit2.NextcloudRetrofitApiBuilder;
|
||||||
|
|
||||||
public class ApiProvider {
|
public class ApiProvider {
|
||||||
private final String TAG = ApiProvider.class.getCanonicalName();
|
private static final String TAG = ApiProvider.class.getCanonicalName();
|
||||||
|
|
||||||
@NonNull
|
|
||||||
protected Context context;
|
|
||||||
protected static API mApi;
|
protected static API mApi;
|
||||||
|
|
||||||
protected static String ssoAccountName;
|
@Nullable
|
||||||
|
public static API getAPI(Context context) {
|
||||||
|
if (mApi == null) {
|
||||||
|
try {
|
||||||
|
SingleSignOnAccount ssoAccount = SingleAccountHelper.getCurrentSingleSignOnAccount(context);
|
||||||
|
NextcloudAPI nextcloudAPI = new NextcloudAPI(context, ssoAccount, new GsonBuilder().create());
|
||||||
|
|
||||||
public ApiProvider(Context context) {
|
mApi = new NextcloudRetrofitApiBuilder(nextcloudAPI, API.mApiEndpoint).create(API.class);
|
||||||
this.context = context;
|
} catch (NextcloudFilesAppAccountNotFoundException | NoCurrentAccountSelectedException e) {
|
||||||
initSsoApi(new NextcloudAPI.ApiConnectedListener() {
|
Log.d(TAG, "setAccout() called with: ex = [" + e + "]");
|
||||||
@Override
|
|
||||||
public void onConnected() {
|
|
||||||
Log.d(TAG, "Connected to Nextcloud instance");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onError(Exception ex) {
|
|
||||||
Log.d(TAG, "Unable to connect to Nextcloud instance: " + ex.toString());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public void initSsoApi(final NextcloudAPI.ApiConnectedListener callback) {
|
|
||||||
try {
|
|
||||||
SingleSignOnAccount ssoAccount = SingleAccountHelper.getCurrentSingleSignOnAccount(context);
|
|
||||||
NextcloudAPI nextcloudAPI = new NextcloudAPI(context, ssoAccount, new GsonBuilder().create(), callback);
|
|
||||||
|
|
||||||
ssoAccountName = ssoAccount.name;
|
|
||||||
mApi = new NextcloudRetrofitApiBuilder(nextcloudAPI, API.mApiEndpoint).create(API.class);
|
|
||||||
} catch (NextcloudFilesAppAccountNotFoundException | NoCurrentAccountSelectedException e) {
|
|
||||||
Log.d(TAG, "setAccout() called with: ex = [" + e + "]");
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public static API getAPI() {
|
|
||||||
return mApi;
|
return mApi;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getAccountName() {
|
public static void logout() {
|
||||||
return ssoAccountName;
|
mApi = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -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.graphics.Color;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
import android.widget.Filter;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
@@ -34,7 +35,9 @@ import org.threeten.bp.LocalDate;
|
|||||||
import org.threeten.bp.ZoneId;
|
import org.threeten.bp.ZoneId;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import it.danieleverducci.nextcloudmaps.utils.GeoUriParser;
|
import it.danieleverducci.nextcloudmaps.utils.GeoUriParser;
|
||||||
|
|
||||||
@@ -164,7 +167,10 @@ public class Geofavorite implements Serializable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Uri getGeoUri() {
|
public Uri getGeoUri() {
|
||||||
return GeoUriParser.createUri(this.lat, this.lng, this.name);
|
return GeoUriParser.createGeoUri(this.lat, this.lng, this.name);
|
||||||
|
}
|
||||||
|
public Uri getGmapsUri() {
|
||||||
|
return GeoUriParser.createGmapsUri(this.lat, this.lng);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean valid() {
|
public boolean valid() {
|
||||||
@@ -198,23 +204,11 @@ public class Geofavorite implements Serializable {
|
|||||||
* @return the generated color or null for the default category
|
* @return the generated color or null for the default category
|
||||||
*/
|
*/
|
||||||
public int categoryColor() {
|
public int categoryColor() {
|
||||||
// If category is default, return null: will be used Nextcloud's accent
|
return categoryColorFromName(this.category);
|
||||||
if (this.category.equals(DEFAULT_CATEGORY))
|
|
||||||
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) });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public String categoryLetter() {
|
public String categoryLetter() {
|
||||||
if (category == null || category.length() == 0)
|
if (category == null || category.length() == 0 || category.equals(DEFAULT_CATEGORY))
|
||||||
return "";
|
|
||||||
if (category.equals(DEFAULT_CATEGORY))
|
|
||||||
return "\u2022";
|
return "\u2022";
|
||||||
return category.substring(0,1);
|
return category.substring(0,1);
|
||||||
}
|
}
|
||||||
@@ -225,4 +219,27 @@ public class Geofavorite implements Serializable {
|
|||||||
return "[" + getName() + " (" + getLat() + "," + getLng() + ")]";
|
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) });
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
package it.danieleverducci.nextcloudmaps.repository;
|
package it.danieleverducci.nextcloudmaps.repository;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
|
||||||
import androidx.lifecycle.MutableLiveData;
|
import androidx.lifecycle.MutableLiveData;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -29,13 +29,23 @@ public class GeofavoriteRepository {
|
|||||||
private MutableLiveData<Boolean> mIsUpdating = new MutableLiveData<>(false);
|
private MutableLiveData<Boolean> mIsUpdating = new MutableLiveData<>(false);
|
||||||
private SingleLiveEvent<Boolean> mOnFinished = new SingleLiveEvent<>();
|
private SingleLiveEvent<Boolean> mOnFinished = new SingleLiveEvent<>();
|
||||||
|
|
||||||
public static GeofavoriteRepository getInstance() {
|
private Context applicationContext;
|
||||||
|
|
||||||
|
public GeofavoriteRepository(Context applicationContext) {
|
||||||
|
this.applicationContext = applicationContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static GeofavoriteRepository getInstance(Context applicationContext) {
|
||||||
if(instance == null){
|
if(instance == null){
|
||||||
instance = new GeofavoriteRepository();
|
instance = new GeofavoriteRepository(applicationContext);
|
||||||
}
|
}
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void resetInstance() {
|
||||||
|
instance = null;
|
||||||
|
}
|
||||||
|
|
||||||
public MutableLiveData<List<Geofavorite>> getGeofavorites(){
|
public MutableLiveData<List<Geofavorite>> getGeofavorites(){
|
||||||
if (mGeofavorites == null) {
|
if (mGeofavorites == null) {
|
||||||
mGeofavorites = new MutableLiveData<>();
|
mGeofavorites = new MutableLiveData<>();
|
||||||
@@ -59,7 +69,7 @@ public class GeofavoriteRepository {
|
|||||||
public void updateGeofavorites() {
|
public void updateGeofavorites() {
|
||||||
mIsUpdating.postValue(true);
|
mIsUpdating.postValue(true);
|
||||||
// Obtain geofavorites
|
// Obtain geofavorites
|
||||||
Call<List<Geofavorite>> call = ApiProvider.getAPI().getGeofavorites();
|
Call<List<Geofavorite>> call = ApiProvider.getAPI(this.applicationContext).getGeofavorites();
|
||||||
call.enqueue(new Callback<List<Geofavorite>>() {
|
call.enqueue(new Callback<List<Geofavorite>>() {
|
||||||
@Override
|
@Override
|
||||||
public void onResponse(@NonNull Call<List<Geofavorite>> call, @NonNull Response<List<Geofavorite>> response) {
|
public void onResponse(@NonNull Call<List<Geofavorite>> call, @NonNull Response<List<Geofavorite>> response) {
|
||||||
@@ -94,10 +104,10 @@ public class GeofavoriteRepository {
|
|||||||
Call<Geofavorite> call;
|
Call<Geofavorite> call;
|
||||||
if (geofav.getId() == 0) {
|
if (geofav.getId() == 0) {
|
||||||
// New geofavorite
|
// New geofavorite
|
||||||
call = ApiProvider.getAPI().createGeofavorite(geofav);
|
call = ApiProvider.getAPI(this.applicationContext).createGeofavorite(geofav);
|
||||||
} else {
|
} else {
|
||||||
// Update existing geofavorite
|
// Update existing geofavorite
|
||||||
call = ApiProvider.getAPI().updateGeofavorite(geofav.getId(), geofav);
|
call = ApiProvider.getAPI(this.applicationContext).updateGeofavorite(geofav.getId(), geofav);
|
||||||
}
|
}
|
||||||
call.enqueue(new Callback<Geofavorite>() {
|
call.enqueue(new Callback<Geofavorite>() {
|
||||||
@Override
|
@Override
|
||||||
@@ -129,7 +139,7 @@ public class GeofavoriteRepository {
|
|||||||
public void deleteGeofavorite(Geofavorite geofav) {
|
public void deleteGeofavorite(Geofavorite geofav) {
|
||||||
mIsUpdating.postValue(true);
|
mIsUpdating.postValue(true);
|
||||||
// Delete Geofavorite
|
// Delete Geofavorite
|
||||||
Call<Geofavorite> call = ApiProvider.getAPI().deleteGeofavorite(geofav.getId());
|
Call<Geofavorite> call = ApiProvider.getAPI(this.applicationContext).deleteGeofavorite(geofav.getId());
|
||||||
call.enqueue(new Callback<Geofavorite>() {
|
call.enqueue(new Callback<Geofavorite>() {
|
||||||
@Override
|
@Override
|
||||||
public void onResponse(Call<Geofavorite> call, Response<Geofavorite> response) {
|
public void onResponse(Call<Geofavorite> call, Response<Geofavorite> response) {
|
||||||
@@ -156,7 +166,9 @@ public class GeofavoriteRepository {
|
|||||||
private void updateCategories(List<Geofavorite> geofavs) {
|
private void updateCategories(List<Geofavorite> geofavs) {
|
||||||
HashSet<String> categories = new HashSet<>();
|
HashSet<String> categories = new HashSet<>();
|
||||||
for (Geofavorite g : geofavs) {
|
for (Geofavorite g : geofavs) {
|
||||||
categories.add(g.getCategory());
|
String cat = g.getCategory();
|
||||||
|
if (cat != null)
|
||||||
|
categories.add(cat);
|
||||||
}
|
}
|
||||||
mCategories.postValue(categories);
|
mCategories.postValue(categories);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,35 +10,79 @@ import it.danieleverducci.nextcloudmaps.model.Geofavorite;
|
|||||||
|
|
||||||
public class GeoUriParser {
|
public class GeoUriParser {
|
||||||
private static final Pattern PATTERN_GEO = Pattern.compile("geo:(-?[\\d.]+),(-?[\\d.]+)");
|
private static final Pattern PATTERN_GEO = Pattern.compile("geo:(-?[\\d.]+),(-?[\\d.]+)");
|
||||||
|
// Try to match not only geoUri but also Google Maps Uri
|
||||||
|
private static final Pattern PATTERN_BROAD = Pattern.compile(
|
||||||
|
"(?:@|&query=|&ce\nter=|geo:|#map=\\d{1,2}\\/)(-?\\d{1,2}\\.\\d+)(?:,|%2C|\\/)(-?\\d{1,3}\\.\\d{1,10})"
|
||||||
|
);
|
||||||
|
|
||||||
public static double[] parseUri(Uri uri) throws IllegalArgumentException {
|
/**
|
||||||
|
* Parses an URI into latitude and longitude
|
||||||
|
* @param uri to parse
|
||||||
|
* @param strict if true, the uri must be a valid geo: uri, otherwise a broader check is applied to include other uris, like Google Maps ones
|
||||||
|
* @return the parsed coordinates in an array [lat,lon]
|
||||||
|
* @throws IllegalArgumentException if the url could not be parsed
|
||||||
|
*/
|
||||||
|
public static double[] parseUri(Uri uri, boolean strict) throws IllegalArgumentException {
|
||||||
if (uri == null)
|
if (uri == null)
|
||||||
throw new IllegalArgumentException("no uri");
|
throw new IllegalArgumentException("no uri");
|
||||||
|
|
||||||
Matcher m = PATTERN_GEO.matcher(uri.toString());
|
// Try to extract coordinates in uri string with regexp
|
||||||
if (m.find() && m.groupCount() == 2) {
|
Pattern pattern = strict ? PATTERN_GEO : PATTERN_BROAD;
|
||||||
String sLat = m.group(1);
|
Matcher m = pattern.matcher(uri.toString());
|
||||||
String sLon = m.group(2);
|
if (!m.find() || m.groupCount() != 2)
|
||||||
try {
|
throw new IllegalArgumentException("unable to parse uri: unable to find coordinates in uri");
|
||||||
return new double[]{Double.parseDouble(sLat), Double.parseDouble(sLon)};
|
|
||||||
} catch (NumberFormatException e) {
|
// Obtain coordinates from regexp result
|
||||||
throw new IllegalArgumentException("unable to parse uri");
|
String sLat = m.group(1);
|
||||||
}
|
String sLon = m.group(2);
|
||||||
} else {
|
double[] coords = null;
|
||||||
throw new IllegalArgumentException("unable to parse uri");
|
try {
|
||||||
|
// Check coordinates are numeric
|
||||||
|
coords = new double[]{Double.parseDouble(sLat), Double.parseDouble(sLon)};
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
throw new IllegalArgumentException("unable to parse uri: coordinates are not double");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check coordinates validity
|
||||||
|
String error = checkCoordsValidity(coords[0], coords[1]);
|
||||||
|
if (error != null)
|
||||||
|
throw new IllegalArgumentException(error);
|
||||||
|
|
||||||
|
return coords;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Uri createUri(double lat, double lon, String name) {
|
public static Uri createGeoUri(double lat, double lon, String name) {
|
||||||
// Check coords validity
|
String error = checkCoordsValidity(lat, lon);
|
||||||
if (lon <= -180 || lon >= 180 )
|
if (error != null)
|
||||||
throw new IllegalArgumentException("Invalid longitude: " + lon);
|
throw new IllegalArgumentException(error);
|
||||||
if (lat <= -90 || lat >= 90)
|
|
||||||
throw new IllegalArgumentException("Invalid latitude: " + lat);
|
|
||||||
|
|
||||||
String uriStr = "geo:" + lat + "," + lon;
|
String uriStr = "geo:" + lat + "," + lon;
|
||||||
if (name != null)
|
if (name != null)
|
||||||
uriStr += "(" + name + ")";
|
uriStr += "(" + name + ")";
|
||||||
return Uri.parse(uriStr);
|
return Uri.parse(uriStr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Uri createGmapsUri(double lat, double lon) {
|
||||||
|
String error = checkCoordsValidity(lat, lon);
|
||||||
|
if (error != null)
|
||||||
|
throw new IllegalArgumentException(error);
|
||||||
|
|
||||||
|
String uriStr = "https://www.google.com/maps/search/?api=1&query=" + lat + "," + lon;
|
||||||
|
return Uri.parse(uriStr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks a latitude/longitude is valid
|
||||||
|
* @param lat latitude
|
||||||
|
* @param lon longitude
|
||||||
|
* @return null if valid, a string containing an error otherwise
|
||||||
|
*/
|
||||||
|
private static String checkCoordsValidity(double lat, double lon) {
|
||||||
|
// Check coords validity
|
||||||
|
if (lon <= -180 || lon >= 180 )
|
||||||
|
return "Invalid longitude: " + lon;
|
||||||
|
if (lat <= -90 || lat >= 90)
|
||||||
|
return "Invalid latitude: " + lat;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -13,6 +13,7 @@ public class IntentGenerator {
|
|||||||
i.setAction(Intent.ACTION_SEND);
|
i.setAction(Intent.ACTION_SEND);
|
||||||
i.setType("text/plain");
|
i.setType("text/plain");
|
||||||
String shareMessage = context.getString(R.string.share_message)
|
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("{lat}", ""+item.getLat())
|
||||||
.replace("{lng}", ""+item.getLng());
|
.replace("{lng}", ""+item.getLng());
|
||||||
i.putExtra(Intent.EXTRA_TEXT, shareMessage );
|
i.putExtra(Intent.EXTRA_TEXT, shareMessage );
|
||||||
@@ -22,7 +23,10 @@ public class IntentGenerator {
|
|||||||
public static Intent newGeoUriIntent(Context context, Geofavorite item) {
|
public static Intent newGeoUriIntent(Context context, Geofavorite item) {
|
||||||
Intent i = new Intent();
|
Intent i = new Intent();
|
||||||
i.setAction(Intent.ACTION_VIEW);
|
i.setAction(Intent.ACTION_VIEW);
|
||||||
i.setData(item.getGeoUri());
|
i.setData(
|
||||||
|
SettingsManager.isUseGoogleMaps(context)
|
||||||
|
? item.getGmapsUri() : item.getGeoUri()
|
||||||
|
);
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,68 @@
|
|||||||
|
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";
|
||||||
|
static private final String SETTING_USE_GOOGLE_MAPS = "SETTING_USE_GOOGLE_MAPS";
|
||||||
|
|
||||||
|
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 boolean isUseGoogleMaps(Context context) {
|
||||||
|
return PreferenceManager.getDefaultSharedPreferences(context)
|
||||||
|
.getBoolean(SETTING_USE_GOOGLE_MAPS, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setUseGoogleMaps(Context context, boolean value) {
|
||||||
|
PreferenceManager.getDefaultSharedPreferences(context)
|
||||||
|
.edit().putBoolean(SETTING_USE_GOOGLE_MAPS, value).apply();
|
||||||
|
}
|
||||||
|
|
||||||
|
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"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
<item
|
<item>
|
||||||
android:left="8dp"
|
|
||||||
android:right="8dp"
|
|
||||||
android:top="8dp"
|
|
||||||
android:bottom="8dp">
|
|
||||||
<shape
|
<shape
|
||||||
android:shape="oval">
|
android:shape="oval">
|
||||||
<solid android:color="@color/defaultBrandAlpha"/>
|
<solid android:color="@color/defaultBrandAlpha"/>
|
||||||
|
|||||||
@@ -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:height="24dp"
|
||||||
android:viewportWidth="24"
|
android:viewportWidth="24"
|
||||||
android:viewportHeight="24"
|
android:viewportHeight="24"
|
||||||
android:tint="?attr/colorControlNormal">
|
android:tint="?android:attr/colorControlNormal">
|
||||||
<path
|
<path
|
||||||
android:fillColor="@android:color/white"
|
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"/>
|
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:height="24dp"
|
||||||
android:viewportWidth="24"
|
android:viewportWidth="24"
|
||||||
android:viewportHeight="24"
|
android:viewportHeight="24"
|
||||||
android:tint="?attr/colorControlNormal">
|
android:tint="?android:attr/colorControlNormal">
|
||||||
<path
|
<path
|
||||||
android:fillColor="@android:color/white"
|
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"/>
|
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:height="24dp"
|
||||||
android:viewportWidth="24"
|
android:viewportWidth="24"
|
||||||
android:viewportHeight="24"
|
android:viewportHeight="24"
|
||||||
android:tint="?attr/colorControlNormal">
|
android:tint="?android:attr/colorControlNormal">
|
||||||
<path
|
<path
|
||||||
android:fillColor="@android:color/white"
|
android:fillColor="@android:color/white"
|
||||||
android:pathData="M12,2l-5.5,9h11z"/>
|
android:pathData="M12,2l-5.5,9h11z"/>
|
||||||
|
|||||||
@@ -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>
|
||||||
@@ -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:height="24dp"
|
||||||
android:viewportWidth="24"
|
android:viewportWidth="24"
|
||||||
android:viewportHeight="24"
|
android:viewportHeight="24"
|
||||||
android:tint="?attr/colorControlNormal">
|
android:tint="?android:attr/colorControlNormal">
|
||||||
<path
|
<path
|
||||||
android:fillColor="@android:color/white"
|
android:fillColor="@android:color/white"
|
||||||
android:pathData="M21,3L3,10.53v0.98l6.84,2.65L12.48,21h0.98L21,3z"/>
|
android:pathData="M21,3L3,10.53v0.98l6.84,2.65L12.48,21h0.98L21,3z"/>
|
||||||
|
|||||||
@@ -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>
|
||||||
@@ -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:height="24dp"
|
||||||
android:viewportWidth="24"
|
android:viewportWidth="24"
|
||||||
android:viewportHeight="24"
|
android:viewportHeight="24"
|
||||||
android:tint="?attr/colorControlNormal">
|
android:tint="?android:attr/colorControlNormal">
|
||||||
<path
|
<path
|
||||||
android:fillColor="@android:color/white"
|
android:fillColor="@android:color/white"
|
||||||
android:pathData="M9,16.17L4.83,12l-1.42,1.41L9,19 21,7l-1.41,-1.41z"/>
|
android:pathData="M9,16.17L4.83,12l-1.42,1.41L9,19 21,7l-1.41,-1.41z"/>
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
<!--
|
||||||
|
Material Design Settings icon by Google
|
||||||
|
Licensed under the Apache License, Version 2.0
|
||||||
|
https://www.apache.org/licenses/LICENSE-2.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="#757575">
|
||||||
|
<path
|
||||||
|
android:fillColor="#757575"
|
||||||
|
android:pathData="M19.14,12.94c0.04,-0.3 0.06,-0.61 0.06,-0.94c0,-0.32 -0.02,-0.64 -0.07,-0.94l2.03,-1.58a0.49,0.49 0,0 0,0.12 -0.61l-1.92,-3.32a0.49,0.49 0,0 0,-0.59 -0.22l-2.39,0.96c-0.5,-0.38 -1.03,-0.7 -1.62,-0.94L14.4,2.81a0.48,0.48 0,0 0,-0.47 -0.41h-3.84c-0.24,0 -0.43,0.17 -0.47,0.41L9.25,5.35C8.66,5.59 8.12,5.92 7.63,6.29L5.24,5.33a0.49,0.49 0,0 0,-0.59 0.22L2.74,8.87a0.48,0.48 0,0 0,0.12 0.61l2.03,1.58C4.84,11.36 4.8,11.69 4.8,12s0.02,0.64 0.07,0.94l-2.03,1.58a0.49,0.49 0,0 0,-0.12 0.61l1.92,3.32c0.12,0.22 0.37,0.29 0.59,0.22l2.39,-0.96c0.5,0.38 1.03,0.7 1.62,0.94l0.36,2.54c0.05,0.24 0.24,0.41 0.48,0.41h3.84c0.24,0 0.44,-0.17 0.47,-0.41l0.36,-2.54c0.59,-0.24 1.13,-0.56 1.62,-0.94l2.39,0.96c0.22,0.08 0.47,0 0.59,-0.22l1.92,-3.32c0.12,-0.22 0.07,-0.47 -0.12,-0.61L19.14,12.94zM12,15.6A3.6,3.6 0,1 1,12 8.4a3.6,3.6 0,0 1,0 7.2z"/>
|
||||||
|
</vector>
|
||||||
@@ -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>
|
||||||
@@ -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>
|
||||||
@@ -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
|
<androidx.appcompat.widget.Toolbar
|
||||||
android:id="@+id/toolbar"
|
android:id="@+id/toolbar"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="?attr/actionBarSize"
|
android:layout_height="?android:attr/actionBarSize"
|
||||||
app:contentInsetStartWithNavigation="0dp"
|
app:contentInsetStartWithNavigation="0dp"
|
||||||
app:navigationIcon="@drawable/ic_back_grey"
|
app:navigationIcon="@drawable/ic_back_grey"
|
||||||
app:titleMarginStart="0dp"/>
|
app:titleMarginStart="0dp"/>
|
||||||
|
|||||||
@@ -43,7 +43,7 @@
|
|||||||
<androidx.appcompat.widget.Toolbar
|
<androidx.appcompat.widget.Toolbar
|
||||||
android:id="@+id/toolbar"
|
android:id="@+id/toolbar"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="?attr/actionBarSize"
|
android:layout_height="?android:attr/actionBarSize"
|
||||||
app:contentInsetStart="0dp"
|
app:contentInsetStart="0dp"
|
||||||
app:layout_collapseMode="pin"
|
app:layout_collapseMode="pin"
|
||||||
android:background="@android:color/transparent">
|
android:background="@android:color/transparent">
|
||||||
@@ -51,25 +51,26 @@
|
|||||||
<!-- Back button -->
|
<!-- Back button -->
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/back_bt"
|
android:id="@+id/back_bt"
|
||||||
android:layout_width="?attr/actionBarSize"
|
android:layout_width="40dp"
|
||||||
android:layout_height="?attr/actionBarSize"
|
android:layout_height="40dp"
|
||||||
android:layout_gravity="start"
|
android:layout_gravity="start"
|
||||||
android:padding="16dp"
|
android:layout_margin="8dp"
|
||||||
|
android:padding="8dp"
|
||||||
android:src="@drawable/ic_back_grey"
|
android:src="@drawable/ic_back_grey"
|
||||||
app:tint="@color/white"
|
app:tint="@color/white"
|
||||||
android:background="@drawable/floating_semitransparent_button_background"/>
|
android:background="@drawable/floating_semitransparent_button_background"/>
|
||||||
|
|
||||||
<!-- Manual position button -->
|
<!-- Save button -->
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/manual_pos_bt"
|
android:id="@+id/submit_bt"
|
||||||
android:layout_width="?attr/actionBarSize"
|
android:layout_width="40dp"
|
||||||
android:layout_height="?attr/actionBarSize"
|
android:layout_height="40dp"
|
||||||
android:layout_gravity="end"
|
android:layout_gravity="end"
|
||||||
android:padding="16dp"
|
android:layout_margin="8dp"
|
||||||
android:src="@drawable/ic_manual_pos"
|
android:padding="8dp"
|
||||||
|
android:src="@drawable/ic_ok"
|
||||||
app:tint="@color/white"
|
app:tint="@color/white"
|
||||||
android:background="@drawable/floating_semitransparent_button_background"
|
android:background="@drawable/round_button_background"/>
|
||||||
android:visibility="gone"/> <!-- TODO: Implement edit -->
|
|
||||||
|
|
||||||
</androidx.appcompat.widget.Toolbar>
|
</androidx.appcompat.widget.Toolbar>
|
||||||
|
|
||||||
@@ -197,20 +198,40 @@
|
|||||||
android:drawableTint="@color/defaultBrand"
|
android:drawableTint="@color/defaultBrand"
|
||||||
android:hint="@string/description"/>
|
android:hint="@string/description"/>
|
||||||
|
|
||||||
<AutoCompleteTextView
|
<LinearLayout
|
||||||
android:id="@+id/category_at"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="20dp"
|
android:orientation="horizontal"
|
||||||
android:ems="10"
|
android:layout_marginTop="20dp">
|
||||||
android:gravity="start|top"
|
|
||||||
android:inputType="textMultiLine"
|
<AutoCompleteTextView
|
||||||
android:maxLines="10"
|
android:id="@+id/category_at"
|
||||||
android:background="@android:color/transparent"
|
android:layout_width="0dp"
|
||||||
android:drawableLeft="@drawable/ic_category_asc"
|
android:layout_height="wrap_content"
|
||||||
android:drawablePadding="5dp"
|
android:layout_weight="1"
|
||||||
android:drawableTint="@color/defaultBrand"
|
android:maxLines="1"
|
||||||
android:hint="@string/category"/>
|
android:background="@android:color/transparent"
|
||||||
|
android:drawableLeft="@drawable/ic_category_asc"
|
||||||
|
android:drawablePadding="5dp"
|
||||||
|
android:drawableTint="@color/defaultBrand"
|
||||||
|
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
|
<TextView
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
@@ -249,7 +270,9 @@
|
|||||||
android:id="@+id/coords_tv"
|
android:id="@+id/coords_tv"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:textAlignment="textEnd" />
|
android:textAlignment="textEnd"
|
||||||
|
app:drawableEndCompat="@drawable/ic_copy"
|
||||||
|
android:drawablePadding="10sp"/>
|
||||||
|
|
||||||
<ProgressBar
|
<ProgressBar
|
||||||
android:id="@+id/progress"
|
android:id="@+id/progress"
|
||||||
@@ -258,16 +281,6 @@
|
|||||||
android:indeterminate="true"
|
android:indeterminate="true"
|
||||||
android:visibility="gone"/>
|
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>
|
</LinearLayout>
|
||||||
|
|
||||||
</androidx.core.widget.NestedScrollView>
|
</androidx.core.widget.NestedScrollView>
|
||||||
|
|||||||
@@ -15,160 +15,34 @@
|
|||||||
~ You should have received a copy of the GNU General Public License
|
~ You should have received a copy of the GNU General Public License
|
||||||
~ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
~ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
-->
|
-->
|
||||||
|
<FrameLayout
|
||||||
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:id="@+id/activity_list_view"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
<com.google.android.material.appbar.AppBarLayout
|
<androidx.fragment.app.FragmentContainerView
|
||||||
android:id="@+id/appBar"
|
android:id="@+id/fragment_container"
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="?attr/actionBarSize"
|
|
||||||
app:elevation="0dp">
|
|
||||||
|
|
||||||
<com.google.android.material.appbar.CollapsingToolbarLayout
|
|
||||||
android:id="@+id/toolbar_layout"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:fitsSystemWindows="true"
|
|
||||||
app:contentScrim="?attr/colorPrimary"
|
|
||||||
app:layout_scrollFlags="scroll|enterAlways"
|
|
||||||
app:toolbarId="@+id/toolbar" >
|
|
||||||
|
|
||||||
<androidx.appcompat.widget.Toolbar
|
|
||||||
android:id="@+id/toolbar"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:visibility="visible"
|
|
||||||
app:contentInsetStartWithNavigation="0dp"
|
|
||||||
app:titleMarginStart="0dp"
|
|
||||||
tools:title="@string/app_name">
|
|
||||||
|
|
||||||
<androidx.appcompat.widget.SearchView
|
|
||||||
android:id="@+id/search_view"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content">
|
|
||||||
</androidx.appcompat.widget.SearchView>
|
|
||||||
|
|
||||||
</androidx.appcompat.widget.Toolbar>
|
|
||||||
|
|
||||||
<com.google.android.material.card.MaterialCardView
|
|
||||||
android:id="@+id/home_toolbar"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginStart="@dimen/spacer_2x"
|
|
||||||
android:layout_marginTop="@dimen/spacer_1hx"
|
|
||||||
android:layout_marginEnd="@dimen/spacer_2x"
|
|
||||||
android:layout_marginBottom="@dimen/spacer_1hx"
|
|
||||||
app: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_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:layout_margin="@dimen/spacer_1hx"
|
android:name="it.danieleverducci.nextcloudmaps.fragments.GeofavoriteListFragment"
|
||||||
app:layout_behavior="@string/appbar_scrolling_view_behavior">
|
tools:layout="@layout/fragment_geofavorite_list" />
|
||||||
|
|
||||||
<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 -->
|
<!-- Add from map FAB -->
|
||||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||||
android:id="@+id/add_from_map"
|
android:id="@+id/add_from_map"
|
||||||
android:layout_margin="24dp"
|
|
||||||
android:layout_gravity="bottom|end"
|
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="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"
|
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 -->
|
<!-- Add from current position FAB -->
|
||||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||||
@@ -179,7 +53,9 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
app:fabSize="mini"
|
app:fabSize="mini"
|
||||||
android:src="@drawable/ic_add_gps"
|
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 -->
|
<!-- Main FAB -->
|
||||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||||
@@ -189,6 +65,8 @@
|
|||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:src="@drawable/ic_add"
|
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:id="@+id/scrollView"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:background="?attr/colorPrimary">
|
android:background="?android:attr/colorPrimary">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
@@ -68,9 +68,11 @@
|
|||||||
android:id="@+id/app_name"
|
android:id="@+id/app_name"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginRight="20dp"
|
||||||
android:layout_centerVertical="true"
|
android:layout_centerVertical="true"
|
||||||
android:layout_toEndOf="@id/logo"
|
android:layout_toEndOf="@id/logo"
|
||||||
android:ellipsize="end"
|
android:ellipsize="end"
|
||||||
|
android:lines="2"
|
||||||
android:fontFamily="sans-serif-light"
|
android:fontFamily="sans-serif-light"
|
||||||
android:gravity="center_vertical"
|
android:gravity="center_vertical"
|
||||||
android:text="@string/app_name"
|
android:text="@string/app_name"
|
||||||
|
|||||||
@@ -16,27 +16,30 @@
|
|||||||
android:layout_height="48dp"
|
android:layout_height="48dp"
|
||||||
android:layout_marginBottom="24dp"
|
android:layout_marginBottom="24dp"
|
||||||
android:layout_gravity="center"
|
android:layout_gravity="center"
|
||||||
android:src="@drawable/ic_map_pin"/>
|
android:src="@drawable/ic_map_pin"
|
||||||
|
app:tint="@color/defaultBrand"/>
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/back_bt"
|
android:id="@+id/back_bt"
|
||||||
android:layout_width="?attr/actionBarSize"
|
android:layout_width="?android:attr/actionBarSize"
|
||||||
android:layout_height="?attr/actionBarSize"
|
android:layout_height="?android:attr/actionBarSize"
|
||||||
|
android:layout_margin="16dp"
|
||||||
android:layout_gravity="start"
|
android:layout_gravity="start"
|
||||||
android:padding="16dp"
|
android:padding="16dp"
|
||||||
android:src="@drawable/ic_back_grey"
|
android:src="@drawable/ic_back_grey"
|
||||||
app:tint="@color/white"
|
app:tint="@color/text_color"
|
||||||
android:background="@drawable/floating_semitransparent_button_background"/>
|
android:background="@drawable/unselected_floating_semitransparent_button_background"/>
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/ok_bt"
|
android:id="@+id/ok_bt"
|
||||||
android:layout_width="?attr/actionBarSize"
|
android:layout_width="?android:attr/actionBarSize"
|
||||||
android:layout_height="?attr/actionBarSize"
|
android:layout_height="?android:attr/actionBarSize"
|
||||||
|
android:layout_margin="16dp"
|
||||||
android:layout_gravity="end"
|
android:layout_gravity="end"
|
||||||
android:padding="16dp"
|
android:padding="16dp"
|
||||||
android:src="@drawable/ic_ok"
|
android:src="@drawable/ic_ok"
|
||||||
app:tint="@color/white"
|
app:tint="@color/white"
|
||||||
android:background="@drawable/floating_semitransparent_button_background"/>
|
android:background="@drawable/round_button_background"/>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|||||||
@@ -0,0 +1,81 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
~ Nextcloud Maps Geofavorites for Android
|
||||||
|
~
|
||||||
|
~ This program is free software: you can redistribute it and/or modify
|
||||||
|
~ it under the terms of the GNU General Public License as published by
|
||||||
|
~ the Free Software Foundation, either version 3 of the License, or
|
||||||
|
~ (at your option) any later version.
|
||||||
|
~
|
||||||
|
~ This program is distributed in the hope that it will be useful,
|
||||||
|
~ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
~ GNU General Public License for more details.
|
||||||
|
~
|
||||||
|
~ You should have received a copy of the GNU General Public License
|
||||||
|
~ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<ScrollView
|
||||||
|
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="match_parent"
|
||||||
|
android:background="@color/primary"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<com.google.android.material.appbar.AppBarLayout
|
||||||
|
android:id="@+id/appBar"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.Toolbar
|
||||||
|
android:id="@+id/toolbar"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="?android:attr/actionBarSize"
|
||||||
|
app:contentInsetStartWithNavigation="0dp"
|
||||||
|
app:navigationIcon="@drawable/ic_back_grey"
|
||||||
|
app:titleMarginStart="0dp"/>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:padding="@dimen/spacer_2x">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:padding="10dp">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:layout_gravity="center_vertical"
|
||||||
|
android:text="@string/settings_use_google_maps"
|
||||||
|
style="?android:attr/editTextPreferenceStyle"/>
|
||||||
|
|
||||||
|
<Switch
|
||||||
|
android:id="@+id/use_google_maps_switch"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center_vertical"/>
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:paddingStart="10dp"
|
||||||
|
android:paddingEnd="10dp"
|
||||||
|
android:paddingBottom="10dp"
|
||||||
|
android:text="@string/settings_use_google_maps_summary"
|
||||||
|
android:textSize="12sp"
|
||||||
|
android:textColor="@android:color/darker_gray"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</com.google.android.material.appbar.AppBarLayout>
|
||||||
|
|
||||||
|
</ScrollView>
|
||||||
@@ -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>
|
||||||
@@ -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>
|
||||||
@@ -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>
|
||||||
@@ -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>
|
||||||
@@ -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>
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!--
|
|
||||||
~ Nextcloud Maps Geofavorites for Android
|
|
||||||
~
|
|
||||||
~ This program is free software: you can redistribute it and/or modify
|
|
||||||
~ it under the terms of the GNU General Public License as published by
|
|
||||||
~ the Free Software Foundation, either version 3 of the License, or
|
|
||||||
~ (at your option) any later version.
|
|
||||||
~
|
|
||||||
~ This program is distributed in the hope that it will be useful,
|
|
||||||
~ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
~ GNU General Public License for more details.
|
|
||||||
~
|
|
||||||
~ You should have received a copy of the GNU General Public License
|
|
||||||
~ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
<background android:drawable="@drawable/ic_launcher_background"/>
|
|
||||||
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
|
|
||||||
</adaptive-icon>
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!--
|
|
||||||
~ Nextcloud Maps Geofavorites for Android
|
|
||||||
~
|
|
||||||
~ This program is free software: you can redistribute it and/or modify
|
|
||||||
~ it under the terms of the GNU General Public License as published by
|
|
||||||
~ the Free Software Foundation, either version 3 of the License, or
|
|
||||||
~ (at your option) any later version.
|
|
||||||
~
|
|
||||||
~ This program is distributed in the hope that it will be useful,
|
|
||||||
~ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
~ GNU General Public License for more details.
|
|
||||||
~
|
|
||||||
~ You should have received a copy of the GNU General Public License
|
|
||||||
~ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
<background android:drawable="@drawable/ic_launcher_background"/>
|
|
||||||
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
|
|
||||||
</adaptive-icon>
|
|
||||||
|
Before Width: | Height: | Size: 3.8 KiB |
|
Before Width: | Height: | Size: 5.4 KiB |
|
Before Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 3.3 KiB |
|
Before Width: | Height: | Size: 5.5 KiB |
|
Before Width: | Height: | Size: 7.9 KiB |
|
Before Width: | Height: | Size: 8.7 KiB |
|
Before Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 962 B |
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 2.2 KiB |
|
After Width: | Height: | Size: 2.3 KiB |
@@ -18,28 +18,34 @@
|
|||||||
|
|
||||||
<resources>
|
<resources>
|
||||||
<!-- App strings -->
|
<!-- App strings -->
|
||||||
<string name="app_name">Maps Geobookmarks</string>
|
<string name="app_name">Maps Geofavorites</string>
|
||||||
<string name="welcome">Benvenuto su Nextcloud Maps Geobookmarks</string>
|
<string name="welcome">Benvenuto su Nextcloud Maps Geofavorites</string>
|
||||||
|
|
||||||
<!-- Login Activity -->
|
<!-- Login Activity -->
|
||||||
<string name="choose_account">Scegli account</string>
|
<string name="choose_account">Scegli account</string>
|
||||||
|
|
||||||
<!-- Geobookmarks list -->
|
<!-- Geofavorites list -->
|
||||||
<string name="new_geobookmark">Nuovo geosegnalibro</string>
|
<string name="new_geobookmark">Nuovo geosegnalibro</string>
|
||||||
<string name="about">Informazioni</string>
|
<string name="about">Informazioni</string>
|
||||||
<string name="switch_account">Cambia account</string>
|
<string name="switch_account">Cambia account</string>
|
||||||
<string name="list_mode">Lista</string>
|
<string name="list_mode">Lista</string>
|
||||||
<string name="search_in_all">Cerca per nome</string>
|
<string name="search_in_all">Cerca per nome</string>
|
||||||
<string name="share_via">Condividi via</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_share">Condividi</string>
|
||||||
<string name="list_context_menu_delete">Elimina</string>
|
<string name="list_context_menu_delete">Elimina</string>
|
||||||
<string name="dialog_delete_title">Elimina geosegnalibro</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_message">Stai per eliminare il geosegnalibro {name}. Procedere?</string>
|
||||||
<string name="dialog_delete_delete">Elimina</string>
|
<string name="dialog_delete_delete">Elimina</string>
|
||||||
<string name="dialog_delete_cancel">Mantieni</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_deleted">Geosegnalibro eliminato</string>
|
||||||
<string name="list_geofavorite_connection_error">Impossibile ottenere la lista dei geosegnalibri</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 -->
|
<!-- Sort dialog -->
|
||||||
<string name="sort_by">Ordina per</string>
|
<string name="sort_by">Ordina per</string>
|
||||||
@@ -48,7 +54,7 @@
|
|||||||
<string name="menu_item_sort_by_category_a_z">Categoria</string>
|
<string name="menu_item_sort_by_category_a_z">Categoria</string>
|
||||||
<string name="menu_item_sort_by_distance_nearest_first">Distanza</string>
|
<string name="menu_item_sort_by_distance_nearest_first">Distanza</string>
|
||||||
|
|
||||||
<!-- Geobookmarks detail -->
|
<!-- Geofavorites detail -->
|
||||||
<string name="name">Nome</string>
|
<string name="name">Nome</string>
|
||||||
<string name="description">Descrizione</string>
|
<string name="description">Descrizione</string>
|
||||||
<string name="created">Creato</string>
|
<string name="created">Creato</string>
|
||||||
@@ -58,11 +64,12 @@
|
|||||||
<string name="accuracy">Accuratezza: {accuracy} m</string>
|
<string name="accuracy">Accuratezza: {accuracy} m</string>
|
||||||
<string name="accuracy_nosignal">Nessun segnale GPS!</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="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_saving_geofavorite">Impossibile salvare il geosegnalibro</string>
|
||||||
<string name="error_unsupported_uri">Impossibile ottenere le coordinate dai dati ricevuti</string>
|
<string name="error_unsupported_uri">Impossibile ottenere le coordinate dai dati ricevuti</string>
|
||||||
<string name="geofavorite_saved">Geosegnalibro salvato</string>
|
<string name="geofavorite_saved">Geosegnalibro salvato</string>
|
||||||
<string name="incomplete_geofavorite">Geosegnalibro incompleto: nome e categoria sono obbligatori</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 -->
|
<!-- Map picker activity -->
|
||||||
<string name="coordinates_parse_error">Le coordinate dovrebbero essere nel formato xx.xxxxxx</string>
|
<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_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>
|
<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 -->
|
<!-- Menu -->
|
||||||
<string name="new_geobookmark_gps">Crea dalla posizione corrente</string>
|
<string name="new_geobookmark_gps">Crea dalla posizione corrente</string>
|
||||||
<string name="new_geobookmark_map">Crea dalla mappa</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>
|
</resources>
|
||||||
|
|||||||
@@ -3,4 +3,8 @@
|
|||||||
<color name="text_color">#eee</color>
|
<color name="text_color">#eee</color>
|
||||||
<color name="disabled">#888</color>
|
<color name="disabled">#888</color>
|
||||||
<color name="defaultBackground">#000</color>
|
<color name="defaultBackground">#000</color>
|
||||||
|
<color name="translucent">#C000</color>
|
||||||
|
|
||||||
|
<!-- Toolbar -->
|
||||||
|
<color name="toolbar_background">#211e28</color>
|
||||||
</resources>
|
</resources>
|
||||||
@@ -19,7 +19,7 @@
|
|||||||
<resources>
|
<resources>
|
||||||
|
|
||||||
<style name="AppTheme" parent="BaseTheme">
|
<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:windowLightStatusBar">true</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
|||||||
@@ -19,9 +19,9 @@
|
|||||||
<resources>
|
<resources>
|
||||||
|
|
||||||
<style name="AppTheme" parent="BaseTheme">
|
<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:windowLightStatusBar">true</item>
|
||||||
<item name="android:navigationBarColor">?attr/colorPrimary</item>
|
<item name="android:navigationBarColor">?android:attr/colorPrimary</item>
|
||||||
<item name="android:windowLightNavigationBar">true</item>
|
<item name="android:windowLightNavigationBar">true</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
|||||||
@@ -20,11 +20,13 @@
|
|||||||
<!-- Generic Colors -->
|
<!-- Generic Colors -->
|
||||||
<color name="primary">#ffffff</color>
|
<color name="primary">#ffffff</color>
|
||||||
<color name="transparent">#00000000</color>
|
<color name="transparent">#00000000</color>
|
||||||
|
<color name="translucent">#AEFFFFFF</color>
|
||||||
<color name="defaultBrand">#0082C9</color>
|
<color name="defaultBrand">#0082C9</color>
|
||||||
<color name="defaultBrandAlpha">#550082C9</color>
|
<color name="defaultBrandAlpha">#550082C9</color>
|
||||||
<color name="disabled">#666</color>
|
<color name="disabled">#666</color>
|
||||||
<color name="systemBar">@color/defaultBackground</color>
|
<color name="systemBar">@color/defaultBackground</color>
|
||||||
<color name="defaultBackground">#fff</color>
|
<color name="defaultBackground">#fff</color>
|
||||||
|
<color name="inactive">#ccc</color>
|
||||||
|
|
||||||
<!-- List Colors -->
|
<!-- List Colors -->
|
||||||
<color name="text_color">#333</color>
|
<color name="text_color">#333</color>
|
||||||
@@ -36,4 +38,7 @@
|
|||||||
|
|
||||||
<!-- Generic Colors -->
|
<!-- Generic Colors -->
|
||||||
<color name="white">#fff</color>
|
<color name="white">#fff</color>
|
||||||
|
|
||||||
|
<!-- Toolbar -->
|
||||||
|
<color name="toolbar_background">@color/defaultBackground</color>
|
||||||
</resources>
|
</resources>
|
||||||
@@ -39,4 +39,7 @@
|
|||||||
<!-- FAB dimensions -->
|
<!-- FAB dimensions -->
|
||||||
<dimen name="fab_vertical_offset">75dp</dimen>
|
<dimen name="fab_vertical_offset">75dp</dimen>
|
||||||
|
|
||||||
|
<!-- Floating bar below search bar -->
|
||||||
|
<dimen name="floating_bar_height">36dp</dimen>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -17,28 +17,34 @@
|
|||||||
|
|
||||||
<resources>
|
<resources>
|
||||||
<!-- App strings -->
|
<!-- App strings -->
|
||||||
<string name="app_name">Maps Geobookmarks</string>
|
<string name="app_name">Maps Geofavorites</string>
|
||||||
<string name="welcome">Welcome to Nextcloud Maps Geobookmarks</string>
|
<string name="welcome">Welcome to Nextcloud Maps Geofavorites</string>
|
||||||
|
|
||||||
<!-- Login Activity -->
|
<!-- Login Activity -->
|
||||||
<string name="choose_account">Choose account</string>
|
<string name="choose_account">Choose account</string>
|
||||||
|
|
||||||
<!-- Geobookmarks list -->
|
<!-- Geofavorites list -->
|
||||||
<string name="new_geobookmark">New geofavorite</string>
|
<string name="new_geobookmark">New geofavorite</string>
|
||||||
<string name="about">About</string>
|
<string name="about">About</string>
|
||||||
<string name="switch_account">Switch account</string>
|
<string name="switch_account">Switch account</string>
|
||||||
<string name="list_mode">List</string>
|
<string name="list_mode">List</string>
|
||||||
<string name="search_in_all">Search by name</string>
|
<string name="search_in_all">Search by name</string>
|
||||||
<string name="share_via">Share via</string>
|
<string name="share_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_share">Share</string>
|
||||||
<string name="list_context_menu_delete">Delete</string>
|
<string name="list_context_menu_delete">Delete</string>
|
||||||
<string name="dialog_delete_title">Delete geofavorite</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_message">You are about to delete geofavorite {name}. Proceed?</string>
|
||||||
<string name="dialog_delete_delete">Delete</string>
|
<string name="dialog_delete_delete">Delete</string>
|
||||||
<string name="dialog_delete_cancel">Maintain</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_deleted">Geofavorite deleted</string>
|
||||||
<string name="list_geofavorite_connection_error">Unable to obtain geofavorites list</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 -->
|
<!-- Sort dialog -->
|
||||||
<string name="sort_by">Sort by</string>
|
<string name="sort_by">Sort by</string>
|
||||||
@@ -47,7 +53,7 @@
|
|||||||
<string name="menu_item_sort_by_category_a_z">Category</string>
|
<string name="menu_item_sort_by_category_a_z">Category</string>
|
||||||
<string name="menu_item_sort_by_distance_nearest_first">Distance</string>
|
<string name="menu_item_sort_by_distance_nearest_first">Distance</string>
|
||||||
|
|
||||||
<!-- Geobookmarks detail -->
|
<!-- Geofavorites detail -->
|
||||||
<string name="name">Name</string>
|
<string name="name">Name</string>
|
||||||
<string name="description">Description</string>
|
<string name="description">Description</string>
|
||||||
<string name="created">Created</string>
|
<string name="created">Created</string>
|
||||||
@@ -57,11 +63,12 @@
|
|||||||
<string name="accuracy">Accuracy: {accuracy} m</string>
|
<string name="accuracy">Accuracy: {accuracy} m</string>
|
||||||
<string name="accuracy_nosignal">No GPS signal!</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="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_saving_geofavorite">Unable to save geofavorite</string>
|
||||||
<string name="error_unsupported_uri">Unable to obtain coordinates from shared data</string>
|
<string name="error_unsupported_uri">Unable to obtain coordinates from shared data</string>
|
||||||
<string name="geofavorite_saved">Geofavorite saved</string>
|
<string name="geofavorite_saved">Geofavorite saved</string>
|
||||||
<string name="incomplete_geofavorite">Incomplete geofavorite: Name and category are mandatory</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 -->
|
<!-- Map picker activity -->
|
||||||
<string name="coordinates_parse_error">Coordinates should be in format xx.xxxxxx</string>
|
<string name="coordinates_parse_error">Coordinates should be in format xx.xxxxxx</string>
|
||||||
@@ -93,11 +100,17 @@
|
|||||||
<string name="url_maps" translatable="false">https://donate.openstreetmap.org</string>
|
<string name="url_maps" translatable="false">https://donate.openstreetmap.org</string>
|
||||||
|
|
||||||
<!-- Settings -->
|
<!-- Settings -->
|
||||||
<string name="setting_sort_by">SETTING_SORT_BY</string>
|
<string name="settings">Settings</string>
|
||||||
<string name="setting_grid_view_enabled">SETTING_GRID_VIEW_ENABLED</string>
|
<string name="settings_use_google_maps">Always open with Google Maps</string>
|
||||||
|
<string name="settings_use_google_maps_summary">When disabled, a generic Geo URI will be used instead so you can choose your preferred maps app</string>
|
||||||
|
|
||||||
<!-- Menu -->
|
<!-- Menu -->
|
||||||
<string name="new_geobookmark_gps">New from current position</string>
|
<string name="new_geobookmark_gps">New from current position</string>
|
||||||
<string name="new_geobookmark_map">New from map</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>
|
</resources>
|
||||||
|
|||||||
@@ -17,15 +17,17 @@
|
|||||||
|
|
||||||
<resources>
|
<resources>
|
||||||
<!-- Base application theme. -->
|
<!-- 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="colorAccent">@color/defaultBrand</item>
|
||||||
<item name="colorControlNormal">?attr/colorAccent</item>
|
<item name="colorControlNormal">?android:attr/colorAccent</item>
|
||||||
<item name="windowActionModeOverlay">true</item>
|
<item name="windowActionModeOverlay">true</item>
|
||||||
<!-- App bar -->
|
<!-- App bar -->
|
||||||
<item name="colorPrimary">@color/systemBar</item>
|
<item name="colorPrimary">@color/systemBar</item>
|
||||||
<!-- Generic background -->
|
<!-- Generic background -->
|
||||||
<item name="android:windowBackground">@color/defaultBackground</item>
|
<item name="android:windowBackground">@color/defaultBackground</item>
|
||||||
|
|
||||||
|
<item name="alertDialogTheme">@style/AlertDialogTheme</item>
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style name="AppTheme" parent="BaseTheme"/>
|
<style name="AppTheme" parent="BaseTheme"/>
|
||||||
@@ -48,4 +50,22 @@
|
|||||||
<item name="android:textColor">@color/white</item>
|
<item name="android:textColor">@color/white</item>
|
||||||
</style>
|
</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>
|
</resources>
|
||||||
@@ -22,10 +22,10 @@
|
|||||||
buildscript {
|
buildscript {
|
||||||
repositories {
|
repositories {
|
||||||
google()
|
google()
|
||||||
jcenter()
|
mavenCentral()
|
||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.android.tools.build:gradle:4.2.2'
|
classpath 'com.android.tools.build:gradle:9.2.1'
|
||||||
|
|
||||||
// NOTE: Do not place your application dependencies here; they belong
|
// NOTE: Do not place your application dependencies here; they belong
|
||||||
// in the individual module build.gradle files
|
// in the individual module build.gradle files
|
||||||
@@ -35,7 +35,7 @@ buildscript {
|
|||||||
allprojects {
|
allprojects {
|
||||||
repositories {
|
repositories {
|
||||||
google()
|
google()
|
||||||
jcenter()
|
mavenCentral()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
|
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 |
@@ -0,0 +1,4 @@
|
|||||||
|
Fix crash when using corrupted dataset with null category (It may happen on imports from Google Maps)
|
||||||
|
Reimplemented API Provider to try to fix NullPointerException on mApi reported in Play Store
|
||||||
|
Open Google Maps on Google devices
|
||||||
|
Support share from: google maps urls, OpenStreetMap urls (only if containing coordinates)
|
||||||
@@ -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,5 +1,5 @@
|
|||||||
UNOFFICIAL and FOSS Nextcloud Maps client at its earliest stages of developement. Shows your Nextcloud Maps geobookmarks list.
|
UNOFFICIAL and FOSS Nextcloud Maps client. Shows your Nextcloud Maps geofavorites in a list or a map.
|
||||||
Geobookmarks can be opened in all apps supporting geo links (i.e. Google Maps, Organic Maps etc...).
|
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.
|
A new geofavorite can be created on current location, by sharing a "geo:" uri from another app or manually picking from the map.
|
||||||
|
|
||||||
Requires Maps app to be installed on the Nextcloud instance.
|
Requires Maps app to be installed on the Nextcloud instance.
|
||||||
|
|||||||
|
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 +1 @@
|
|||||||
Manage Nextcloud Maps Geobookmarks on your phone
|
Manage Nextcloud Maps Geofavorites on your phone
|
||||||
|
|||||||