├── .gitignore
├── .idea
├── .gitignore
├── .name
├── compiler.xml
├── jarRepositories.xml
└── migrations.xml
├── LICENSE
├── README.md
├── app
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── ic_launcher-playstore.png
│ ├── java
│ └── it
│ │ └── danieleverducci
│ │ └── nextcloudmaps
│ │ ├── activity
│ │ ├── NextcloudMapsStyledActivity.java
│ │ ├── about
│ │ │ └── AboutActivity.java
│ │ ├── detail
│ │ │ ├── CategoriesAdapter.java
│ │ │ ├── GeofavoriteDetailActivity.java
│ │ │ └── GeofavoriteDetailActivityViewModel.java
│ │ ├── login
│ │ │ └── LoginActivity.java
│ │ ├── main
│ │ │ ├── GeofavoriteAdapter.java
│ │ │ ├── GeofavoritesFragmentViewModel.java
│ │ │ ├── MainActivity.java
│ │ │ ├── NavigationAdapter.java
│ │ │ └── SortingOrderDialogFragment.java
│ │ └── mappicker
│ │ │ └── MapPickerActivity.java
│ │ ├── api
│ │ ├── API.java
│ │ └── ApiProvider.java
│ │ ├── fragments
│ │ ├── GeofavoriteListFragment.java
│ │ ├── GeofavoriteMapFragment.java
│ │ └── GeofavoritesFragment.java
│ │ ├── model
│ │ └── Geofavorite.java
│ │ ├── repository
│ │ └── GeofavoriteRepository.java
│ │ ├── utils
│ │ ├── GeoUriParser.java
│ │ ├── GeofavoritesFilter.java
│ │ ├── IntentGenerator.java
│ │ ├── MapUtils.java
│ │ ├── SettingsManager.java
│ │ └── SingleLiveEvent.java
│ │ └── views
│ │ └── GeofavMarkerInfoWindow.java
│ ├── res
│ ├── drawable
│ │ ├── floating_semitransparent_button_background.xml
│ │ ├── geofav_infowindow_pointer.xml
│ │ ├── ic_accuracy_fail.xml
│ │ ├── ic_accuracy_ok.xml
│ │ ├── ic_add.xml
│ │ ├── ic_add_gps.xml
│ │ ├── ic_add_map.xml
│ │ ├── ic_alphabetical_asc.xml
│ │ ├── ic_app.xml
│ │ ├── ic_back_grey.xml
│ │ ├── ic_category_asc.xml
│ │ ├── ic_clear.xml
│ │ ├── ic_copy.xml
│ │ ├── ic_delete_grey.xml
│ │ ├── ic_distance_asc.xml
│ │ ├── ic_edit.xml
│ │ ├── ic_filter.xml
│ │ ├── ic_filter_off.xml
│ │ ├── ic_info_grey.xml
│ │ ├── ic_launcher_foreground.xml
│ │ ├── ic_list_pin.xml
│ │ ├── ic_logout_grey.xml
│ │ ├── ic_map_pin.xml
│ │ ├── ic_menu_grey.xml
│ │ ├── ic_modification_asc.xml
│ │ ├── ic_more.xml
│ │ ├── ic_nav.xml
│ │ ├── ic_ok.xml
│ │ ├── ic_save_grey.xml
│ │ ├── ic_share.xml
│ │ ├── ic_time_grey.xml
│ │ ├── ic_view_list.xml
│ │ ├── ic_view_map.xml
│ │ ├── infowindow_geofav_background.xml
│ │ ├── round_button_background.xml
│ │ ├── rounded_label_background.xml
│ │ ├── unselected_floating_semitransparent_button_background.xml
│ │ └── user_badge_mask.xml
│ ├── layout
│ │ ├── activity_about.xml
│ │ ├── activity_geofavorite_detail.xml
│ │ ├── activity_list_view.xml
│ │ ├── activity_login.xml
│ │ ├── activity_main.xml
│ │ ├── activity_map_picker.xml
│ │ ├── app_toolbar.xml
│ │ ├── category_listitem.xml
│ │ ├── fragment_geofavorite_list.xml
│ │ ├── fragment_geofavorite_map.xml
│ │ ├── infowindow_geofav.xml
│ │ ├── item_geofav.xml
│ │ ├── item_navigation.xml
│ │ └── sorting_order_fragment.xml
│ ├── menu
│ │ └── list_context_menu.xml
│ ├── mipmap-anydpi-v26
│ │ ├── ic_launcher.xml
│ │ └── ic_launcher_round.xml
│ ├── mipmap-hdpi
│ │ ├── ic_launcher.png
│ │ ├── ic_launcher_round.png
│ │ └── ic_person.png
│ ├── mipmap-mdpi
│ │ ├── ic_launcher.png
│ │ ├── ic_launcher_round.png
│ │ └── ic_person.png
│ ├── mipmap-xhdpi
│ │ ├── ic_launcher.png
│ │ ├── ic_launcher_round.png
│ │ └── ic_person.png
│ ├── mipmap-xxhdpi
│ │ ├── ic_launcher.png
│ │ ├── ic_launcher_round.png
│ │ └── ic_person.png
│ ├── mipmap-xxxhdpi
│ │ ├── ic_launcher.png
│ │ ├── ic_launcher_round.png
│ │ └── ic_person.png
│ ├── values-it
│ │ └── strings.xml
│ ├── values-night
│ │ └── colors.xml
│ ├── values-v23
│ │ └── styles.xml
│ ├── values-v27
│ │ └── styles.xml
│ └── values
│ │ ├── colors.xml
│ │ ├── dimens.xml
│ │ ├── ic_launcher_background.xml
│ │ ├── strings.xml
│ │ └── styles.xml
│ └── web_hi_res_512.png
├── build.gradle
├── fastlane
└── metadata
│ └── android
│ ├── en-US
│ ├── changelogs
│ │ ├── 1.txt
│ │ ├── 2.txt
│ │ ├── 3.txt
│ │ ├── 4.txt
│ │ ├── 5.txt
│ │ ├── 6.txt
│ │ ├── 7.txt
│ │ └── 9.txt
│ ├── full_description.txt
│ ├── images
│ │ ├── featureGraphic.png
│ │ ├── icon.png
│ │ ├── phoneScreenshots
│ │ │ ├── 1.png
│ │ │ ├── 2.png
│ │ │ └── 3.png
│ │ └── promoGraphic.png
│ ├── short_description.txt
│ └── title.txt
│ └── it-IT
│ ├── full_description.txt
│ ├── short_description.txt
│ └── title.txt
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── screenshots
├── 1.png
├── 2.png
├── 3.png
└── full
│ ├── 1.png
│ ├── 2.png
│ └── 3.png
└── settings.gradle
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea/caches
5 | /.idea/libraries
6 | /.idea/modules.xml
7 | /.idea/workspace.xml
8 | /.idea/navEditor.xml
9 | /.idea/assetWizardSettings.xml
10 | .DS_Store
11 | /build
12 | /captures
13 | .externalNativeBuild
14 | .cxx
15 | # Built application files
16 | *.apk
17 | *.ap_
18 | *.aab
19 |
20 | # Files for the ART/Dalvik VM
21 | *.dex
22 |
23 | # Java class files
24 | *.class
25 |
26 | # Generated files
27 | bin/
28 | gen/
29 | out/
30 | # Uncomment the following line in case you need and you don't have the release build type files in your app
31 | # release/
32 |
33 | # Gradle files
34 | .gradle/
35 | build/
36 |
37 | # Local configuration file (sdk path, etc)
38 | local.properties
39 |
40 | # Proguard folder generated by Eclipse
41 | proguard/
42 |
43 | # Log Files
44 | *.log
45 |
46 | # Android Studio Navigation editor temp files
47 | .navigation/
48 |
49 | # Android Studio captures folder
50 | captures/
51 |
52 | # IntelliJ
53 | *.iml
54 | .idea/workspace.xml
55 | .idea/tasks.xml
56 | .idea/gradle.xml
57 | .idea/assetWizardSettings.xml
58 | .idea/dictionaries
59 | .idea/libraries
60 | # Android Studio 3 in .gitignore file.
61 | .idea/caches
62 | .idea/modules.xml
63 | # Comment next line if keeping position of elements in Navigation Editor is relevant for you
64 | .idea/navEditor.xml
65 |
66 | # Keystore files
67 | # Uncomment the following lines if you do not want to check your keystore files in.
68 | #*.jks
69 | #*.keystore
70 |
71 | # External native build folder generated in Android Studio 2.2 and later
72 | .externalNativeBuild
73 | .cxx/
74 |
75 | # Google Services (e.g. APIs or Firebase)
76 | # google-services.json
77 |
78 | # Freeline
79 | freeline.py
80 | freeline/
81 | freeline_project_description.json
82 |
83 | # fastlane
84 | fastlane/report.xml
85 | fastlane/Preview.html
86 | fastlane/screenshots
87 | fastlane/test_output
88 | fastlane/readme.md
89 |
90 | # Version control
91 | vcs.xml
92 |
93 | # lint
94 | lint/intermediates/
95 | lint/generated/
96 | lint/outputs/
97 | lint/tmp/
98 | # lint/reports/
99 |
100 | app/release/output-metadata.json
101 |
102 | .idea/deploymentTargetDropDown.xml
103 | .idea/misc.xml
104 |
--------------------------------------------------------------------------------
/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # Default ignored files
2 | /shelf/
3 | /workspace.xml
4 |
--------------------------------------------------------------------------------
/.idea/.name:
--------------------------------------------------------------------------------
1 | Nextcloud Maps Geofavorites
--------------------------------------------------------------------------------
/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/jarRepositories.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/.idea/migrations.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
10 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 
2 |
3 | # Nextcloud Maps Geofavorites Android app
4 |
5 | [
](https://f-droid.org/it/packages/it.danieleverducci.nextcloudmaps)
6 | [
](https://play.google.com/store/apps/details?id=it.danieleverducci.nextcloudmaps)
7 | [
](https://github.com/penguin86/nextcloud-maps-client/releases/latest)
8 |
9 | (Always prefer [F-Droid](https://f-droid.org) build, when possible).
10 |
11 | UNOFFICIAL and FOSS Nextcloud Maps client at its earliest stages of developement. Shows your Nextcloud Maps geofavorites in a list and a map.
12 | Geofavorites can be opened in all apps supporting geo links (i.e. Google Maps, Organic Maps etc...).
13 | A new geofavorite can be created on current location, by sharing a "geo:" uri from another app or manually picking from the map.
14 |
15 | **Requires Maps app to be installed on the Nextcloud instance.**
16 |
17 | 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).
18 |
19 |   
20 |
21 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | /*
2 | * Nextcloud Geofavorites for Android
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with this program. If not, see .
16 | */
17 |
18 | apply plugin: 'com.android.application'
19 |
20 | android {
21 | compileSdkVersion 34
22 |
23 | defaultConfig {
24 | applicationId "it.danieleverducci.nextcloudmaps"
25 | minSdkVersion 23
26 | targetSdkVersion 34
27 | versionCode 9
28 | versionName "0.4.0"
29 |
30 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
31 | }
32 |
33 | buildTypes {
34 | release {
35 | minifyEnabled false
36 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
37 | }
38 | }
39 | compileOptions {
40 | // Flag to enable support for the new language APIs
41 | coreLibraryDesugaringEnabled true
42 | // Sets Java compatibility to Java 8
43 | sourceCompatibility JavaVersion.VERSION_1_8
44 | targetCompatibility JavaVersion.VERSION_1_8
45 | }
46 |
47 | buildFeatures {
48 | dataBinding true
49 | }
50 | namespace 'it.danieleverducci.nextcloudmaps'
51 | }
52 |
53 | repositories {
54 | // Needed for Nextcloud SSO
55 | maven { url "https://jitpack.io" }
56 | }
57 |
58 | dependencies {
59 | implementation fileTree(dir: "libs", include: ["*.jar"])
60 |
61 | // Desugaring lib: see https://developer.android.com/studio/write/java8-support
62 | coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.0.3")
63 |
64 | implementation 'com.android.support:design:34.0.0'
65 | implementation 'androidx.appcompat:appcompat:1.6.1'
66 | implementation 'androidx.recyclerview:recyclerview:1.3.2'
67 | implementation "androidx.cardview:cardview:1.0.0"
68 | implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
69 | implementation "androidx.preference:preference:1.2.1"
70 | implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0'
71 |
72 | // Retrofif2
73 | implementation 'com.squareup.retrofit2:retrofit:2.9.0'
74 | implementation 'com.squareup.retrofit2:converter-gson:2.6.1'
75 |
76 | // Nextcloud SSO
77 | implementation "com.github.nextcloud:Android-SingleSignOn:1.0.0"
78 |
79 | // OSMDroid
80 | implementation 'org.osmdroid:osmdroid-android:6.1.18'
81 |
82 | //Threeten-Backport (ports Java 8 Date API on Java 6+)
83 | implementation 'org.threeten:threetenbp:1.5.1'
84 |
85 | // https://mvnrepository.com/artifact/commons-io/commons-io
86 | implementation 'commons-io:commons-io:2.11.0'
87 |
88 | // Picasso (image loader)
89 | implementation 'com.squareup.picasso:picasso:2.8'
90 |
91 | configurations.all {
92 | resolutionStrategy {
93 | force 'commons-io:commons-io:2.11.0'
94 | }
95 | }
96 |
97 | }
98 |
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
18 |
19 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
39 |
40 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
50 |
51 |
52 |
53 |
54 |
55 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
102 |
103 |
104 |
105 |
106 |
109 |
110 |
111 |
112 |
113 |
114 |
118 |
119 |
120 |
--------------------------------------------------------------------------------
/app/src/main/ic_launcher-playstore.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/penguin86/nextcloud-maps-client/bd8a0d706dc7bbb34c8b958dc1a24d0e8897bd33/app/src/main/ic_launcher-playstore.png
--------------------------------------------------------------------------------
/app/src/main/java/it/danieleverducci/nextcloudmaps/activity/NextcloudMapsStyledActivity.java:
--------------------------------------------------------------------------------
1 | package it.danieleverducci.nextcloudmaps.activity;
2 |
3 | import android.content.res.Configuration;
4 | import android.os.Bundle;
5 | import android.view.View;
6 |
7 | import androidx.annotation.Nullable;
8 | import androidx.appcompat.app.AppCompatActivity;
9 |
10 | import org.osmdroid.views.overlay.TilesOverlay;
11 |
12 | public class NextcloudMapsStyledActivity extends AppCompatActivity {
13 |
14 | @Override
15 | protected void onCreate(@Nullable Bundle savedInstanceState) {
16 | super.onCreate(savedInstanceState);
17 |
18 | // For whatever reason, android:windowLightStatusBar is ignored in styles.xml
19 | int currentNightMode = getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK;
20 | if (currentNightMode == Configuration.UI_MODE_NIGHT_YES)
21 | getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE);
22 | }
23 |
24 | }
25 |
26 |
27 |
--------------------------------------------------------------------------------
/app/src/main/java/it/danieleverducci/nextcloudmaps/activity/about/AboutActivity.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Nextcloud Geofavorites for Android
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with this program. If not, see .
16 | */
17 |
18 | package it.danieleverducci.nextcloudmaps.activity.about;
19 |
20 | import android.content.Intent;
21 | import android.net.Uri;
22 | import android.os.Bundle;
23 | import android.text.Html;
24 | import android.widget.Button;
25 | import android.widget.TextView;
26 |
27 | import androidx.appcompat.app.ActionBar;
28 | import androidx.appcompat.app.AppCompatActivity;
29 | import androidx.appcompat.widget.Toolbar;
30 |
31 | import it.danieleverducci.nextcloudmaps.BuildConfig;
32 | import it.danieleverducci.nextcloudmaps.R;
33 | import it.danieleverducci.nextcloudmaps.activity.NextcloudMapsStyledActivity;
34 |
35 | public class AboutActivity extends NextcloudMapsStyledActivity {
36 | @Override
37 | protected void onCreate(Bundle savedInstanceState) {
38 | super.onCreate(savedInstanceState);
39 | setContentView(R.layout.activity_about);
40 |
41 | Toolbar toolbar = findViewById(R.id.toolbar);
42 | setSupportActionBar(toolbar);
43 |
44 | ActionBar actionBar = getSupportActionBar();
45 | if (actionBar != null) {
46 | actionBar.setDisplayShowTitleEnabled(false);
47 | }
48 |
49 | fillAboutActivity();
50 | }
51 |
52 | private void fillAboutActivity () {
53 | TextView tvVersion = findViewById(R.id.about_version);
54 | tvVersion.setText(Html.fromHtml(getString(R.string.about_version, "v" + BuildConfig.VERSION_NAME)));
55 |
56 | Button btLicence = findViewById(R.id.about_app_license_button);
57 | btLicence.setOnClickListener(view -> openUtl(getString(R.string.url_license)));
58 |
59 | TextView tvSource = findViewById(R.id.about_source);
60 | tvSource.setText(Html.fromHtml(getString(R.string.about_source, getString(R.string.url_source))));
61 | tvSource.setOnClickListener(view -> openUtl(getString(R.string.url_source)));
62 |
63 | TextView tvIssues = findViewById(R.id.about_issues);
64 | tvIssues.setText(Html.fromHtml(getString(R.string.about_issues, getString(R.string.url_issues))));
65 | tvIssues.setOnClickListener(view -> openUtl(getString(R.string.url_issues)));
66 |
67 | TextView tvMaps = findViewById(R.id.about_maps);
68 | tvMaps.setText(Html.fromHtml(getString(R.string.about_maps)));
69 | tvMaps.setOnClickListener(view -> openUtl(getString(R.string.url_maps)));
70 | }
71 |
72 | @Override
73 | public boolean onSupportNavigateUp() {
74 | finish();
75 | return true;
76 | }
77 |
78 | private void openUtl(String url) {
79 | startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url)));
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/app/src/main/java/it/danieleverducci/nextcloudmaps/activity/detail/CategoriesAdapter.java:
--------------------------------------------------------------------------------
1 | package it.danieleverducci.nextcloudmaps.activity.detail;
2 |
3 | import android.content.Context;
4 | import android.graphics.drawable.Drawable;
5 | import android.view.View;
6 | import android.view.ViewGroup;
7 | import android.widget.ArrayAdapter;
8 | import android.widget.TextView;
9 |
10 | import androidx.annotation.NonNull;
11 | import androidx.annotation.Nullable;
12 | import androidx.core.graphics.drawable.DrawableCompat;
13 |
14 | import java.util.ArrayList;
15 | import java.util.HashSet;
16 |
17 | import it.danieleverducci.nextcloudmaps.R;
18 | import it.danieleverducci.nextcloudmaps.model.Geofavorite;
19 |
20 | public class CategoriesAdapter extends ArrayAdapter {
21 |
22 | public CategoriesAdapter(@NonNull Context context) {
23 | super(context, R.layout.category_listitem, R.id.category_name, new ArrayList<>());
24 | }
25 |
26 | @NonNull
27 | @Override
28 | public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
29 | View v = super.getView(position, convertView, parent);
30 | TextView categoryName = v.findViewById(R.id.category_name);
31 | Drawable backgroundDrawable = categoryName.getBackground();
32 | DrawableCompat.setTint(
33 | backgroundDrawable,
34 | Geofavorite.categoryColorFromName(categoryName.getText().toString()) == 0
35 | ? v.getContext().getColor(R.color.defaultBrand)
36 | : Geofavorite.categoryColorFromName(categoryName.getText().toString())
37 | );
38 | return v;
39 | }
40 |
41 | public void setCategoriesList(HashSet categories) {
42 | clear();
43 | addAll(categories);
44 | notifyDataSetChanged();
45 | }
46 |
47 | }
48 |
--------------------------------------------------------------------------------
/app/src/main/java/it/danieleverducci/nextcloudmaps/activity/detail/GeofavoriteDetailActivityViewModel.java:
--------------------------------------------------------------------------------
1 | package it.danieleverducci.nextcloudmaps.activity.detail;
2 |
3 | import android.content.Context;
4 |
5 | import androidx.lifecycle.LiveData;
6 | import androidx.lifecycle.MutableLiveData;
7 | import androidx.lifecycle.ViewModel;
8 |
9 | import java.util.HashMap;
10 | import java.util.HashSet;
11 | import java.util.List;
12 |
13 | import it.danieleverducci.nextcloudmaps.model.Geofavorite;
14 | import it.danieleverducci.nextcloudmaps.repository.GeofavoriteRepository;
15 |
16 | public class GeofavoriteDetailActivityViewModel extends ViewModel {
17 | private GeofavoriteRepository mRepo;
18 |
19 | public void init(Context applicationContext) {
20 | mRepo = GeofavoriteRepository.getInstance(applicationContext);
21 | }
22 |
23 | public Geofavorite getGeofavorite(int id) {
24 | return mRepo.getGeofavorite(id);
25 | }
26 |
27 | public void saveGeofavorite(Geofavorite geofav) {
28 | mRepo.saveGeofavorite(geofav);
29 | }
30 |
31 | public LiveData> getCategories(){
32 | return mRepo.getCategories();
33 | }
34 |
35 | public LiveData getIsUpdating(){
36 | return mRepo.isUpdating();
37 | }
38 |
39 | public LiveData getOnFinished(){
40 | return mRepo.onFinished();
41 | }
42 |
43 | }
44 |
--------------------------------------------------------------------------------
/app/src/main/java/it/danieleverducci/nextcloudmaps/activity/login/LoginActivity.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Nextcloud Geofavorites for Android
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with this program. If not, see .
16 | */
17 |
18 | package it.danieleverducci.nextcloudmaps.activity.login;
19 |
20 | import android.content.Context;
21 | import android.content.Intent;
22 | import android.os.Bundle;
23 | import android.os.Handler;
24 | import android.util.Log;
25 | import android.view.View;
26 | import android.widget.Button;
27 | import android.widget.ProgressBar;
28 |
29 | import androidx.annotation.NonNull;
30 | import androidx.appcompat.app.AppCompatActivity;
31 |
32 | import com.nextcloud.android.sso.AccountImporter;
33 | import com.nextcloud.android.sso.api.NextcloudAPI;
34 | import com.nextcloud.android.sso.exceptions.AccountImportCancelledException;
35 | import com.nextcloud.android.sso.exceptions.AndroidGetAccountsPermissionNotGranted;
36 | import com.nextcloud.android.sso.exceptions.NextcloudFilesAppAccountNotFoundException;
37 | import com.nextcloud.android.sso.exceptions.NextcloudFilesAppNotInstalledException;
38 | import com.nextcloud.android.sso.exceptions.NoCurrentAccountSelectedException;
39 | import com.nextcloud.android.sso.helper.SingleAccountHelper;
40 | import com.nextcloud.android.sso.model.SingleSignOnAccount;
41 | import com.nextcloud.android.sso.ui.UiExceptionManager;
42 |
43 | import it.danieleverducci.nextcloudmaps.R;
44 | import it.danieleverducci.nextcloudmaps.activity.NextcloudMapsStyledActivity;
45 | import it.danieleverducci.nextcloudmaps.activity.main.MainActivity;
46 | import it.danieleverducci.nextcloudmaps.api.API;
47 | import it.danieleverducci.nextcloudmaps.api.ApiProvider;
48 |
49 | public class LoginActivity extends NextcloudMapsStyledActivity {
50 | private static final String TAG = "LoginActivity";
51 |
52 | protected ProgressBar progress;
53 | protected Button button;
54 |
55 | protected SingleSignOnAccount ssoAccount;
56 |
57 | @Override
58 | protected void onCreate(Bundle savedInstanceState) {
59 | super.onCreate(savedInstanceState);
60 | setContentView(R.layout.activity_login);
61 |
62 | progress = findViewById(R.id.progress);
63 | button = findViewById(R.id.chose_button);
64 | button.setOnClickListener(view -> {
65 | progress.setVisibility(View.VISIBLE);
66 | openAccountChooser();
67 | });
68 |
69 | Handler h = new Handler();
70 | h.post(() -> {
71 | try {
72 | ssoAccount = SingleAccountHelper.getCurrentSingleSignOnAccount(getApplicationContext());
73 | SingleAccountHelper.applyCurrentAccount(getApplicationContext(), ssoAccount.name);
74 | accountAccessDone();
75 | } catch (NextcloudFilesAppAccountNotFoundException | NoCurrentAccountSelectedException e) {
76 | Log.e(TAG, "Autologin: " + e.toString());
77 | }
78 | });
79 | }
80 | private void openAccountChooser() {
81 | try {
82 | AccountImporter.pickNewAccount(this);
83 | } catch (NextcloudFilesAppNotInstalledException | AndroidGetAccountsPermissionNotGranted e) {
84 | UiExceptionManager.showDialogForException(this, e);
85 |
86 | Log.e(TAG, "openAccountChooser: " + e.toString());
87 | progress.setVisibility(View.GONE);
88 | }
89 | }
90 |
91 | public void onActivityResult(int requestCode, int resultCode, Intent data) {
92 | super.onActivityResult(requestCode, resultCode, data);
93 |
94 | try {
95 | AccountImporter.onActivityResult(requestCode, resultCode, data, this, new AccountImporter.IAccountAccessGranted() {
96 | NextcloudAPI.ApiConnectedListener callback = new NextcloudAPI.ApiConnectedListener() {
97 | @Override
98 | public void onConnected() {
99 | // ignore this one… see 5)
100 | }
101 |
102 | @Override
103 | public void onError(Exception ex) {
104 | // TODO handle errors
105 | }
106 | };
107 |
108 | @Override
109 | public void accountAccessGranted(SingleSignOnAccount account) {
110 | Context l_context = getApplicationContext();
111 | SingleAccountHelper.applyCurrentAccount(l_context, account.name);
112 |
113 | accountAccessDone();
114 | }
115 | });
116 | } catch (AccountImportCancelledException e) {
117 | e.printStackTrace();
118 | }
119 | }
120 |
121 | @Override
122 | public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
123 | super.onRequestPermissionsResult(requestCode, permissions, grantResults);
124 | AccountImporter.onRequestPermissionsResult(requestCode, permissions, grantResults, this);
125 | }
126 |
127 | private void accountAccessDone() {
128 | Intent intent = new Intent(LoginActivity.this, MainActivity.class);
129 | startActivity(intent);
130 |
131 | finish();
132 | }
133 | }
--------------------------------------------------------------------------------
/app/src/main/java/it/danieleverducci/nextcloudmaps/activity/main/GeofavoritesFragmentViewModel.java:
--------------------------------------------------------------------------------
1 | package it.danieleverducci.nextcloudmaps.activity.main;
2 |
3 | import android.content.Context;
4 |
5 | import androidx.lifecycle.LiveData;
6 | import androidx.lifecycle.ViewModel;
7 |
8 | import java.util.HashSet;
9 | import java.util.List;
10 |
11 | import it.danieleverducci.nextcloudmaps.model.Geofavorite;
12 | import it.danieleverducci.nextcloudmaps.repository.GeofavoriteRepository;
13 |
14 | public class GeofavoritesFragmentViewModel extends ViewModel {
15 | private GeofavoriteRepository mRepo;
16 |
17 | public void init(Context applicationContext) {
18 | mRepo = GeofavoriteRepository.getInstance(applicationContext);
19 | }
20 |
21 | public LiveData> getGeofavorites(){
22 | mRepo.updateGeofavorites();
23 | return mRepo.getGeofavorites();
24 | }
25 |
26 | public void updateGeofavorites() {
27 | mRepo.updateGeofavorites();
28 | }
29 |
30 | public LiveData> getCategories(){
31 | return mRepo.getCategories();
32 | }
33 |
34 | public void deleteGeofavorite(Geofavorite geofav) {
35 | mRepo.deleteGeofavorite(geofav);
36 | }
37 |
38 | public LiveData getIsUpdating(){
39 | return mRepo.isUpdating();
40 | }
41 |
42 | public LiveData getOnFinished(){
43 | return mRepo.onFinished();
44 | }
45 |
46 | }
47 |
--------------------------------------------------------------------------------
/app/src/main/java/it/danieleverducci/nextcloudmaps/activity/main/NavigationAdapter.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Nextcloud Maps Geofavorites for Android
3 | *
4 | * @copyright Copyright (c) 2020 John Doe
5 | * @author John Doe
6 | *
7 | * This program is free software: you can redistribute it and/or modify
8 | * it under the terms of the GNU General Public License as published by
9 | * the Free Software Foundation, either version 3 of the License, or
10 | * (at your option) any later version.
11 | *
12 | * This program is distributed in the hope that it will be useful,
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | * GNU General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU General Public License
18 | * along with this program. If not, see .
19 | */
20 |
21 | package it.danieleverducci.nextcloudmaps.activity.main;
22 |
23 | import android.content.Context;
24 | import android.view.LayoutInflater;
25 | import android.view.View;
26 | import android.view.ViewGroup;
27 | import android.widget.ImageView;
28 | import android.widget.TextView;
29 |
30 | import androidx.annotation.DrawableRes;
31 | import androidx.annotation.NonNull;
32 | import androidx.core.graphics.drawable.DrawableCompat;
33 | import androidx.recyclerview.widget.RecyclerView;
34 |
35 | import java.util.ArrayList;
36 | import java.util.List;
37 |
38 | import it.danieleverducci.nextcloudmaps.R;
39 |
40 | public class NavigationAdapter extends RecyclerView.Adapter {
41 |
42 | @NonNull
43 | private final Context context;
44 |
45 | public static class NavigationItem {
46 | @NonNull
47 | public String id;
48 | @NonNull
49 | public String label;
50 | @DrawableRes
51 | public int icon;
52 |
53 | public NavigationItem(@NonNull String id, @NonNull String label, @DrawableRes int icon) {
54 | this.id = id;
55 | this.label = label;
56 | this.icon = icon;
57 | }
58 | }
59 |
60 | class ViewHolder extends RecyclerView.ViewHolder {
61 | @NonNull
62 | private final View view;
63 |
64 | @NonNull
65 | private final TextView name;
66 | @NonNull
67 | private final ImageView icon;
68 |
69 | private NavigationItem currentItem;
70 |
71 | ViewHolder(@NonNull View itemView, @NonNull final ClickListener clickListener) {
72 | super(itemView);
73 | view = itemView;
74 |
75 | this.name = itemView.findViewById(R.id.navigationItemLabel);
76 | this.icon = itemView.findViewById(R.id.navigationItemIcon);
77 |
78 | icon.setOnClickListener(view -> clickListener.onItemClick(currentItem));
79 | itemView.setOnClickListener(view -> clickListener.onItemClick(currentItem));
80 | }
81 |
82 | private void bind(@NonNull NavigationItem item) {
83 |
84 | currentItem = item;
85 | name.setText(item.label);
86 |
87 |
88 | icon.setImageDrawable(DrawableCompat.wrap(icon.getResources().getDrawable(item.icon)));
89 | icon.setVisibility(View.VISIBLE);
90 | }
91 |
92 | }
93 |
94 | public interface ClickListener {
95 | void onItemClick(NavigationItem item);
96 | }
97 |
98 | @NonNull
99 | private List items = new ArrayList<>();
100 | private String selectedItem = null;
101 | @NonNull
102 | private final ClickListener clickListener;
103 |
104 | public NavigationAdapter(@NonNull Context context, @NonNull ClickListener clickListener) {
105 | this.context = context;
106 | this.clickListener = clickListener;
107 | }
108 |
109 | @NonNull
110 | @Override
111 | public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
112 | View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_navigation, parent, false);
113 | return new ViewHolder(v, clickListener);
114 | }
115 |
116 | @Override
117 | public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
118 | holder.bind(items.get(position));
119 | }
120 |
121 | @Override
122 | public int getItemCount() {
123 | return items.size();
124 | }
125 |
126 | public void setItems(@NonNull List items) {
127 | this.items = items;
128 | notifyDataSetChanged();
129 | }
130 |
131 | }
132 |
--------------------------------------------------------------------------------
/app/src/main/java/it/danieleverducci/nextcloudmaps/activity/main/SortingOrderDialogFragment.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Nextcloud Maps Geofavorites for Android
3 | *
4 | * @copyright Copyright (c) 2020 John Doe
5 | * @author John Doe
6 | *
7 | * This program is free software: you can redistribute it and/or modify
8 | * it under the terms of the GNU General Public License as published by
9 | * the Free Software Foundation, either version 3 of the License, or
10 | * (at your option) any later version.
11 | *
12 | * This program is distributed in the hope that it will be useful,
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | * GNU General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU General Public License
18 | * along with this program. If not, see .
19 | */
20 |
21 | package it.danieleverducci.nextcloudmaps.activity.main;
22 |
23 | import android.app.Dialog;
24 | import android.graphics.Typeface;
25 | import android.graphics.drawable.Drawable;
26 | import android.os.Bundle;
27 | import android.view.LayoutInflater;
28 | import android.view.View;
29 | import android.view.ViewGroup;
30 | import android.widget.Button;
31 | import android.widget.ImageButton;
32 | import android.widget.TextView;
33 |
34 | import androidx.annotation.NonNull;
35 | import androidx.core.content.ContextCompat;
36 | import androidx.core.graphics.drawable.DrawableCompat;
37 | import androidx.fragment.app.DialogFragment;
38 |
39 | import it.danieleverducci.nextcloudmaps.R;
40 |
41 | /**
42 | * Dialog to show and choose the sorting order for the file listing.
43 | */
44 | public class SortingOrderDialogFragment extends DialogFragment {
45 |
46 | private final static String TAG = SortingOrderDialogFragment.class.getSimpleName();
47 |
48 | public static final String SORTING_ORDER_FRAGMENT = "SORTING_ORDER_FRAGMENT";
49 | private static final String KEY_SORT_ORDER = "SORT_ORDER";
50 |
51 | private OnSortingOrderListener onSortingOrderListener;
52 | private View mView;
53 | private View[] mTaggedViews;
54 | private Button mCancel;
55 |
56 | private int mCurrentSortOrder;
57 |
58 | public static SortingOrderDialogFragment newInstance(int sortOrder) {
59 | SortingOrderDialogFragment dialogFragment = new SortingOrderDialogFragment();
60 |
61 | Bundle args = new Bundle();
62 | args.putInt(KEY_SORT_ORDER, sortOrder);
63 | dialogFragment.setArguments(args);
64 |
65 | return dialogFragment;
66 | }
67 |
68 | @Override
69 | public void onCreate(Bundle savedInstanceState) {
70 | super.onCreate(savedInstanceState);
71 |
72 | // keep the state of the fragment on configuration changes
73 | setRetainInstance(true);
74 |
75 | mView = null;
76 |
77 | Bundle arguments = getArguments();
78 | if (arguments == null) {
79 | throw new IllegalArgumentException("Arguments may not be null");
80 | }
81 | mCurrentSortOrder = arguments.getInt(KEY_SORT_ORDER, GeofavoriteAdapter.SORT_BY_TITLE);
82 | }
83 |
84 | @Override
85 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
86 | mView = inflater.inflate(R.layout.sorting_order_fragment, container, false);
87 |
88 | setupDialogElements(mView);
89 | setupListeners();
90 |
91 | return mView;
92 | }
93 |
94 | public void setOnSortingOrderListener(OnSortingOrderListener listener) {
95 | this.onSortingOrderListener = listener;
96 | }
97 |
98 | /**
99 | * find all relevant UI elements and set their values.
100 | * TODO: this is REALLY ugly.
101 | *
102 | * @param view the parent view
103 | */
104 | private void setupDialogElements(View view) {
105 | mCancel = view.findViewById(R.id.cancel);
106 |
107 | mTaggedViews = new View[8];
108 | mTaggedViews[0] = view.findViewById(R.id.sortByTitleAscending);
109 | mTaggedViews[0].setTag(GeofavoriteAdapter.SORT_BY_TITLE);
110 | mTaggedViews[1] = view.findViewById(R.id.sortByTitleAscendingText);
111 | mTaggedViews[1].setTag(GeofavoriteAdapter.SORT_BY_TITLE);
112 | mTaggedViews[2] = view.findViewById(R.id.sortByCreationDateDescending);
113 | mTaggedViews[2].setTag(GeofavoriteAdapter.SORT_BY_CREATED);
114 | mTaggedViews[3] = view.findViewById(R.id.sortByCreationDateDescendingText);
115 | mTaggedViews[3].setTag(GeofavoriteAdapter.SORT_BY_CREATED);
116 | mTaggedViews[4] = view.findViewById(R.id.sortByCategoryAscending);
117 | mTaggedViews[4].setTag(GeofavoriteAdapter.SORT_BY_CATEGORY);
118 | mTaggedViews[5] = view.findViewById(R.id.sortByCategoryAscendingText);
119 | mTaggedViews[5].setTag(GeofavoriteAdapter.SORT_BY_CATEGORY);
120 | mTaggedViews[6] = view.findViewById(R.id.sortByDistanceAscending);
121 | mTaggedViews[6].setTag(GeofavoriteAdapter.SORT_BY_DISTANCE);
122 | mTaggedViews[7] = view.findViewById(R.id.sortByDistanceAscendingText);
123 | mTaggedViews[7].setTag(GeofavoriteAdapter.SORT_BY_DISTANCE);
124 |
125 | setupActiveOrderSelection();
126 | }
127 |
128 | /**
129 | * tints the icon reflecting the actual sorting choice in the apps primary color.
130 | */
131 | private void setupActiveOrderSelection() {
132 | for (View view: mTaggedViews) {
133 | if (mCurrentSortOrder != (int) view.getTag()) {
134 | continue;
135 | }
136 | if (view instanceof ImageButton) {
137 | Drawable normalDrawable = ((ImageButton) view).getDrawable();
138 | Drawable wrapDrawable = DrawableCompat.wrap(normalDrawable);
139 | DrawableCompat.setTint(wrapDrawable, ContextCompat.getColor(getContext(), R.color.selector_item_selected));
140 | }
141 | if (view instanceof TextView) {
142 | ((TextView)view).setTextColor(ContextCompat.getColor(getContext(), R.color.selector_item_selected));
143 | ((TextView)view).setTypeface(Typeface.DEFAULT_BOLD);
144 | }
145 | }
146 | }
147 |
148 | /**
149 | * setup all listeners.
150 | */
151 | private void setupListeners() {
152 | mCancel.setOnClickListener(view -> dismiss());
153 |
154 | OnSortOrderClickListener sortOrderClickListener = new OnSortOrderClickListener();
155 |
156 | for (View view : mTaggedViews) {
157 | view.setOnClickListener(sortOrderClickListener);
158 | }
159 | }
160 |
161 | @Override
162 | @NonNull
163 | public Dialog onCreateDialog(Bundle savedInstanceState) {
164 | return super.onCreateDialog(savedInstanceState);
165 | }
166 |
167 | @Override
168 | public void onDestroyView() {
169 | if (getDialog() != null && getRetainInstance()) {
170 | getDialog().setDismissMessage(null);
171 | }
172 | super.onDestroyView();
173 | }
174 |
175 | private class OnSortOrderClickListener implements View.OnClickListener {
176 | @Override
177 | public void onClick(View v) {
178 | dismissAllowingStateLoss();
179 | if (onSortingOrderListener != null)
180 | onSortingOrderListener.onSortingOrderChosen((int) v.getTag());
181 | }
182 | }
183 |
184 | public interface OnSortingOrderListener {
185 | void onSortingOrderChosen(int sortSelection);
186 | }
187 | }
188 |
--------------------------------------------------------------------------------
/app/src/main/java/it/danieleverducci/nextcloudmaps/api/API.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Nextcloud Maps Geofavorites for Android
3 | *
4 | * @copyright Copyright (c) 2020 John Doe
5 | * @author John Doe
6 | *
7 | * This program is free software: you can redistribute it and/or modify
8 | * it under the terms of the GNU General Public License as published by
9 | * the Free Software Foundation, either version 3 of the License, or
10 | * (at your option) any later version.
11 | *
12 | * This program is distributed in the hope that it will be useful,
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | * GNU General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU General Public License
18 | * along with this program. If not, see .
19 | */
20 |
21 | package it.danieleverducci.nextcloudmaps.api;
22 |
23 | import java.util.List;
24 |
25 | import it.danieleverducci.nextcloudmaps.model.Geofavorite;
26 | import retrofit2.Call;
27 | import retrofit2.http.Body;
28 | import retrofit2.http.DELETE;
29 | import retrofit2.http.GET;
30 | import retrofit2.http.POST;
31 | import retrofit2.http.PUT;
32 | import retrofit2.http.Path;
33 |
34 | public interface API {
35 | String mApiEndpoint = "/index.php/apps/maps/api/1.0";
36 |
37 | @GET("/favorites")
38 | Call> getGeofavorites();
39 |
40 | @POST("/favorites")
41 | Call createGeofavorite (
42 | @Body Geofavorite geofavorite
43 | );
44 |
45 | @PUT("/favorites/{id}")
46 | Call updateGeofavorite (
47 | @Path("id") int id,
48 | @Body Geofavorite geofavorite
49 | );
50 |
51 | @DELETE("/favorites/{id}")
52 | Call deleteGeofavorite (
53 | @Path("id") int id
54 | );
55 | }
56 |
--------------------------------------------------------------------------------
/app/src/main/java/it/danieleverducci/nextcloudmaps/api/ApiProvider.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Nextcloud Maps Geofavorites for Android
3 | *
4 | * @copyright Copyright (c) 2020 John Doe
5 | * @author John Doe
6 | *
7 | * This program is free software: you can redistribute it and/or modify
8 | * it under the terms of the GNU General Public License as published by
9 | * the Free Software Foundation, either version 3 of the License, or
10 | * (at your option) any later version.
11 | *
12 | * This program is distributed in the hope that it will be useful,
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | * GNU General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU General Public License
18 | * along with this program. If not, see .
19 | */
20 |
21 | package it.danieleverducci.nextcloudmaps.api;
22 |
23 | import android.content.Context;
24 | import android.util.Log;
25 |
26 | import androidx.annotation.NonNull;
27 | import androidx.annotation.Nullable;
28 |
29 | import com.google.gson.GsonBuilder;
30 | import com.nextcloud.android.sso.api.NextcloudAPI;
31 | import com.nextcloud.android.sso.exceptions.NextcloudFilesAppAccountNotFoundException;
32 | import com.nextcloud.android.sso.exceptions.NoCurrentAccountSelectedException;
33 | import com.nextcloud.android.sso.helper.SingleAccountHelper;
34 | import com.nextcloud.android.sso.model.SingleSignOnAccount;
35 |
36 | import retrofit2.NextcloudRetrofitApiBuilder;
37 |
38 | public class ApiProvider {
39 | private static final String TAG = ApiProvider.class.getCanonicalName();
40 |
41 | protected static API mApi;
42 |
43 | @Nullable
44 | public static API getAPI(Context context) {
45 | if (mApi == null) {
46 | try {
47 | SingleSignOnAccount ssoAccount = SingleAccountHelper.getCurrentSingleSignOnAccount(context);
48 | NextcloudAPI nextcloudAPI = new NextcloudAPI(context, ssoAccount, new GsonBuilder().create());
49 |
50 | mApi = new NextcloudRetrofitApiBuilder(nextcloudAPI, API.mApiEndpoint).create(API.class);
51 | } catch (NextcloudFilesAppAccountNotFoundException | NoCurrentAccountSelectedException e) {
52 | Log.d(TAG, "setAccout() called with: ex = [" + e + "]");
53 | }
54 | }
55 |
56 | return mApi;
57 | }
58 |
59 | public static void logout() {
60 | mApi = null;
61 | }
62 | }
--------------------------------------------------------------------------------
/app/src/main/java/it/danieleverducci/nextcloudmaps/fragments/GeofavoriteListFragment.java:
--------------------------------------------------------------------------------
1 | package it.danieleverducci.nextcloudmaps.fragments;
2 |
3 | import static it.danieleverducci.nextcloudmaps.activity.main.GeofavoriteAdapter.SORT_BY_CATEGORY;
4 | import static it.danieleverducci.nextcloudmaps.activity.main.GeofavoriteAdapter.SORT_BY_CREATED;
5 | import static it.danieleverducci.nextcloudmaps.activity.main.GeofavoriteAdapter.SORT_BY_DISTANCE;
6 | import static it.danieleverducci.nextcloudmaps.activity.main.GeofavoriteAdapter.SORT_BY_TITLE;
7 |
8 | import android.os.Bundle;
9 | import android.view.LayoutInflater;
10 | import android.view.View;
11 | import android.view.ViewGroup;
12 |
13 | import androidx.annotation.NonNull;
14 | import androidx.annotation.Nullable;
15 | import androidx.appcompat.widget.AppCompatImageView;
16 | import androidx.fragment.app.FragmentTransaction;
17 | import androidx.lifecycle.Observer;
18 | import androidx.recyclerview.widget.LinearLayoutManager;
19 | import androidx.recyclerview.widget.RecyclerView;
20 | import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
21 |
22 | import java.util.ArrayList;
23 | import java.util.List;
24 |
25 | import it.danieleverducci.nextcloudmaps.R;
26 | import it.danieleverducci.nextcloudmaps.activity.main.GeofavoriteAdapter;
27 | import it.danieleverducci.nextcloudmaps.activity.main.MainActivity;
28 | import it.danieleverducci.nextcloudmaps.activity.main.SortingOrderDialogFragment;
29 | import it.danieleverducci.nextcloudmaps.model.Geofavorite;
30 | import it.danieleverducci.nextcloudmaps.utils.GeofavoritesFilter;
31 | import it.danieleverducci.nextcloudmaps.utils.SettingsManager;
32 |
33 | public class GeofavoriteListFragment extends GeofavoritesFragment implements SortingOrderDialogFragment.OnSortingOrderListener {
34 |
35 | private SwipeRefreshLayout swipeRefresh;
36 | private GeofavoriteAdapter geofavoriteAdapter;
37 |
38 | @Nullable
39 | @Override
40 | public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
41 | View v = inflater.inflate(R.layout.fragment_geofavorite_list, container, false);
42 |
43 | // Setup list
44 | int sortRule = SettingsManager.getGeofavoriteListSortBy(requireContext());
45 |
46 | RecyclerView recyclerView = v.findViewById(R.id.recycler_view);
47 | LinearLayoutManager layoutManager = new LinearLayoutManager(requireContext());
48 | recyclerView.setLayoutManager(layoutManager);
49 |
50 | GeofavoriteAdapter.ItemClickListener rvItemClickListener = new GeofavoriteAdapter.ItemClickListener() {
51 | @Override
52 | public void onItemClick(Geofavorite item) {
53 | openGeofavorite(item);
54 | }
55 |
56 | @Override
57 | public void onItemShareClick(Geofavorite item) {
58 | shareGeofavorite(item);
59 | }
60 |
61 | @Override
62 | public void onItemNavClick(Geofavorite item) {
63 | navigateToGeofavorite(item);
64 | }
65 |
66 | @Override
67 | public void onItemDeleteClick(Geofavorite item) {
68 | deleteGeofavorite(item);
69 | }
70 | };
71 |
72 | geofavoriteAdapter = new GeofavoriteAdapter(requireContext(), rvItemClickListener);
73 | recyclerView.setAdapter(geofavoriteAdapter);
74 | geofavoriteAdapter.setSortRule(sortRule);
75 |
76 | // Register for data source events
77 | mGeofavoritesFragmentViewModel.getIsUpdating().observe(getViewLifecycleOwner(), new Observer() {
78 | @Override
79 | public void onChanged(@Nullable Boolean changed) {
80 | if(Boolean.TRUE.equals(changed)){
81 | swipeRefresh.setRefreshing(true);
82 | }
83 | else{
84 | swipeRefresh.setRefreshing(false);
85 | }
86 | }
87 | });
88 |
89 | // Setup view listeners
90 | swipeRefresh = v.findViewById(R.id.swipe_refresh);
91 | swipeRefresh.setOnRefreshListener(() ->
92 | mGeofavoritesFragmentViewModel.updateGeofavorites());
93 |
94 | AppCompatImageView sortButton = v.findViewById(R.id.sort_mode);
95 | sortButton.setOnClickListener(view -> openSortingOrderDialogFragment(geofavoriteAdapter.getSortRule()));
96 |
97 | View showMapButton = v.findViewById(R.id.view_mode_map);
98 | showMapButton.setOnClickListener(View -> ((MainActivity)requireActivity()).showMap());
99 |
100 | return v;
101 | }
102 |
103 | @Override
104 | public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
105 | super.onViewCreated(view, savedInstanceState);
106 |
107 | // Set icons
108 | int sortRule = SettingsManager.getGeofavoriteListSortBy(requireContext());
109 | updateSortingIcon(sortRule);
110 | }
111 |
112 | @Override
113 | public void onDatasetChange(List items) {
114 | // Called when the items are loaded or a filtering happens
115 | geofavoriteAdapter.setGeofavoriteList(items);
116 | }
117 |
118 | @Override
119 | public void onSortingOrderChosen(int sortSelection) {
120 | geofavoriteAdapter.setSortRule(sortSelection);
121 | updateSortingIcon(sortSelection);
122 |
123 | SettingsManager.setGeofavoriteListSortBy(requireContext(), sortSelection);
124 | }
125 |
126 | private void openSortingOrderDialogFragment(int sortOrder) {
127 | FragmentTransaction fragmentTransaction = requireActivity().getSupportFragmentManager().beginTransaction();
128 | fragmentTransaction.addToBackStack(null);
129 |
130 | SortingOrderDialogFragment sodf = SortingOrderDialogFragment.newInstance(sortOrder);
131 | sodf.setOnSortingOrderListener(this);
132 | sodf.show(fragmentTransaction, SortingOrderDialogFragment.SORTING_ORDER_FRAGMENT);
133 | }
134 |
135 | private void updateSortingIcon(int sortSelection) {
136 | AppCompatImageView sortButton = requireView().findViewById(R.id.sort_mode);
137 | switch (sortSelection) {
138 | case SORT_BY_TITLE:
139 | sortButton.setImageResource(R.drawable.ic_alphabetical_asc);
140 | break;
141 | case SORT_BY_CREATED:
142 | sortButton.setImageResource(R.drawable.ic_modification_asc);
143 | break;
144 | case SORT_BY_CATEGORY:
145 | sortButton.setImageResource(R.drawable.ic_category_asc);
146 | break;
147 | case SORT_BY_DISTANCE:
148 | sortButton.setImageResource(R.drawable.ic_distance_asc);
149 | break;
150 | }
151 | }
152 |
153 | }
154 |
--------------------------------------------------------------------------------
/app/src/main/java/it/danieleverducci/nextcloudmaps/model/Geofavorite.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Nextcloud Maps Geofavorites for Android
3 | *
4 | * @copyright Copyright (c) 2020 John Doe
5 | * @author John Doe
6 | *
7 | * This program is free software: you can redistribute it and/or modify
8 | * it under the terms of the GNU General Public License as published by
9 | * the Free Software Foundation, either version 3 of the License, or
10 | * (at your option) any later version.
11 | *
12 | * This program is distributed in the hope that it will be useful,
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | * GNU General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU General Public License
18 | * along with this program. If not, see .
19 | */
20 |
21 | package it.danieleverducci.nextcloudmaps.model;
22 |
23 | import android.graphics.Color;
24 | import android.net.Uri;
25 | import android.widget.Filter;
26 |
27 | import androidx.annotation.NonNull;
28 | import androidx.annotation.Nullable;
29 |
30 | import com.google.gson.annotations.Expose;
31 | import com.google.gson.annotations.SerializedName;
32 |
33 | import org.threeten.bp.Instant;
34 | import org.threeten.bp.LocalDate;
35 | import org.threeten.bp.ZoneId;
36 |
37 | import java.io.Serializable;
38 | import java.util.ArrayList;
39 | import java.util.Comparator;
40 | import java.util.List;
41 |
42 | import it.danieleverducci.nextcloudmaps.utils.GeoUriParser;
43 |
44 | public class Geofavorite implements Serializable {
45 | public static final String DEFAULT_CATEGORY = "Personal";
46 | private static final double EARTH_RADIUS = 6371; // https://en.wikipedia.org/wiki/Earth_radius
47 |
48 | /**
49 | * JSON Definition:
50 | * {
51 | * "id": 20,
52 | * "name": "Ipermercato Collestrada",
53 | * "date_modified": 1626798839,
54 | * "date_created": 1626798825,
55 | * "lat": 43.08620320282127,
56 | * "lng": 12.481070617773184,
57 | * "category": "Personal",
58 | * "comment": "Strada Centrale Umbra 06135 Collestrada Umbria Italia",
59 | * "extensions": ""
60 | * }
61 | */
62 |
63 | @Expose
64 | @SerializedName("id") private int id;
65 |
66 | @Expose
67 | @Nullable
68 | @SerializedName("name") private String name;
69 |
70 | @Expose
71 | @SerializedName("date_modified") private long dateModified;
72 |
73 | @Expose
74 | @SerializedName("date_created") private long dateCreated;
75 |
76 | @Expose
77 | @SerializedName("lat") private double lat;
78 |
79 | @Expose
80 | @SerializedName("lng") private double lng;
81 |
82 | @Expose
83 | @SerializedName("category") private String category;
84 |
85 | @Expose
86 | @Nullable
87 | @SerializedName("comment") private String comment;
88 |
89 | public int getId() {
90 | return id;
91 | }
92 |
93 | public void setId(int id) {
94 | this.id = id;
95 | }
96 |
97 | @Nullable
98 | public String getName() {
99 | return name;
100 | }
101 |
102 | public void setName(String name) {
103 | if (!name.equals(this.name))
104 | this.name = name;
105 | }
106 |
107 | public long getDateModified() {
108 | return dateModified;
109 | }
110 | public void setDateModified(long dateModified) {
111 | this.dateModified = dateModified;
112 | }
113 | public LocalDate getLocalDateModified() {
114 | return Instant.ofEpochSecond(getDateCreated()).atZone(ZoneId.systemDefault()).toLocalDate();
115 | }
116 |
117 | public long getDateCreated() {
118 | return dateCreated;
119 | }
120 | public LocalDate getLocalDateCreated() {
121 | return Instant.ofEpochSecond(getDateCreated()).atZone(ZoneId.systemDefault()).toLocalDate();
122 | }
123 |
124 | public void setDateCreated(long dateCreated) {
125 | this.dateCreated = dateCreated;
126 | }
127 |
128 | public double getLat() {
129 | return lat;
130 | }
131 | public void setLat(double lat) {
132 | this.lat = lat;
133 | }
134 |
135 | public double getLng() {
136 | return lng;
137 | }
138 | public void setLng(double lng) {
139 | this.lng = lng;
140 | }
141 |
142 | public String getCategory() {
143 | return category;
144 | }
145 | public void setCategory(String category) {
146 | this.category = category;
147 | }
148 |
149 | @Nullable
150 | public String getComment() {
151 | return comment;
152 | }
153 | public void setComment(String comment) {
154 | this.comment = comment;
155 | }
156 |
157 | /**
158 | * Comparators for list order
159 | */
160 | public static Comparator ByTitleAZ = (gf0, gf1) -> gf0.name.compareTo(gf1.name);
161 | public static Comparator ByLastCreated = (gf0, gf1) -> (int) (gf1.dateCreated - gf0.dateCreated);
162 | public static Comparator ByCategory = (gf0, gf1) -> (gf0.category + gf0.name).compareTo(gf1.category + gf1.name);
163 | public static Comparator ByDistance = (gf0, gf1) -> 0; // (int) ((gf1.getDistanceFrom(userPosition) - gf0.getDistanceFrom(userPosition)) * 1000);
164 |
165 | public String getCoordinatesString() {
166 | return this.lat + " N, " + this.lng + " E";
167 | }
168 |
169 | public Uri getGeoUri() {
170 | return GeoUriParser.createGeoUri(this.lat, this.lng, this.name);
171 | }
172 | public Uri getGmapsUri() {
173 | return GeoUriParser.createGmapsUri(this.lat, this.lng);
174 | }
175 |
176 | public boolean valid() {
177 | return
178 | getLat() != 0 && getLng() != 0 &&
179 | getName() != null && getName().length() > 0 &&
180 | getCategory() != null && getCategory().length() > 0;
181 | }
182 |
183 | /**
184 | * Returns the distance between the current Geofavorite and the provided one, in kilometers.
185 | * @param other Geovavorite
186 | * @return the distance in kilometers
187 | */
188 | public double getDistanceFrom(Geofavorite other) {
189 | double latDistance = (other.lat-lat) * Math.PI / 180;
190 | double lonDistance = (other.lng-lng) * Math.PI / 180;
191 | double a =
192 | Math.sin(latDistance / 2) * Math.sin(latDistance / 2) +
193 | Math.cos(lat * Math.PI / 180) * Math.cos(other.lat * Math.PI / 180) *
194 | Math.sin(lonDistance / 2) * Math.sin(lonDistance / 2);
195 | double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
196 | return EARTH_RADIUS * c;
197 | }
198 |
199 | /**
200 | * Based on Nextcloud Maps's getLetterColor util.
201 | * Assigns a color to a category based on its two first letters.
202 | *
203 | * @see "https://github.com/nextcloud/maps/blob/master/src/utils.js"
204 | * @return the generated color or null for the default category
205 | */
206 | public int categoryColor() {
207 | return categoryColorFromName(this.category);
208 | }
209 |
210 | public String categoryLetter() {
211 | if (category == null || category.length() == 0 || category.equals(DEFAULT_CATEGORY))
212 | return "\u2022";
213 | return category.substring(0,1);
214 | }
215 |
216 | @NonNull
217 | @Override
218 | public String toString() {
219 | return "[" + getName() + " (" + getLat() + "," + getLng() + ")]";
220 | }
221 |
222 |
223 |
224 | /**
225 | * Based on Nextcloud Maps's getLetterColor util.
226 | * Assigns a color to a category based on its two first letters.
227 | *
228 | * @see "https://github.com/nextcloud/maps/blob/master/src/utils.js"
229 | * @return the generated color or null for the default category
230 | */
231 | public static int categoryColorFromName(String category) {
232 | // If category is default, return null: will be used Nextcloud's accent
233 | if (category == null || category.equals(DEFAULT_CATEGORY) || category.length() == 0)
234 | return 0;
235 |
236 | float letter1Index = category.toLowerCase().charAt(0);
237 | float letter2Index = category.toLowerCase().charAt(1);
238 | float letterCoef = ((letter1Index * letter2Index) % 100) / 100;
239 | float h = letterCoef * 360;
240 | float s = 75 + letterCoef * 10;
241 | float l = 50 + letterCoef * 10;
242 | return Color.HSVToColor( new float[]{ Math.round(h), Math.round(s), Math.round(l) });
243 | }
244 |
245 | }
246 |
--------------------------------------------------------------------------------
/app/src/main/java/it/danieleverducci/nextcloudmaps/repository/GeofavoriteRepository.java:
--------------------------------------------------------------------------------
1 | package it.danieleverducci.nextcloudmaps.repository;
2 |
3 | import android.content.Context;
4 | import android.util.Log;
5 |
6 | import androidx.annotation.NonNull;
7 | import androidx.lifecycle.MutableLiveData;
8 |
9 | import java.util.ArrayList;
10 | import java.util.HashSet;
11 | import java.util.List;
12 |
13 | import it.danieleverducci.nextcloudmaps.api.ApiProvider;
14 | import it.danieleverducci.nextcloudmaps.model.Geofavorite;
15 | import it.danieleverducci.nextcloudmaps.utils.SingleLiveEvent;
16 | import retrofit2.Call;
17 | import retrofit2.Callback;
18 | import retrofit2.Response;
19 |
20 | /**
21 | * Singleton pattern
22 | */
23 | public class GeofavoriteRepository {
24 |
25 | private static final String TAG = "GeofavoriteRepository";
26 | private static GeofavoriteRepository instance;
27 | private MutableLiveData> mGeofavorites;
28 | private MutableLiveData> mCategories = new MutableLiveData>();
29 | private MutableLiveData mIsUpdating = new MutableLiveData<>(false);
30 | private SingleLiveEvent mOnFinished = new SingleLiveEvent<>();
31 |
32 | private Context applicationContext;
33 |
34 | public GeofavoriteRepository(Context applicationContext) {
35 | this.applicationContext = applicationContext;
36 | }
37 |
38 | public static GeofavoriteRepository getInstance(Context applicationContext) {
39 | if(instance == null){
40 | instance = new GeofavoriteRepository(applicationContext);
41 | }
42 | return instance;
43 | }
44 |
45 | public static void resetInstance() {
46 | instance = null;
47 | }
48 |
49 | public MutableLiveData> getGeofavorites(){
50 | if (mGeofavorites == null) {
51 | mGeofavorites = new MutableLiveData<>();
52 | mGeofavorites.setValue(new ArrayList<>());
53 | }
54 | return mGeofavorites;
55 | }
56 |
57 | public MutableLiveData> getCategories() {
58 | return mCategories;
59 | }
60 |
61 | public MutableLiveData isUpdating() {
62 | return mIsUpdating;
63 | }
64 |
65 | public SingleLiveEvent onFinished() {
66 | return mOnFinished;
67 | }
68 |
69 | public void updateGeofavorites() {
70 | mIsUpdating.postValue(true);
71 | // Obtain geofavorites
72 | Call> call = ApiProvider.getAPI(this.applicationContext).getGeofavorites();
73 | call.enqueue(new Callback>() {
74 | @Override
75 | public void onResponse(@NonNull Call> call, @NonNull Response> response) {
76 | if (response.isSuccessful() && response.body() != null) {
77 | mGeofavorites.postValue(response.body());
78 | updateCategories(response.body());
79 | mIsUpdating.postValue(false);
80 | mOnFinished.postValue(true);
81 | } else {
82 | onFailure(call, new Throwable("Dataset is empty"));
83 | }
84 | }
85 |
86 | @Override
87 | public void onFailure(@NonNull Call> call, @NonNull Throwable t) {
88 | mIsUpdating.postValue(false);
89 | mOnFinished.postValue(false);
90 | }
91 | });
92 | }
93 |
94 | public Geofavorite getGeofavorite(int id) {
95 | for (Geofavorite g : mGeofavorites.getValue()) {
96 | if (g.getId() == id)
97 | return g;
98 | }
99 | return null;
100 | }
101 |
102 | public void saveGeofavorite(Geofavorite geofav) {
103 | mIsUpdating.postValue(true);
104 | Call call;
105 | if (geofav.getId() == 0) {
106 | // New geofavorite
107 | call = ApiProvider.getAPI(this.applicationContext).createGeofavorite(geofav);
108 | } else {
109 | // Update existing geofavorite
110 | call = ApiProvider.getAPI(this.applicationContext).updateGeofavorite(geofav.getId(), geofav);
111 | }
112 | call.enqueue(new Callback() {
113 | @Override
114 | public void onResponse(Call call, Response response) {
115 | if (response.isSuccessful()) {
116 | List geofavs = mGeofavorites.getValue();
117 | if (geofav.getId() != 0) {
118 | geofavs.remove(geofav);
119 | }
120 | geofavs.add(response.body());
121 | mGeofavorites.postValue(geofavs);
122 | mIsUpdating.postValue(false);
123 | mOnFinished.postValue(true);
124 | } else {
125 | mIsUpdating.postValue(false);
126 | mOnFinished.postValue(false);
127 | }
128 | }
129 |
130 | @Override
131 | public void onFailure(Call call, Throwable t) {
132 | Log.e(TAG, t.getMessage());
133 | mIsUpdating.postValue(false);
134 | mOnFinished.postValue(false);
135 | }
136 | });
137 | }
138 |
139 | public void deleteGeofavorite(Geofavorite geofav) {
140 | mIsUpdating.postValue(true);
141 | // Delete Geofavorite
142 | Call call = ApiProvider.getAPI(this.applicationContext).deleteGeofavorite(geofav.getId());
143 | call.enqueue(new Callback() {
144 | @Override
145 | public void onResponse(Call call, Response response) {
146 | List geofavs = mGeofavorites.getValue();
147 | if (geofavs.remove(geofav)) {
148 | mGeofavorites.postValue(geofavs);
149 | mIsUpdating.postValue(false);
150 | mOnFinished.postValue(true);
151 | } else {
152 | // Should never happen
153 | mIsUpdating.postValue(false);
154 | mOnFinished.postValue(false);
155 | }
156 | }
157 |
158 | @Override
159 | public void onFailure(Call call, Throwable t) {
160 | mIsUpdating.postValue(false);
161 | mOnFinished.postValue(false);
162 | }
163 | });
164 | }
165 |
166 | private void updateCategories(List geofavs) {
167 | HashSet categories = new HashSet<>();
168 | for (Geofavorite g : geofavs) {
169 | String cat = g.getCategory();
170 | if (cat != null)
171 | categories.add(cat);
172 | }
173 | mCategories.postValue(categories);
174 | }
175 |
176 | }
177 |
--------------------------------------------------------------------------------
/app/src/main/java/it/danieleverducci/nextcloudmaps/utils/GeoUriParser.java:
--------------------------------------------------------------------------------
1 | package it.danieleverducci.nextcloudmaps.utils;
2 |
3 | import android.net.Uri;
4 | import android.util.Log;
5 |
6 | import java.util.regex.Matcher;
7 | import java.util.regex.Pattern;
8 |
9 | import it.danieleverducci.nextcloudmaps.model.Geofavorite;
10 |
11 | public class GeoUriParser {
12 | private static final Pattern PATTERN_GEO = Pattern.compile("geo:(-?[\\d.]+),(-?[\\d.]+)");
13 | // Try to match not only geoUri but also Google Maps Uri
14 | private static final Pattern PATTERN_BROAD = Pattern.compile(
15 | "(?:@|&query=|&ce\nter=|geo:|#map=\\d{1,2}\\/)(-?\\d{1,2}\\.\\d+)(?:,|%2C|\\/)(-?\\d{1,3}\\.\\d{1,10})"
16 | );
17 |
18 | /**
19 | * Parses an URI into latitude and longitude
20 | * @param uri to parse
21 | * @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
22 | * @return the parsed coordinates in an array [lat,lon]
23 | * @throws IllegalArgumentException if the url could not be parsed
24 | */
25 | public static double[] parseUri(Uri uri, boolean strict) throws IllegalArgumentException {
26 | if (uri == null)
27 | throw new IllegalArgumentException("no uri");
28 |
29 | // Try to extract coordinates in uri string with regexp
30 | Pattern pattern = strict ? PATTERN_GEO : PATTERN_BROAD;
31 | Matcher m = pattern.matcher(uri.toString());
32 | if (!m.find() || m.groupCount() != 2)
33 | throw new IllegalArgumentException("unable to parse uri: unable to find coordinates in uri");
34 |
35 | // Obtain coordinates from regexp result
36 | String sLat = m.group(1);
37 | String sLon = m.group(2);
38 | double[] coords = null;
39 | try {
40 | // Check coordinates are numeric
41 | coords = new double[]{Double.parseDouble(sLat), Double.parseDouble(sLon)};
42 | } catch (NumberFormatException e) {
43 | throw new IllegalArgumentException("unable to parse uri: coordinates are not double");
44 | }
45 |
46 | // Check coordinates validity
47 | String error = checkCoordsValidity(coords[0], coords[1]);
48 | if (error != null)
49 | throw new IllegalArgumentException(error);
50 |
51 | return coords;
52 | }
53 |
54 | public static Uri createGeoUri(double lat, double lon, String name) {
55 | String error = checkCoordsValidity(lat, lon);
56 | if (error != null)
57 | throw new IllegalArgumentException(error);
58 |
59 | String uriStr = "geo:" + lat + "," + lon;
60 | if (name != null)
61 | uriStr += "(" + name + ")";
62 | return Uri.parse(uriStr);
63 | }
64 |
65 | public static Uri createGmapsUri(double lat, double lon) {
66 | String error = checkCoordsValidity(lat, lon);
67 | if (error != null)
68 | throw new IllegalArgumentException(error);
69 |
70 | String uriStr = "https://www.google.com/maps/search/?api=1&query=" + lat + "," + lon;
71 | return Uri.parse(uriStr);
72 | }
73 |
74 | /**
75 | * Checks a latitude/longitude is valid
76 | * @param lat latitude
77 | * @param lon longitude
78 | * @return null if valid, a string containing an error otherwise
79 | */
80 | private static String checkCoordsValidity(double lat, double lon) {
81 | // Check coords validity
82 | if (lon <= -180 || lon >= 180 )
83 | return "Invalid longitude: " + lon;
84 | if (lat <= -90 || lat >= 90)
85 | return "Invalid latitude: " + lat;
86 | return null;
87 | }
88 | }
89 |
--------------------------------------------------------------------------------
/app/src/main/java/it/danieleverducci/nextcloudmaps/utils/GeofavoritesFilter.java:
--------------------------------------------------------------------------------
1 | package it.danieleverducci.nextcloudmaps.utils;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 |
6 | import it.danieleverducci.nextcloudmaps.model.Geofavorite;
7 |
8 | public class GeofavoritesFilter {
9 | List items;
10 | public GeofavoritesFilter(List items) {
11 | this.items = items;
12 | }
13 |
14 | public List byText(String text) {
15 | List filteredGeofavorites = new ArrayList<>();
16 |
17 | if (text.isEmpty()) {
18 | return items;
19 | } else {
20 | for (Geofavorite geofavorite : items) {
21 | String query = text.toLowerCase();
22 | if (geofavorite.getName() != null && geofavorite.getName().toLowerCase().contains(query)) {
23 | filteredGeofavorites.add(geofavorite);
24 | } else if (geofavorite.getComment() != null && geofavorite.getComment().toLowerCase().contains(query)) {
25 | filteredGeofavorites.add(geofavorite);
26 | }
27 | }
28 | }
29 | return filteredGeofavorites;
30 | }
31 |
32 | public List byCategory(String category) {
33 | List filteredGeofavorites = new ArrayList<>();
34 |
35 | if (category == null) {
36 | return items;
37 | } else {
38 | for (Geofavorite geofavorite : items) {
39 | if (geofavorite.getCategory().equals(category)) {
40 | filteredGeofavorites.add(geofavorite);
41 | }
42 | }
43 | }
44 | return filteredGeofavorites;
45 |
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/app/src/main/java/it/danieleverducci/nextcloudmaps/utils/IntentGenerator.java:
--------------------------------------------------------------------------------
1 | package it.danieleverducci.nextcloudmaps.utils;
2 |
3 | import android.content.Context;
4 | import android.content.Intent;
5 | import android.content.pm.PackageManager;
6 | import android.util.Log;
7 |
8 | import it.danieleverducci.nextcloudmaps.R;
9 | import it.danieleverducci.nextcloudmaps.model.Geofavorite;
10 |
11 | public class IntentGenerator {
12 | public static Intent newShareIntent(Context context, Geofavorite item) {
13 | Intent i = new Intent();
14 | i.setAction(Intent.ACTION_SEND);
15 | i.setType("text/plain");
16 | String shareMessage = context.getString(R.string.share_message)
17 | .replace("{title}", item.getName() == null ? context.getString(R.string.share_message_default_title) : item.getName())
18 | .replace("{lat}", ""+item.getLat())
19 | .replace("{lng}", ""+item.getLng());
20 | i.putExtra(Intent.EXTRA_TEXT, shareMessage );
21 | return i;
22 | }
23 |
24 | public static Intent newGeoUriIntent(Context context, Geofavorite item) {
25 | Intent i = new Intent();
26 | i.setAction(Intent.ACTION_VIEW);
27 | i.setData(isGoogleMapsInstalled(context) ? item.getGmapsUri() : item.getGeoUri());
28 | return i;
29 | }
30 |
31 | public static boolean isGoogleMapsInstalled(Context context) {
32 | try {
33 | context.getPackageManager().getApplicationInfo("com.google.android.apps.maps", 0);
34 | return true;
35 | } catch (PackageManager.NameNotFoundException e) {
36 | return false;
37 | }
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/app/src/main/java/it/danieleverducci/nextcloudmaps/utils/MapUtils.java:
--------------------------------------------------------------------------------
1 | package it.danieleverducci.nextcloudmaps.utils;
2 |
3 | import android.content.Context;
4 | import android.content.res.Configuration;
5 |
6 | import androidx.preference.PreferenceManager;
7 |
8 | import org.osmdroid.config.IConfigurationProvider;
9 | import org.osmdroid.views.MapView;
10 | import org.osmdroid.views.overlay.TilesOverlay;
11 |
12 | import it.danieleverducci.nextcloudmaps.BuildConfig;
13 |
14 | public class MapUtils {
15 |
16 | public static void configOsmdroid(Context context) {
17 | IConfigurationProvider osmdroidConfig = org.osmdroid.config.Configuration.getInstance();
18 | osmdroidConfig.load(context,
19 | PreferenceManager.getDefaultSharedPreferences(context));
20 | osmdroidConfig.setUserAgentValue(BuildConfig.APPLICATION_ID);
21 | }
22 |
23 | public static void setTheme(MapView mapView) {
24 | int currentNightMode = mapView.getContext().getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK;
25 | switch (currentNightMode) {
26 | case Configuration.UI_MODE_NIGHT_NO:
27 | // Night mode is not active, we're using the light theme
28 | mapView.getOverlayManager().getTilesOverlay().setColorFilter(null);
29 | break;
30 | case Configuration.UI_MODE_NIGHT_YES:
31 | // Night mode is active, we're using dark theme
32 | mapView.getOverlayManager().getTilesOverlay().setColorFilter(TilesOverlay.INVERT_COLORS);
33 | break;
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/app/src/main/java/it/danieleverducci/nextcloudmaps/utils/SettingsManager.java:
--------------------------------------------------------------------------------
1 | package it.danieleverducci.nextcloudmaps.utils;
2 |
3 | import android.content.Context;
4 | import android.content.SharedPreferences;
5 |
6 | import androidx.preference.PreferenceManager;
7 | import it.danieleverducci.nextcloudmaps.activity.main.GeofavoriteAdapter;
8 |
9 | public class SettingsManager {
10 | static private final String SETTING_SORT_BY = "SETTING_SORT_BY";
11 | static private final String SETTING_LAST_SELECTED_LIST_VIEW = "SETTING_LAST_SELECTED_LIST_VIEW";
12 | static private final String SETTING_LAST_MAP_POSITION_LAT = "SETTING_LAST_MAP_POSITION_LAT";
13 | static private final String SETTING_LAST_MAP_POSITION_LNG = "SETTING_LAST_MAP_POSITION_LNG";
14 | static private final String SETTING_LAST_MAP_POSITION_ZOOM = "SETTING_LAST_MAP_POSITION_ZOOM";
15 |
16 | public static int getGeofavoriteListSortBy(Context context) {
17 | return PreferenceManager.getDefaultSharedPreferences(context)
18 | .getInt(SETTING_SORT_BY, GeofavoriteAdapter.SORT_BY_CREATED);
19 | }
20 |
21 | public static void setGeofavoriteListSortBy(Context context, int value) {
22 | PreferenceManager.getDefaultSharedPreferences(context)
23 | .edit().putInt(SETTING_SORT_BY, value).apply();
24 | }
25 |
26 | public static boolean isGeofavoriteListShownAsMap(Context context) {
27 | return PreferenceManager.getDefaultSharedPreferences(context)
28 | .getBoolean(SETTING_LAST_SELECTED_LIST_VIEW, false);
29 | }
30 |
31 | public static void setGeofavoriteListShownAsMap(Context context, boolean value) {
32 | PreferenceManager.getDefaultSharedPreferences(context)
33 | .edit().putBoolean(SETTING_LAST_SELECTED_LIST_VIEW, value).apply();
34 | }
35 |
36 | /**
37 | * Returns the last saved position
38 | * @param context
39 | * @return double[lat,lng,zoom]
40 | */
41 | public static double[] getLastMapPosition(Context context) {
42 | SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
43 | return new double[] {
44 | (double) sp.getFloat(SETTING_LAST_MAP_POSITION_LAT, 0.0f),
45 | (double) sp.getFloat(SETTING_LAST_MAP_POSITION_LNG, 0.0f),
46 | (double) sp.getFloat(SETTING_LAST_MAP_POSITION_ZOOM, 10.0f),
47 | };
48 | }
49 |
50 | public static void setLastMapPosition(Context context, double lat, double lng, double zoom) {
51 | PreferenceManager.getDefaultSharedPreferences(context).edit()
52 | .putFloat(SETTING_LAST_MAP_POSITION_LAT, (float)lat)
53 | .putFloat(SETTING_LAST_MAP_POSITION_LNG, (float)lng)
54 | .putFloat(SETTING_LAST_MAP_POSITION_ZOOM, (float)zoom)
55 | .apply();
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/app/src/main/java/it/danieleverducci/nextcloudmaps/utils/SingleLiveEvent.java:
--------------------------------------------------------------------------------
1 | package it.danieleverducci.nextcloudmaps.utils;
2 |
3 | import androidx.annotation.MainThread;
4 | import androidx.annotation.NonNull;
5 | import androidx.lifecycle.LifecycleOwner;
6 | import androidx.lifecycle.MutableLiveData;
7 | import androidx.lifecycle.Observer;
8 | import java.util.concurrent.atomic.AtomicBoolean;
9 |
10 | /**
11 | * Events implementation in LiveData
12 | * From: https://gist.github.com/teegarcs/319a3e7e4736a0cce8eba2216c52b0ca#file-singleliveevent
13 | * @param
14 | */
15 | public class SingleLiveEvent extends MutableLiveData {
16 | AtomicBoolean mPending = new AtomicBoolean(false);
17 |
18 | @MainThread
19 | @Override
20 | public void setValue(T value) {
21 | mPending.set(true);
22 | super.setValue(value);
23 | }
24 |
25 | @MainThread
26 | @Override
27 | public void observe(@NonNull LifecycleOwner owner, @NonNull Observer super T> observer) {
28 | super.observe(owner, new Observer() {
29 | @Override
30 | public void onChanged(T t) {
31 | if (mPending.compareAndSet(true, false)) {
32 | observer.onChanged(t);
33 | }
34 | }
35 | });
36 | }
37 |
38 | /**
39 | * Util function for Void implementations.
40 | */
41 | public void call() {
42 | setValue(null);
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/app/src/main/java/it/danieleverducci/nextcloudmaps/views/GeofavMarkerInfoWindow.java:
--------------------------------------------------------------------------------
1 | package it.danieleverducci.nextcloudmaps.views;
2 |
3 | import android.content.Context;
4 | import android.graphics.drawable.Drawable;
5 | import android.view.View;
6 |
7 | import androidx.appcompat.content.res.AppCompatResources;
8 | import androidx.core.graphics.drawable.DrawableCompat;
9 |
10 | import org.osmdroid.views.MapView;
11 | import org.osmdroid.views.overlay.infowindow.InfoWindow;
12 | import org.osmdroid.views.overlay.infowindow.MarkerInfoWindow;
13 |
14 | import it.danieleverducci.nextcloudmaps.R;
15 | import it.danieleverducci.nextcloudmaps.model.Geofavorite;
16 |
17 | public class GeofavMarkerInfoWindow extends MarkerInfoWindow implements View.OnClickListener {
18 | private OnGeofavMarkerInfoWindowClickListener onGeofavMarkerInfoWindowClickListener;
19 |
20 | public GeofavMarkerInfoWindow(MapView mapView, Geofavorite geofavorite) {
21 | super(R.layout.infowindow_geofav, mapView);
22 | Context context = getView().getContext();
23 |
24 | // Set category color
25 | View category = getView().findViewById(R.id.bubble_subdescription);
26 | Drawable backgroundDrawable = category.getBackground();
27 | DrawableCompat.setTint(backgroundDrawable, geofavorite.categoryColor() == 0 ? context.getColor(R.color.defaultBrand) : geofavorite.categoryColor());
28 |
29 | // Set listeners
30 | getView().findViewById(R.id.action_icon_share).setOnClickListener(this);
31 | getView().findViewById(R.id.action_icon_nav).setOnClickListener(this);
32 | getView().findViewById(R.id.action_icon_delete).setOnClickListener(this);
33 | getView().findViewById(R.id.action_icon_edit).setOnClickListener(this);
34 | }
35 |
36 | public void setOnGeofavMarkerInfoWindowClickListener(OnGeofavMarkerInfoWindowClickListener l) {
37 | this.onGeofavMarkerInfoWindowClickListener = l;
38 | }
39 |
40 | @Override
41 | public void onOpen(Object item) {
42 | InfoWindow.closeAllInfoWindowsOn(getMapView());
43 | super.onOpen(item);
44 | }
45 |
46 |
47 | @Override
48 | public void onClick(View v) {
49 | if (onGeofavMarkerInfoWindowClickListener == null)
50 | return;
51 |
52 | if (v.getId() == R.id.action_icon_share)
53 | onGeofavMarkerInfoWindowClickListener.onGeofavMarkerInfoWindowShareClick();
54 |
55 | if (v.getId() == R.id.action_icon_nav)
56 | onGeofavMarkerInfoWindowClickListener.onGeofavMarkerInfoWindowNavClick();
57 |
58 | if (v.getId() == R.id.action_icon_delete)
59 | onGeofavMarkerInfoWindowClickListener.onGeofavMarkerInfoWindowDeleteClick();
60 |
61 | if (v.getId() == R.id.action_icon_edit)
62 | onGeofavMarkerInfoWindowClickListener.onGeofavMarkerInfoWindowEditClick();
63 | }
64 |
65 |
66 | public interface OnGeofavMarkerInfoWindowClickListener {
67 | public void onGeofavMarkerInfoWindowEditClick();
68 | public void onGeofavMarkerInfoWindowShareClick();
69 | public void onGeofavMarkerInfoWindowNavClick();
70 | public void onGeofavMarkerInfoWindowDeleteClick();
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/floating_semitransparent_button_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | -
4 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/geofav_infowindow_pointer.xml:
--------------------------------------------------------------------------------
1 |
6 |
13 |
14 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_accuracy_fail.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_accuracy_ok.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_add.xml:
--------------------------------------------------------------------------------
1 |
17 |
18 |
24 |
26 |
27 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_add_gps.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_add_map.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_alphabetical_asc.xml:
--------------------------------------------------------------------------------
1 |
17 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_app.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_back_grey.xml:
--------------------------------------------------------------------------------
1 |
17 |
18 |
25 |
27 |
28 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_category_asc.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
13 |
16 |
17 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_clear.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_copy.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_delete_grey.xml:
--------------------------------------------------------------------------------
1 |
17 |
18 |
24 |
27 |
28 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_distance_asc.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_edit.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_filter.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_filter_off.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_info_grey.xml:
--------------------------------------------------------------------------------
1 |
17 |
18 |
25 |
27 |
28 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
7 |
11 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_list_pin.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_logout_grey.xml:
--------------------------------------------------------------------------------
1 |
17 |
18 |
25 |
28 |
31 |
32 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_map_pin.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_menu_grey.xml:
--------------------------------------------------------------------------------
1 |
17 |
18 |
25 |
28 |
29 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_modification_asc.xml:
--------------------------------------------------------------------------------
1 |
17 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_more.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_nav.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_ok.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_save_grey.xml:
--------------------------------------------------------------------------------
1 |
17 |
18 |
24 |
27 |
28 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_share.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_time_grey.xml:
--------------------------------------------------------------------------------
1 |
17 |
18 |
25 |
27 |
28 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_view_list.xml:
--------------------------------------------------------------------------------
1 |
17 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_view_map.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/infowindow_geofav_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/round_button_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | -
4 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/rounded_label_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/unselected_floating_semitransparent_button_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | -
4 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/user_badge_mask.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | -
5 |
9 |
10 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_about.xml:
--------------------------------------------------------------------------------
1 |
2 |
18 |
19 |
26 |
27 |
31 |
32 |
39 |
40 |
45 |
46 |
55 |
56 |
61 |
62 |
69 |
70 |
75 |
76 |
82 |
83 |
90 |
91 |
96 |
97 |
104 |
105 |
110 |
111 |
118 |
119 |
124 |
125 |
132 |
133 |
134 |
135 |
136 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_list_view.xml:
--------------------------------------------------------------------------------
1 |
2 |
18 |
24 |
25 |
31 |
32 |
33 |
34 |
46 |
47 |
48 |
59 |
60 |
61 |
71 |
72 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_login.xml:
--------------------------------------------------------------------------------
1 |
2 |
18 |
19 |
29 |
30 |
39 |
40 |
50 |
51 |
64 |
65 |
74 |
75 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
18 |
19 |
28 |
29 |
33 |
34 |
35 |
40 |
41 |
46 |
47 |
51 |
52 |
57 |
58 |
66 |
67 |
82 |
83 |
84 |
93 |
94 |
95 |
96 |
97 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_map_picker.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
8 |
9 |
13 |
14 |
21 |
22 |
32 |
33 |
43 |
44 |
51 |
52 |
62 |
63 |
70 |
71 |
82 |
83 |
90 |
91 |
102 |
103 |
104 |
105 |
106 |
107 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/app_toolbar.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
18 |
19 |
26 |
27 |
28 |
29 |
30 |
42 |
43 |
47 |
48 |
61 |
74 |
75 |
76 |
83 |
84 |
85 |
89 |
94 |
98 |
99 |
100 |
101 |
102 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/category_listitem.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
26 |
27 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_geofavorite_list.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
10 |
11 |
16 |
17 |
24 |
25 |
26 |
27 |
35 |
36 |
47 |
48 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
71 |
72 |
75 |
76 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_geofavorite_map.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
10 |
11 |
15 |
16 |
22 |
23 |
28 |
29 |
30 |
31 |
37 |
38 |
39 |
40 |
53 |
54 |
55 |
56 |
68 |
69 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/infowindow_geofav.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
15 |
16 |
17 |
27 |
28 |
29 |
38 |
39 |
40 |
57 |
58 |
62 |
63 |
64 |
65 |
73 |
74 |
82 |
83 |
91 |
92 |
100 |
101 |
102 |
103 |
108 |
109 |
110 |
111 |
118 |
119 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_geofav.xml:
--------------------------------------------------------------------------------
1 |
2 |
18 |
19 |
29 |
30 |
43 |
44 |
51 |
52 |
63 |
64 |
65 |
69 |
70 |
83 |
84 |
85 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
110 |
111 |
119 |
120 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_navigation.xml:
--------------------------------------------------------------------------------
1 |
17 |
18 |
29 |
30 |
39 |
40 |
50 |
51 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/list_context_menu.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/penguin86/nextcloud-maps-client/bd8a0d706dc7bbb34c8b958dc1a24d0e8897bd33/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/penguin86/nextcloud-maps-client/bd8a0d706dc7bbb34c8b958dc1a24d0e8897bd33/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_person.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/penguin86/nextcloud-maps-client/bd8a0d706dc7bbb34c8b958dc1a24d0e8897bd33/app/src/main/res/mipmap-hdpi/ic_person.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/penguin86/nextcloud-maps-client/bd8a0d706dc7bbb34c8b958dc1a24d0e8897bd33/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/penguin86/nextcloud-maps-client/bd8a0d706dc7bbb34c8b958dc1a24d0e8897bd33/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_person.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/penguin86/nextcloud-maps-client/bd8a0d706dc7bbb34c8b958dc1a24d0e8897bd33/app/src/main/res/mipmap-mdpi/ic_person.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/penguin86/nextcloud-maps-client/bd8a0d706dc7bbb34c8b958dc1a24d0e8897bd33/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/penguin86/nextcloud-maps-client/bd8a0d706dc7bbb34c8b958dc1a24d0e8897bd33/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_person.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/penguin86/nextcloud-maps-client/bd8a0d706dc7bbb34c8b958dc1a24d0e8897bd33/app/src/main/res/mipmap-xhdpi/ic_person.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/penguin86/nextcloud-maps-client/bd8a0d706dc7bbb34c8b958dc1a24d0e8897bd33/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/penguin86/nextcloud-maps-client/bd8a0d706dc7bbb34c8b958dc1a24d0e8897bd33/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_person.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/penguin86/nextcloud-maps-client/bd8a0d706dc7bbb34c8b958dc1a24d0e8897bd33/app/src/main/res/mipmap-xxhdpi/ic_person.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/penguin86/nextcloud-maps-client/bd8a0d706dc7bbb34c8b958dc1a24d0e8897bd33/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/penguin86/nextcloud-maps-client/bd8a0d706dc7bbb34c8b958dc1a24d0e8897bd33/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_person.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/penguin86/nextcloud-maps-client/bd8a0d706dc7bbb34c8b958dc1a24d0e8897bd33/app/src/main/res/mipmap-xxxhdpi/ic_person.png
--------------------------------------------------------------------------------
/app/src/main/res/values-it/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
18 |
19 |
20 |
21 | Maps Geofavorites
22 | Benvenuto su Nextcloud Maps Geofavorites
23 |
24 |
25 | Scegli account
26 |
27 |
28 | Nuovo geosegnalibro
29 | Informazioni
30 | Cambia account
31 | Lista
32 | Cerca per nome
33 | Condividi via
34 | {title}: {lat}°N, {lng}°E https://www.openstreetmap.org/#map=17/{lat}/{lng}
35 | Posizione condivisa:
36 | Condividi
37 | Elimina
38 | Elimina geosegnalibro
39 | Stai per eliminare il geosegnalibro {name}. Procedere?
40 | Elimina
41 | Mantieni
42 | Cambia account
43 | Vuoi cambiare account?
44 | Geosegnalibro eliminato
45 | Impossibile ottenere la lista dei geosegnalibri
46 | Il filtro per categoria non è disponibile al momento
47 | Filtra per categoria
48 | Mostra tutti
49 |
50 |
51 | Ordina per
52 | A - Z
53 | Più recenti
54 | Categoria
55 | Distanza
56 |
57 |
58 | Nome
59 | Descrizione
60 | Creato
61 | Modificato
62 | Categoria
63 | Coordinate
64 | Accuratezza: {accuracy} m
65 | Nessun segnale GPS!
66 | Per creare un geosegnalibro è necessario consentire l\'accesso alla posizione.
67 | Scrivi il nome per creare una nuova categoria
68 | Impossibile salvare il geosegnalibro
69 | Impossibile ottenere le coordinate dai dati ricevuti
70 | Geosegnalibro salvato
71 | Geosegnalibro incompleto: nome e categoria sono obbligatori
72 | Coordinate copiate nella clipboard
73 |
74 |
75 | Le coordinate dovrebbero essere nel formato xx.xxxxxx
76 | Coordinate non valide
77 | °N
78 | °E
79 |
80 |
81 | Versione
82 | Stai usando la versione <strong>%1$s</strong>
83 | Codice sorgente
84 | Questo progetto è disponibile su GitHub: <a href="%1$s">%1$s</a>
85 | Segnalazioni
86 | Puoi segnalare bugs, proporre migliorie o richiedere nuove funzionalità sul GitHub issue tracker: <a href="%1$s">%1$s</a>
87 | Mappe
88 | Questa app usa i server e le tiles di OpenStreetMap. Non accetto donazioni per questa app, ma raccomando piuttosto di donare a <a href="%1$s">OpenStreetMap</a>, poiché questa applicazione non potrebbe esistere senza di loro.
89 | Licenza
90 | Questa applicazione è rilasciata sotto licenza GNU GENERAL PUBLIC LICENSE v3+.
91 | Mostra licenza
92 |
93 |
94 | Si
95 | Annulla
96 |
97 |
98 | https://github.com/penguin86/nextcloud-maps-client
99 | https://github.com/penguin86/nextcloud-maps-client/issues
100 | https://raw.githubusercontent.com/penguin86/nextcloud-maps-client/master/LICENSE
101 | https://donate.openstreetmap.org
102 |
103 |
104 | Crea dalla posizione corrente
105 | Crea dalla mappa
106 |
107 |
108 | Aggiungi
109 | Crea dalla posizione corrente
110 | Crea dalla mappa
111 |
112 |
113 |
--------------------------------------------------------------------------------
/app/src/main/res/values-night/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #eee
4 | #888
5 | #000
6 | #C000
7 |
8 |
9 | #211e28
10 |
--------------------------------------------------------------------------------
/app/src/main/res/values-v23/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
18 |
19 |
20 |
21 |
25 |
26 |
--------------------------------------------------------------------------------
/app/src/main/res/values-v27/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
18 |
19 |
20 |
21 |
27 |
28 |
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
18 |
19 |
20 |
21 | #ffffff
22 | #00000000
23 | #AEFFFFFF
24 | #0082C9
25 | #550082C9
26 | #666
27 | @color/defaultBackground
28 | #fff
29 | #ccc
30 |
31 |
32 | #333
33 | @color/disabled
34 |
35 |
36 | @color/defaultBrand
37 | @color/disabled
38 |
39 |
40 | #fff
41 |
42 |
43 | @color/defaultBackground
44 |
--------------------------------------------------------------------------------
/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
18 |
19 |
20 |
21 |
22 | 4dp
23 | 8dp
24 | 16dp
25 |
26 |
27 | 100dp
28 | 42dp
29 |
30 |
31 | 0dp
32 | 16dp
33 | 8dp
34 | 16dp
35 | 8dp
36 | 16sp
37 | 12sp
38 |
39 |
40 | 75dp
41 |
42 |
43 | 36dp
44 |
45 |
46 |
--------------------------------------------------------------------------------
/app/src/main/res/values/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #0082C9
4 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
17 |
18 |
19 |
20 | Maps Geofavorites
21 | Welcome to Nextcloud Maps Geofavorites
22 |
23 |
24 | Choose account
25 |
26 |
27 | New geofavorite
28 | About
29 | Switch account
30 | List
31 | Search by name
32 | Share via
33 | {title}: {lat}°N, {lng}°E https://www.openstreetmap.org/#map=17/{lat}/{lng}
34 | Check out this place:
35 | Share
36 | Delete
37 | Delete geofavorite
38 | You are about to delete geofavorite {name}. Proceed?
39 | Delete
40 | Maintain
41 | Switch account
42 | Do you want to switch account?
43 | Geofavorite deleted
44 | Unable to obtain geofavorites list
45 | Category filtering is unavailable at the moment
46 | Filter by category
47 | Show all
48 |
49 |
50 | Sort by
51 | A - Z
52 | Newest first
53 | Category
54 | Distance
55 |
56 |
57 | Name
58 | Description
59 | Created
60 | Modified
61 | Category
62 | Coordinates
63 | Accuracy: {accuracy} m
64 | No GPS signal!
65 | Location permission is required to create a geofavorite.
66 | Write the name to create a new category
67 | Unable to save geofavorite
68 | Unable to obtain coordinates from shared data
69 | Geofavorite saved
70 | Incomplete geofavorite: Name and category are mandatory
71 | Coordinates have been copied to the clipboard
72 |
73 |
74 | Coordinates should be in format xx.xxxxxx
75 | Invalid coordinates
76 | °N
77 | °E
78 |
79 |
80 | Version
81 | You are currently using <strong>%1$s</strong>
82 | Source code
83 | This project is hosted on GitHub: <a href="%1$s">%1$s</a>
84 | Issues
85 | You can report bugs, enhancement proposals and feature requests at the GitHub issue tracker: <a href="%1$s">%1$s</a>
86 | Maps
87 | This app uses Open Street Maps tiles and servers to display the map. I do not accept any donation for this app, but strongly encourage to make any donation to <a href="%1$s">OpenStreetMap</a>, as this application could not exist without them.
88 | App license
89 | This application is licensed under the GNU GENERAL PUBLIC LICENSE v3+.
90 | View license
91 |
92 |
93 | Yes
94 | Cancel
95 |
96 |
97 | https://github.com/penguin86/nextcloud-maps-client
98 | https://github.com/penguin86/nextcloud-maps-client/issues
99 | https://raw.githubusercontent.com/penguin86/nextcloud-maps-client/master/LICENSE
100 | https://donate.openstreetmap.org
101 |
102 |
103 | New from current position
104 | New from map
105 |
106 |
107 | Add geofavorite
108 | Add geofavorite at current GPS position
109 | Add geofavorite from map
110 | Open menu
111 |
112 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
17 |
18 |
19 |
20 |
32 |
33 |
34 |
35 |
41 |
42 |
43 |
44 |
48 |
49 |
52 |
53 |
56 |
57 |
58 |
62 |
63 |
66 |
67 |
70 |
71 |
--------------------------------------------------------------------------------
/app/src/main/web_hi_res_512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/penguin86/nextcloud-maps-client/bd8a0d706dc7bbb34c8b958dc1a24d0e8897bd33/app/src/main/web_hi_res_512.png
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | /*
2 | * Nextcloud Maps Geofavorites for Android
3 | *
4 | * @copyright Copyright (c) 2020 John Doe
5 | * @author John Doe
6 | *
7 | * This program is free software: you can redistribute it and/or modify
8 | * it under the terms of the GNU General Public License as published by
9 | * the Free Software Foundation, either version 3 of the License, or
10 | * (at your option) any later version.
11 | *
12 | * This program is distributed in the hope that it will be useful,
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | * GNU General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU General Public License
18 | * along with this program. If not, see .
19 | */
20 |
21 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
22 | buildscript {
23 | repositories {
24 | google()
25 | jcenter()
26 | }
27 | dependencies {
28 | classpath 'com.android.tools.build:gradle:8.2.2'
29 |
30 | // NOTE: Do not place your application dependencies here; they belong
31 | // in the individual module build.gradle files
32 | }
33 | }
34 |
35 | allprojects {
36 | repositories {
37 | google()
38 | jcenter()
39 | }
40 | }
41 |
42 | task clean(type: Delete) {
43 | delete rootProject.buildDir
44 | }
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/1.txt:
--------------------------------------------------------------------------------
1 | First alpha release: working geobookmarks list, open geobookmarks in other apps via geo link, add geofavorite on current location.
2 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/2.txt:
--------------------------------------------------------------------------------
1 | Added geofavorite detail and deletion
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/3.txt:
--------------------------------------------------------------------------------
1 | Added map in geofavorite detail
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/4.txt:
--------------------------------------------------------------------------------
1 | First categories implementation
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/5.txt:
--------------------------------------------------------------------------------
1 | Fixed bug when opening newly-created element
2 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/6.txt:
--------------------------------------------------------------------------------
1 | Add geofavorite from map or coordinates
2 | Night mode (dark theme)
3 | New, less ambiguous, category icons (the old circle with letter inside is conventionally associated with user accounts)
4 | Graphic fixes
5 | Italian translation
6 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/7.txt:
--------------------------------------------------------------------------------
1 | Fix crash when using corrupted dataset with null category (It may happen on imports from Google Maps)
2 | Reimplemented API Provider to try to fix NullPointerException on mApi reported in Play Store
3 | Open Google Maps on Google devices
4 | Support share from: google maps urls, OpenStreetMap urls (only if containing coordinates)
5 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/9.txt:
--------------------------------------------------------------------------------
1 | Map view
2 | Filter by category
3 | Button to copy coordinates to clipboard
4 | Faster autocomplete
5 | Graphics restyling to match new Nextcloud style
6 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/full_description.txt:
--------------------------------------------------------------------------------
1 | UNOFFICIAL and FOSS Nextcloud Maps client. Shows your Nextcloud Maps geofavorites in a list or a map.
2 | Geofavorites can be opened in all apps supporting geo links (i.e. Google Maps, Organic Maps etc...).
3 | A new geofavorite can be created on current location, by sharing a "geo:" uri from another app or manually picking from the map.
4 |
5 | Requires Maps app to be installed on the Nextcloud instance.
6 | As per Nextcloud's guidelines, the login is implemented using Nextcloud's Single Sign On module and thus requires Nextcloud app installed.
7 |
8 | Promo banner by Gasteaud, Public domain, via Wikimedia Commons.
9 |
10 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/images/featureGraphic.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/penguin86/nextcloud-maps-client/bd8a0d706dc7bbb34c8b958dc1a24d0e8897bd33/fastlane/metadata/android/en-US/images/featureGraphic.png
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/images/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/penguin86/nextcloud-maps-client/bd8a0d706dc7bbb34c8b958dc1a24d0e8897bd33/fastlane/metadata/android/en-US/images/icon.png
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/images/phoneScreenshots/1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/penguin86/nextcloud-maps-client/bd8a0d706dc7bbb34c8b958dc1a24d0e8897bd33/fastlane/metadata/android/en-US/images/phoneScreenshots/1.png
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/images/phoneScreenshots/2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/penguin86/nextcloud-maps-client/bd8a0d706dc7bbb34c8b958dc1a24d0e8897bd33/fastlane/metadata/android/en-US/images/phoneScreenshots/2.png
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/images/phoneScreenshots/3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/penguin86/nextcloud-maps-client/bd8a0d706dc7bbb34c8b958dc1a24d0e8897bd33/fastlane/metadata/android/en-US/images/phoneScreenshots/3.png
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/images/promoGraphic.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/penguin86/nextcloud-maps-client/bd8a0d706dc7bbb34c8b958dc1a24d0e8897bd33/fastlane/metadata/android/en-US/images/promoGraphic.png
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/short_description.txt:
--------------------------------------------------------------------------------
1 | Manage Nextcloud Maps Geofavorites on your phone
2 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/title.txt:
--------------------------------------------------------------------------------
1 | Nextcloud Maps Geofavorites
2 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/it-IT/full_description.txt:
--------------------------------------------------------------------------------
1 | Client per Nextcloud Maps non ufficiale e FOSS al suo stato iniziale di sviluppo.
2 | Mostra i geosegnalibri di Nextcloud Maps in lista o in mappa e permette di aprirli in qualunque app supporti i "geo:" urls (i.e. Google Maps, Organic Maps etc...).
3 | È possibile creare nuovi geosegnalibri nella posizione GPS attuale, scegliendo la posizione dalla mappa o condividendola da altre app sotto forma di "geo:" uri.
4 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/it-IT/short_description.txt:
--------------------------------------------------------------------------------
1 | Un semplice client per Nextcloud Maps
2 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/it-IT/title.txt:
--------------------------------------------------------------------------------
1 | Nextcloud Maps Geofavorites
2 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | #
2 | # Nextcloud Maps Geofavorites for Android
3 | #
4 | # @copyright Copyright (c) 2020 John Doe
5 | # @author John Doe
6 | #
7 | # This program is free software: you can redistribute it and/or modify
8 | # it under the terms of the GNU General Public License as published by
9 | # the Free Software Foundation, either version 3 of the License, or
10 | # (at your option) any later version.
11 | #
12 | # This program is distributed in the hope that it will be useful,
13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | # GNU General Public License for more details.
16 | #
17 | # You should have received a copy of the GNU General Public License
18 | # along with this program. If not, see .
19 | #
20 |
21 | # Project-wide Gradle settings.
22 | # IDE (e.g. Android Studio) users:
23 | # Gradle settings configured through the IDE *will override*
24 | # any settings specified in this file.
25 | # For more details on how to configure your build environment visit
26 | # http://www.gradle.org/docs/current/userguide/build_environment.html
27 | # Specifies the JVM arguments used for the daemon process.
28 | # The setting is particularly useful for tweaking memory settings.
29 | org.gradle.jvmargs=-Xmx2048m
30 | # When configured, Gradle will run in incubating parallel mode.
31 | # This option should only be used with decoupled projects. More details, visit
32 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
33 | # org.gradle.parallel=true
34 | # AndroidX package structure to make it clearer which packages are bundled with the
35 | # Android operating system, and which are packaged with your app"s APK
36 | # https://developer.android.com/topic/libraries/support-library/androidx-rn
37 | android.useAndroidX=true
38 | # Automatically convert third-party libraries to use AndroidX
39 | android.enableJetifier=true
40 | android.defaults.buildfeatures.buildconfig=true
41 | android.nonTransitiveRClass=false
42 | android.nonFinalResIds=false
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/penguin86/nextcloud-maps-client/bd8a0d706dc7bbb34c8b958dc1a24d0e8897bd33/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Sun Feb 20 08:50:37 CET 2022
2 | distributionBase=GRADLE_USER_HOME
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.2-bin.zip
4 | distributionPath=wrapper/dists
5 | zipStorePath=wrapper/dists
6 | zipStoreBase=GRADLE_USER_HOME
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Attempt to set APP_HOME
10 | # Resolve links: $0 may be a link
11 | PRG="$0"
12 | # Need this for relative symlinks.
13 | while [ -h "$PRG" ] ; do
14 | ls=`ls -ld "$PRG"`
15 | link=`expr "$ls" : '.*-> \(.*\)$'`
16 | if expr "$link" : '/.*' > /dev/null; then
17 | PRG="$link"
18 | else
19 | PRG=`dirname "$PRG"`"/$link"
20 | fi
21 | done
22 | SAVED="`pwd`"
23 | cd "`dirname \"$PRG\"`/" >/dev/null
24 | APP_HOME="`pwd -P`"
25 | cd "$SAVED" >/dev/null
26 |
27 | APP_NAME="Gradle"
28 | APP_BASE_NAME=`basename "$0"`
29 |
30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
31 | DEFAULT_JVM_OPTS=""
32 |
33 | # Use the maximum available, or set MAX_FD != -1 to use that value.
34 | MAX_FD="maximum"
35 |
36 | warn () {
37 | echo "$*"
38 | }
39 |
40 | die () {
41 | echo
42 | echo "$*"
43 | echo
44 | exit 1
45 | }
46 |
47 | # OS specific support (must be 'true' or 'false').
48 | cygwin=false
49 | msys=false
50 | darwin=false
51 | nonstop=false
52 | case "`uname`" in
53 | CYGWIN* )
54 | cygwin=true
55 | ;;
56 | Darwin* )
57 | darwin=true
58 | ;;
59 | MINGW* )
60 | msys=true
61 | ;;
62 | NONSTOP* )
63 | nonstop=true
64 | ;;
65 | esac
66 |
67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
68 |
69 | # Determine the Java command to use to start the JVM.
70 | if [ -n "$JAVA_HOME" ] ; then
71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
72 | # IBM's JDK on AIX uses strange locations for the executables
73 | JAVACMD="$JAVA_HOME/jre/sh/java"
74 | else
75 | JAVACMD="$JAVA_HOME/bin/java"
76 | fi
77 | if [ ! -x "$JAVACMD" ] ; then
78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
79 |
80 | Please set the JAVA_HOME variable in your environment to match the
81 | location of your Java installation."
82 | fi
83 | else
84 | JAVACMD="java"
85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
86 |
87 | Please set the JAVA_HOME variable in your environment to match the
88 | location of your Java installation."
89 | fi
90 |
91 | # Increase the maximum file descriptors if we can.
92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
93 | MAX_FD_LIMIT=`ulimit -H -n`
94 | if [ $? -eq 0 ] ; then
95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
96 | MAX_FD="$MAX_FD_LIMIT"
97 | fi
98 | ulimit -n $MAX_FD
99 | if [ $? -ne 0 ] ; then
100 | warn "Could not set maximum file descriptor limit: $MAX_FD"
101 | fi
102 | else
103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
104 | fi
105 | fi
106 |
107 | # For Darwin, add options to specify how the application appears in the dock
108 | if $darwin; then
109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
110 | fi
111 |
112 | # For Cygwin, switch paths to Windows format before running java
113 | if $cygwin ; then
114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
116 | JAVACMD=`cygpath --unix "$JAVACMD"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Escape application args
158 | save () {
159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
160 | echo " "
161 | }
162 | APP_ARGS=$(save "$@")
163 |
164 | # Collect all arguments for the java command, following the shell quoting and substitution rules
165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
166 |
167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
169 | cd "$(dirname "$0")"
170 | fi
171 |
172 | exec "$JAVACMD" "$@"
173 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | set DIRNAME=%~dp0
12 | if "%DIRNAME%" == "" set DIRNAME=.
13 | set APP_BASE_NAME=%~n0
14 | set APP_HOME=%DIRNAME%
15 |
16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
17 | set DEFAULT_JVM_OPTS=
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windows variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 |
53 | :win9xME_args
54 | @rem Slurp the command line arguments.
55 | set CMD_LINE_ARGS=
56 | set _SKIP=2
57 |
58 | :win9xME_args_slurp
59 | if "x%~1" == "x" goto execute
60 |
61 | set CMD_LINE_ARGS=%*
62 |
63 | :execute
64 | @rem Setup the command line
65 |
66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
67 |
68 | @rem Execute Gradle
69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
70 |
71 | :end
72 | @rem End local scope for the variables with windows NT shell
73 | if "%ERRORLEVEL%"=="0" goto mainEnd
74 |
75 | :fail
76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
77 | rem the _cmd.exe /c_ return code!
78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
79 | exit /b 1
80 |
81 | :mainEnd
82 | if "%OS%"=="Windows_NT" endlocal
83 |
84 | :omega
85 |
--------------------------------------------------------------------------------
/screenshots/1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/penguin86/nextcloud-maps-client/bd8a0d706dc7bbb34c8b958dc1a24d0e8897bd33/screenshots/1.png
--------------------------------------------------------------------------------
/screenshots/2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/penguin86/nextcloud-maps-client/bd8a0d706dc7bbb34c8b958dc1a24d0e8897bd33/screenshots/2.png
--------------------------------------------------------------------------------
/screenshots/3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/penguin86/nextcloud-maps-client/bd8a0d706dc7bbb34c8b958dc1a24d0e8897bd33/screenshots/3.png
--------------------------------------------------------------------------------
/screenshots/full/1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/penguin86/nextcloud-maps-client/bd8a0d706dc7bbb34c8b958dc1a24d0e8897bd33/screenshots/full/1.png
--------------------------------------------------------------------------------
/screenshots/full/2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/penguin86/nextcloud-maps-client/bd8a0d706dc7bbb34c8b958dc1a24d0e8897bd33/screenshots/full/2.png
--------------------------------------------------------------------------------
/screenshots/full/3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/penguin86/nextcloud-maps-client/bd8a0d706dc7bbb34c8b958dc1a24d0e8897bd33/screenshots/full/3.png
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | /*
2 | * Nextcloud Maps Geofavorites for Android
3 | *
4 | * @copyright Copyright (c) 2020 John Doe
5 | * @author John Doe
6 | *
7 | * This program is free software: you can redistribute it and/or modify
8 | * it under the terms of the GNU General Public License as published by
9 | * the Free Software Foundation, either version 3 of the License, or
10 | * (at your option) any later version.
11 | *
12 | * This program is distributed in the hope that it will be useful,
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | * GNU General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU General Public License
18 | * along with this program. If not, see .
19 | */
20 |
21 | include ':app'
22 | rootProject.name = "Nextcloud Maps Geofavorites"
--------------------------------------------------------------------------------