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