9 Commits

53 changed files with 355 additions and 176 deletions

2
.gitignore vendored
View File

@ -101,3 +101,5 @@ app/release/output-metadata.json
.idea/deploymentTargetDropDown.xml
.idea/misc.xml
.idea/deploymentTargetSelector.xml
.idea/other.xml

View File

@ -8,7 +8,7 @@
(Always prefer [F-Droid](https://f-droid.org) build, when possible).
UNOFFICIAL and FOSS Nextcloud Maps client at its earliest stages of developement. Shows your Nextcloud Maps geofavorites list.
UNOFFICIAL and FOSS Nextcloud Maps client at its earliest stages of developement. Shows your Nextcloud Maps geofavorites in a list and a map.
Geofavorites can be opened in all apps supporting geo links (i.e. Google Maps, Organic Maps etc...).
A new geofavorite can be created on current location, by sharing a "geo:" uri from another app or manually picking from the map.
@ -16,5 +16,5 @@ A new geofavorite can be created on current location, by sharing a "geo:" uri fr
This work is heavily based on [matiasdelellis's Nextcloud SSO example](https://github.com/matiasdelellis/app-tutorial-android) to implement [Nextcloud single sign on](https://github.com/nextcloud/Android-SingleSignOn).
![Screenshot 1](screenshots/1.png) ![Screenshot 1](screenshots/2.png)
![Screenshot 1](screenshots/1.png) ![Screenshot 2](screenshots/2.png) ![Screenshot 3](screenshots/3.png)

View File

@ -18,14 +18,13 @@
apply plugin: 'com.android.application'
android {
compileSdkVersion 34
defaultConfig {
applicationId "it.danieleverducci.nextcloudmaps"
minSdkVersion 23
targetSdkVersion 34
versionCode 8
versionName "0.3.6"
targetSdkVersion 35
compileSdk 35
versionCode 9
versionName "0.4.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
@ -59,10 +58,10 @@ dependencies {
implementation fileTree(dir: "libs", include: ["*.jar"])
// Desugaring lib: see https://developer.android.com/studio/write/java8-support
coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.0.3")
coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.1.2")
implementation 'com.android.support:design:34.0.0'
implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'androidx.appcompat:appcompat:1.7.0'
implementation 'androidx.recyclerview:recyclerview:1.3.2'
implementation "androidx.cardview:cardview:1.0.0"
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
@ -70,11 +69,11 @@ dependencies {
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0'
// Retrofif2
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.squareup.retrofit2:retrofit:2.11.0'
implementation 'com.squareup.retrofit2:converter-gson:2.6.1'
// Nextcloud SSO
implementation "com.github.nextcloud:Android-SingleSignOn:1.0.0"
implementation "com.github.nextcloud:Android-SingleSignOn:1.3.2"
// OSMDroid
implementation 'org.osmdroid:osmdroid-android:6.1.18'
@ -83,7 +82,7 @@ dependencies {
implementation 'org.threeten:threetenbp:1.5.1'
// https://mvnrepository.com/artifact/commons-io/commons-io
implementation 'commons-io:commons-io:2.11.0'
implementation 'commons-io:commons-io:2.13.0'
// Picasso (image loader)
implementation 'com.squareup.picasso:picasso:2.8'

View File

@ -18,6 +18,8 @@
package it.danieleverducci.nextcloudmaps.activity.detail;
import android.Manifest;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
@ -52,6 +54,7 @@ import it.danieleverducci.nextcloudmaps.R;
import it.danieleverducci.nextcloudmaps.activity.NextcloudMapsStyledActivity;
import it.danieleverducci.nextcloudmaps.databinding.ActivityGeofavoriteDetailBinding;
import it.danieleverducci.nextcloudmaps.model.Geofavorite;
import it.danieleverducci.nextcloudmaps.utils.EdgeToEdgeUtils;
import it.danieleverducci.nextcloudmaps.utils.GeoUriParser;
import it.danieleverducci.nextcloudmaps.utils.IntentGenerator;
import it.danieleverducci.nextcloudmaps.utils.MapUtils;
@ -74,17 +77,13 @@ public class GeofavoriteDetailActivity extends NextcloudMapsStyledActivity imple
mViewHolder = new ViewHolder(getLayoutInflater());
setContentView(mViewHolder.getRootView());
EdgeToEdgeUtils.clearTopBarWithPadding(mViewHolder.binding.appbar);
mViewHolder.setOnSubmitListener(new OnSubmitListener() {
@Override
public void onBackPressed() {
finish();
}
@Override
public void onMapEditPressed() {
//TODO
}
@Override
public void onActionIconShareClicked() {
startActivity(Intent.createChooser(IntentGenerator.newShareIntent(GeofavoriteDetailActivity.this, mGeofavorite), getString(R.string.share_via)));
@ -310,6 +309,12 @@ public class GeofavoriteDetailActivity extends NextcloudMapsStyledActivity imple
CategoriesAdapter categoriesAdapter = new CategoriesAdapter(binding.root.getContext());
this.binding.categoryAt.setAdapter(categoriesAdapter);
this.binding.categoryAt.setText(Geofavorite.DEFAULT_CATEGORY);
this.binding.categoryAtClear.setOnClickListener((v) -> {
if (this.binding.categoryAt.getText().toString().isEmpty())
this.binding.categoryAt.setText(Geofavorite.DEFAULT_CATEGORY);
else
this.binding.categoryAt.setText("");
});
// Set map properties
this.binding.map.getZoomController().setVisibility(CustomZoomButtonsController.Visibility.NEVER);
@ -340,6 +345,12 @@ public class GeofavoriteDetailActivity extends NextcloudMapsStyledActivity imple
public void updateViewCoords(Geofavorite item) {
binding.coordsTv.setText(item.getCoordinatesString());
binding.coordsTv.setOnClickListener((v) -> {
ClipboardManager clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
ClipData clip = ClipData.newPlainText(item.getCoordinatesString(), item.getCoordinatesString());
clipboard.setPrimaryClip(clip);
Toast.makeText(GeofavoriteDetailActivity.this, R.string.coords_copied, Toast.LENGTH_SHORT).show();
});
// Center map
GeoPoint position = new GeoPoint(item.getLat(), item.getLng());
@ -407,9 +418,6 @@ public class GeofavoriteDetailActivity extends NextcloudMapsStyledActivity imple
if (v.getId() == R.id.back_bt && this.listener != null) {
this.listener.onBackPressed();
}
if (v.getId() == R.id.manual_pos_bt && this.listener != null) {
this.listener.onMapEditPressed();
}
// Actions
if (v.getId() == R.id.action_icon_share && this.listener != null) {
@ -428,7 +436,6 @@ public class GeofavoriteDetailActivity extends NextcloudMapsStyledActivity imple
void onSubmit();
void onMapClicked();
void onBackPressed();
void onMapEditPressed();
void onActionIconShareClicked();
void onActionIconNavClicked();
void onActionIconDeleteClicked();

View File

@ -61,6 +61,9 @@ public class GeofavoriteAdapter extends RecyclerView.Adapter<GeofavoriteAdapter.
private List<Geofavorite> items = new ArrayList<>();
private int sortRule = SORT_BY_CREATED;
private int bottomInset = 0;
private int leftInset = 0;
private int rightInset = 0;
// Contains the position of the element containing the overflow menu clicked
private int overflowMenuSelectedPosition = -1;
@ -110,6 +113,14 @@ public class GeofavoriteAdapter extends RecyclerView.Adapter<GeofavoriteAdapter.
holder.tv_title.setText(Html.fromHtml(geofavorite.getName() == null ? "" : geofavorite.getName()));
holder.tv_content.setText(geofavorite.getComment() == null ? "" : geofavorite.getComment());
holder.tv_date.setText(geofavorite.getLocalDateCreated().format(dateFormatter));
// Last item: Clear bottom system bar
holder.root_view.setPadding(
leftInset,
holder.root_view.getPaddingTop(),
rightInset,
position == getItemCount() - 1 ? bottomInset : 0
);
}
@Override
@ -117,7 +128,20 @@ public class GeofavoriteAdapter extends RecyclerView.Adapter<GeofavoriteAdapter.
return items.size();
}
public void setBottomInset(int inset) {
this.bottomInset = inset;
}
public void setLeftInset(int inset) {
this.leftInset = inset;
}
public void setRightInset(int inset) {
this.rightInset = inset;
}
class GeofavoriteViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
View root_view;
TextView tv_category, tv_title, tv_content, tv_date;
ImageView bt_context_menu;
ImageView bt_nav;
@ -128,6 +152,7 @@ public class GeofavoriteAdapter extends RecyclerView.Adapter<GeofavoriteAdapter.
GeofavoriteViewHolder(@NonNull View itemView, ItemClickListener itemClickListener) {
super(itemView);
root_view = itemView;
tv_category = itemView.findViewById(R.id.tv_category);
tv_title = itemView.findViewById(R.id.title);
tv_content = itemView.findViewById(R.id.content);

View File

@ -25,7 +25,10 @@ import android.view.View;
import androidx.annotation.NonNull;
import androidx.core.app.ActivityCompat;
import androidx.core.graphics.Insets;
import androidx.core.view.GravityCompat;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;
import androidx.drawerlayout.widget.DrawerLayout;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
@ -48,6 +51,7 @@ import it.danieleverducci.nextcloudmaps.api.ApiProvider;
import it.danieleverducci.nextcloudmaps.fragments.GeofavoriteListFragment;
import it.danieleverducci.nextcloudmaps.fragments.GeofavoriteMapFragment;
import it.danieleverducci.nextcloudmaps.repository.GeofavoriteRepository;
import it.danieleverducci.nextcloudmaps.utils.EdgeToEdgeUtils;
import it.danieleverducci.nextcloudmaps.utils.SettingsManager;
public class MainActivity extends NextcloudMapsStyledActivity {
@ -123,15 +127,7 @@ public class MainActivity extends NextcloudMapsStyledActivity {
else
showList();
FloatingActionButton fab = findViewById(R.id.open_fab);
fab.setOnClickListener(view -> openFab(!this.isFabOpen));
fab = findViewById(R.id.add_from_gps);
fab.setOnClickListener(view -> addGeofavoriteFromGps());
fab = findViewById(R.id.add_from_map);
fab.setOnClickListener(view -> addGeofavoriteFromMap());
setupFAB();
setupNavigationMenu();
drawerLayout = findViewById(R.id.drawerLayout);
@ -150,7 +146,32 @@ public class MainActivity extends NextcloudMapsStyledActivity {
transaction.commit();
}
private void setupFAB() {
// Register listeners
FloatingActionButton fab = findViewById(R.id.open_fab);
fab.setOnClickListener(view -> openFab(!this.isFabOpen));
fab = findViewById(R.id.add_from_gps);
fab.setOnClickListener(view -> addGeofavoriteFromGps());
fab = findViewById(R.id.add_from_map);
fab.setOnClickListener(view -> addGeofavoriteFromMap());
// Clear system bars (in edge to edge mode)
EdgeToEdgeUtils.clearBottomBarWithMargin(findViewById(R.id.fab_container));
}
private void setupNavigationMenu() {
//EdgeToEdgeUtils.clearTopBarWithPadding(findViewById(R.id.header_view));
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.drawerLayout), (v, windowInsets) -> {
Insets insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars());
View hv = findViewById(R.id.header_view);
hv.setPadding(insets.left, insets.top, insets.right, hv.getPaddingBottom());
//return WindowInsetsCompat.CONSUMED;
return windowInsets;
});
ArrayList<NavigationItem> navItems = new ArrayList<>();
navigationCommonAdapter = new NavigationAdapter(this, item -> {

View File

@ -13,6 +13,9 @@ import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.AppCompatImageView;
import androidx.core.graphics.Insets;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;
import androidx.fragment.app.FragmentTransaction;
import androidx.lifecycle.Observer;
import androidx.recyclerview.widget.LinearLayoutManager;
@ -27,6 +30,7 @@ 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.EdgeToEdgeUtils;
import it.danieleverducci.nextcloudmaps.utils.GeofavoritesFilter;
import it.danieleverducci.nextcloudmaps.utils.SettingsManager;
@ -97,6 +101,17 @@ public class GeofavoriteListFragment extends GeofavoritesFragment implements Sor
View showMapButton = v.findViewById(R.id.view_mode_map);
showMapButton.setOnClickListener(View -> ((MainActivity)requireActivity()).showMap());
// Clear top bar in edge to edge and notify the adapter about the system bar size to avoid the system bar covering the last row
ViewCompat.setOnApplyWindowInsetsListener(v.findViewById(R.id.activity_list_view), (rv, windowInsets) -> {
Insets insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars());
rv.setPadding(rv.getPaddingLeft(), insets.top, rv.getPaddingRight(), rv.getPaddingBottom());
geofavoriteAdapter.setBottomInset(insets.bottom);
geofavoriteAdapter.setLeftInset(insets.left);
geofavoriteAdapter.setRightInset(insets.right);
//return WindowInsetsCompat.CONSUMED;
return windowInsets;
});
return v;
}

View File

@ -3,10 +3,11 @@ package it.danieleverducci.nextcloudmaps.fragments;
import android.Manifest;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@ -31,13 +32,12 @@ 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.EdgeToEdgeUtils;
import it.danieleverducci.nextcloudmaps.utils.GeoUriParser;
import it.danieleverducci.nextcloudmaps.utils.MapUtils;
import it.danieleverducci.nextcloudmaps.utils.SettingsManager;
@ -61,7 +61,11 @@ public class GeofavoriteMapFragment extends GeofavoritesFragment implements Main
View v = inflater.inflate(R.layout.fragment_geofavorite_map, container, false);
// Register listeners
v.findViewById(R.id.center_position).setOnClickListener((cpv) -> moveToUserPosition());
View centerPositionFab = v.findViewById(R.id.center_position);
centerPositionFab.setOnClickListener((cpv) -> moveToUserPosition());
// Clear bottom bar in edge to edge
EdgeToEdgeUtils.clearBottomBarWithMargin(v.findViewById(R.id.center_position_container));
// Setup map
map = v.findViewById(R.id.map);
@ -161,6 +165,11 @@ public class GeofavoriteMapFragment extends GeofavoritesFragment implements Main
// Display user position on screen
mLocationOverlay = new MyLocationNewOverlay(new GpsMyLocationProvider(requireContext()), map);
Bitmap personIcon = ((BitmapDrawable)AppCompatResources.getDrawable(requireContext(), R.mipmap.ic_person)).getBitmap();
mLocationOverlay.setPersonIcon(personIcon);
mLocationOverlay.setDirectionIcon(personIcon);
mLocationOverlay.setPersonAnchor(.5f, .5f);
mLocationOverlay.setDirectionAnchor(.5f, .5f);
// On first gps fix, show "center to my position" icon
mLocationOverlay.runOnFirstFix(() -> {
if(getActivity() != null) {

View File

@ -38,6 +38,7 @@ import it.danieleverducci.nextcloudmaps.activity.detail.GeofavoriteDetailActivit
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.EdgeToEdgeUtils;
import it.danieleverducci.nextcloudmaps.utils.GeofavoritesFilter;
import it.danieleverducci.nextcloudmaps.utils.IntentGenerator;
@ -86,6 +87,8 @@ public abstract class GeofavoritesFragment extends Fragment {
userBadgeContainer.setOnClickListener(v -> showSwitchAccountDialog());
// Setup toolbar/searchbar
View toolbarContainer = view.findViewById(R.id.toolbar_container);
EdgeToEdgeUtils.clearTopBarWithMargin(toolbarContainer);
toolbar = view.findViewById(R.id.toolbar);
homeToolbar = view.findViewById(R.id.home_toolbar);
filterButton = view.findViewById(R.id.search_filter);

View File

@ -0,0 +1,62 @@
package it.danieleverducci.nextcloudmaps.utils;
import android.view.View;
import android.view.ViewGroup;
import androidx.core.graphics.Insets;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;
public class EdgeToEdgeUtils {
/**
* Clears the system bars in edge to edge mode (https://developer.android.com/develop/ui/views/layout/edge-to-edge)
* @param viewToClear the view to clear from system bars
*/
public static void clearBottomBarWithMargin(View viewToClear) {
ViewCompat.setOnApplyWindowInsetsListener(viewToClear, (v, windowInsets) -> {
Insets insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars());
ViewGroup.MarginLayoutParams mlp = (ViewGroup.MarginLayoutParams) v.getLayoutParams();
mlp.bottomMargin = insets.bottom;
mlp.leftMargin = insets.left;
mlp.rightMargin = insets.right;
v.setLayoutParams(mlp);
//return WindowInsetsCompat.CONSUMED;
return windowInsets;
});
}
/**
* Clears the system bars in edge to edge mode (https://developer.android.com/develop/ui/views/layout/edge-to-edge)
* @param viewToClear the view to clear from system bars
*/
public static void clearTopBarWithMargin(View viewToClear) {
ViewCompat.setOnApplyWindowInsetsListener(viewToClear, (v, windowInsets) -> {
Insets insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars());
ViewGroup.MarginLayoutParams mlp = (ViewGroup.MarginLayoutParams) v.getLayoutParams();
mlp.topMargin = insets.top;
mlp.leftMargin = insets.left;
mlp.rightMargin = insets.right;
v.setLayoutParams(mlp);
//return WindowInsetsCompat.CONSUMED;
return windowInsets;
});
}
/**
* Clears the system bars in edge to edge mode (https://developer.android.com/develop/ui/views/layout/edge-to-edge)
* @param viewToClear the view to clear from system bars
*/
public static void clearTopBarWithPadding(View viewToClear) {
ViewCompat.setOnApplyWindowInsetsListener(viewToClear, (v, windowInsets) -> {
Insets insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars());
v.setPadding(insets.left, insets.top, insets.right, v.getPaddingBottom());
//return WindowInsetsCompat.CONSUMED;
return windowInsets;
});
}
}

View File

@ -1,10 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:left="8dp"
android:right="8dp"
android:top="8dp"
android:bottom="8dp">
<item>
<shape
android:shape="oval">
<solid android:color="@color/defaultBrandAlpha"/>

View File

@ -0,0 +1,5 @@
<vector android:height="24dp" android:tint="#000000"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M19,6.41L17.59,5 12,10.59 6.41,5 5,6.41 10.59,12 5,17.59 6.41,19 12,13.41 17.59,19 19,17.59 13.41,12z"/>
</vector>

View File

@ -0,0 +1,5 @@
<vector android:height="24dp" android:tint="#000000"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M16,1L4,1c-1.1,0 -2,0.9 -2,2v14h2L4,3h12L16,1zM19,5L8,5c-1.1,0 -2,0.9 -2,2v14c0,1.1 0.9,2 2,2h11c1.1,0 2,-0.9 2,-2L21,7c0,-1.1 -0.9,-2 -2,-2zM19,21L8,21L8,7h11v14z"/>
</vector>

View File

@ -1,16 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?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"/>
<path
android:fillColor="@android:color/white"
android:pathData="M11,11l2.12,0l6.16,-6.16l-2.12,-2.12l-6.16,6.16z"/>
<path
android:fillColor="@android:color/white"
android:pathData="M20.71,2L20,1.29C19.8,1.1 19.55,1 19.29,1c-0.13,0 -0.48,0.07 -0.71,0.29l-0.72,0.72l2.12,2.12l0.72,-0.72C21.1,3.02 21.1,2.39 20.71,2z"/>
</vector>

View File

@ -9,7 +9,7 @@
<solid android:color="@android:color/transparent" />
<stroke
android:width="10dp"
android:color="#fff" />
android:color="@color/toolbar_background" />
</shape>
</item>
</layer-list>

View File

@ -10,14 +10,12 @@
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/appbar"
android:layout_width="match_parent"
android:layout_height="250dp"
android:fitsSystemWindows="true">
android:layout_height="250dp">
<com.google.android.material.appbar.CollapsingToolbarLayout
android:id="@+id/collapsing_toolbar"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
app:contentScrim="@color/defaultBrand"
app:layout_scrollFlags="scroll|snap|exitUntilCollapsed"
app:title="@string/new_geobookmark"
@ -51,25 +49,26 @@
<!-- Back button -->
<ImageView
android:id="@+id/back_bt"
android:layout_width="?android:attr/actionBarSize"
android:layout_height="?android:attr/actionBarSize"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_gravity="start"
android:padding="16dp"
android:layout_margin="8dp"
android:padding="8dp"
android:src="@drawable/ic_back_grey"
app:tint="@color/white"
android:background="@drawable/floating_semitransparent_button_background"/>
<!-- Manual position button -->
<!-- Save button -->
<ImageView
android:id="@+id/manual_pos_bt"
android:layout_width="?android:attr/actionBarSize"
android:layout_height="?android:attr/actionBarSize"
android:id="@+id/submit_bt"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_gravity="end"
android:padding="16dp"
android:src="@drawable/ic_manual_pos"
android:layout_margin="8dp"
android:padding="8dp"
android:src="@drawable/ic_ok"
app:tint="@color/white"
android:background="@drawable/floating_semitransparent_button_background"
android:visibility="gone"/> <!-- TODO: Implement edit -->
android:background="@drawable/round_button_background"/>
</androidx.appcompat.widget.Toolbar>
@ -197,20 +196,40 @@
android:drawableTint="@color/defaultBrand"
android:hint="@string/description"/>
<AutoCompleteTextView
android:id="@+id/category_at"
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:ems="10"
android:gravity="start|top"
android:inputType="textMultiLine"
android:maxLines="10"
android:background="@android:color/transparent"
android:drawableLeft="@drawable/ic_category_asc"
android:drawablePadding="5dp"
android:drawableTint="@color/defaultBrand"
android:hint="@string/category"/>
android:orientation="horizontal"
android:layout_marginTop="20dp">
<AutoCompleteTextView
android:id="@+id/category_at"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:maxLines="1"
android:background="@android:color/transparent"
android:drawableLeft="@drawable/ic_category_asc"
android:drawablePadding="5dp"
android:drawableTint="@color/defaultBrand"
android:hint="@string/category"
android:completionThreshold="0"/>
<ImageButton
android:id="@+id/category_at_clear"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="3dp"
android:background="@color/transparent"
android:src="@drawable/ic_clear"/>
</LinearLayout>
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="@string/category_hint"
android:textSize="12sp"/>
<TextView
android:layout_width="match_parent"
@ -249,7 +268,9 @@
android:id="@+id/coords_tv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAlignment="textEnd" />
android:textAlignment="textEnd"
app:drawableEndCompat="@drawable/ic_copy"
android:drawablePadding="10sp"/>
<ProgressBar
android:id="@+id/progress"
@ -258,16 +279,6 @@
android:indeterminate="true"
android:visibility="gone"/>
<Button
android:id="@+id/submit_bt"
style="@style/Widget.AppCompat.Button.Colored"
android:layout_width="match_parent"
android:layout_height="60dp"
android:layout_margin="50dp"
android:text="@string/confirm"
app:backgroundTint="@color/defaultBrand"
android:onClick="onSubmit"/>
</LinearLayout>
</androidx.core.widget.NestedScrollView>

View File

@ -30,43 +30,51 @@
tools:layout="@layout/fragment_geofavorite_list" />
<!-- Add from map FAB -->
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/add_from_map"
<FrameLayout
android:id="@+id/fab_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="24dp"
android:src="@drawable/ic_add_map"
app:backgroundTint="@color/defaultBrand"
app:fabSize="mini"
app:tint="@color/white"
tools:ignore="DuplicateClickableBoundsCheck"
android:contentDescription="@string/add_from_map" />
android:layout_height="match_parent"
android:layout_gravity="bottom|end">
<!-- Add from current position FAB -->
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/add_from_gps"
android:layout_margin="24dp"
android:layout_gravity="bottom|end"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:fabSize="mini"
android:src="@drawable/ic_add_gps"
app:backgroundTint="@color/defaultBrand"
app:tint="@color/white"
android:contentDescription="@string/add_from_gps"/>
<!-- Add from map FAB -->
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/add_from_map"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:layout_margin="24dp"
android:src="@drawable/ic_add_map"
app:backgroundTint="@color/defaultBrand"
app:fabSize="mini"
app:tint="@color/white"
tools:ignore="DuplicateClickableBoundsCheck"
android:contentDescription="@string/add_from_map" />
<!-- Main FAB -->
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/open_fab"
android:layout_margin="16dp"
android:layout_gravity="bottom|end"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_add"
app:backgroundTint="@color/defaultBrand"
app:tint="@color/white"
android:contentDescription="@string/open_fab"/>
<!-- Add from current position FAB -->
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/add_from_gps"
android:layout_margin="24dp"
android:layout_gravity="bottom|end"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:fabSize="mini"
android:src="@drawable/ic_add_gps"
app:backgroundTint="@color/defaultBrand"
app:tint="@color/white"
android:contentDescription="@string/add_from_gps"/>
<!-- Main FAB -->
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/open_fab"
android:layout_margin="16dp"
android:layout_gravity="bottom|end"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_add"
app:backgroundTint="@color/defaultBrand"
app:tint="@color/white"
android:contentDescription="@string/open_fab"/>
</FrameLayout>
</FrameLayout>

View File

@ -35,8 +35,7 @@
<com.google.android.material.navigation.NavigationView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:fitsSystemWindows="true">
android:layout_gravity="start">
<androidx.core.widget.NestedScrollView
android:id="@+id/scrollView"
@ -49,37 +48,43 @@
android:layout_height="wrap_content"
android:orientation="vertical">
<RelativeLayout
<FrameLayout
android:id="@+id/header_view"
android:layout_width="match_parent"
android:layout_height="@dimen/drawer_header_height"
android:layout_height="wrap_content"
android:background="@color/defaultBrand">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/logo"
android:layout_width="@dimen/drawer_header_logo_size"
android:layout_height="@dimen/drawer_header_logo_size"
android:layout_centerVertical="true"
android:layout_margin="@dimen/spacer_2x"
android:gravity="center"
android:src="@drawable/ic_app" />
<TextView
android:id="@+id/app_name"
android:layout_width="wrap_content"
<LinearLayout
android:layout_width="match_parent"
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"
android:textColor="@android:color/white"
android:textSize="24sp"
android:layout_toRightOf="@id/logo" />
</RelativeLayout>
android:gravity="center_vertical">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/logo"
android:layout_width="@dimen/drawer_header_logo_size"
android:layout_height="@dimen/drawer_header_logo_size"
android:layout_margin="@dimen/spacer_2x"
android:gravity="center"
android:src="@drawable/ic_app" />
<TextView
android:id="@+id/app_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:layout_marginBottom="20dp"
android:layout_marginRight="20dp"
android:ellipsize="end"
android:lines="2"
android:fontFamily="sans-serif-light"
android:gravity="center_vertical"
android:text="@string/app_name"
android:textColor="@android:color/white"
android:textSize="24sp"/>
</LinearLayout>
</FrameLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/navigationCommon"

View File

@ -3,6 +3,7 @@
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/toolbar_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp">
@ -35,6 +36,7 @@
android:layout_marginTop="@dimen/spacer_1hx"
android:layout_marginEnd="@dimen/spacer_2x"
android:layout_marginBottom="@dimen/spacer_1hx"
app:cardBackgroundColor="@color/toolbar_background"
app:cardCornerRadius="30dp"
app:cardElevation="2dp"
app:strokeWidth="0dp">

View File

@ -17,7 +17,6 @@
<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" >

View File

@ -53,18 +53,24 @@
</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"
<FrameLayout
android:id="@+id/center_position_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
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"/>
android:layout_gravity="bottom|right">
<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_marginBottom="25dp"
android:background="@drawable/unselected_floating_semitransparent_button_background"
android:padding="5dp"
android:tint="@color/text_color"
android:src="@drawable/ic_add_gps"
android:visibility="visible"/>
</FrameLayout>
</FrameLayout>

View File

@ -22,7 +22,7 @@
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="90dp"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:clickable="true"
android:focusable="true">
@ -32,6 +32,8 @@
android:layout_width="64dp"
android:layout_height="64dp"
android:layout_marginStart="4dp"
android:layout_marginTop="14dp"
android:layout_marginBottom="14dp"
android:layout_weight="0"
android:background="@drawable/ic_list_pin"
android:gravity="top|center"

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 962 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

@ -64,11 +64,12 @@
<string name="accuracy">Accuratezza: {accuracy} m</string>
<string name="accuracy_nosignal">Nessun segnale GPS!</string>
<string name="location_permission_required">Per creare un geosegnalibro è necessario consentire l\'accesso alla posizione.</string>
<string name="confirm">Salva</string>
<string name="category_hint">Scrivi il nome per creare una nuova categoria</string>
<string name="error_saving_geofavorite">Impossibile salvare il geosegnalibro</string>
<string name="error_unsupported_uri">Impossibile ottenere le coordinate dai dati ricevuti</string>
<string name="geofavorite_saved">Geosegnalibro salvato</string>
<string name="incomplete_geofavorite">Geosegnalibro incompleto: nome e categoria sono obbligatori</string>
<string name="coords_copied">Coordinate copiate nella clipboard</string>
<!-- Map picker activity -->
<string name="coordinates_parse_error">Le coordinate dovrebbero essere nel formato xx.xxxxxx</string>

View File

@ -4,4 +4,7 @@
<color name="disabled">#888</color>
<color name="defaultBackground">#000</color>
<color name="translucent">#C000</color>
<!-- Toolbar -->
<color name="toolbar_background">#211e28</color>
</resources>

View File

@ -38,4 +38,7 @@
<!-- Generic Colors -->
<color name="white">#fff</color>
<!-- Toolbar -->
<color name="toolbar_background">@color/defaultBackground</color>
</resources>

View File

@ -63,11 +63,12 @@
<string name="accuracy">Accuracy: {accuracy} m</string>
<string name="accuracy_nosignal">No GPS signal!</string>
<string name="location_permission_required">Location permission is required to create a geofavorite.</string>
<string name="confirm">Save</string>
<string name="category_hint">Write the name to create a new category</string>
<string name="error_saving_geofavorite">Unable to save geofavorite</string>
<string name="error_unsupported_uri">Unable to obtain coordinates from shared data</string>
<string name="geofavorite_saved">Geofavorite saved</string>
<string name="incomplete_geofavorite">Incomplete geofavorite: Name and category are mandatory</string>
<string name="coords_copied">Coordinates have been copied to the clipboard</string>
<!-- Map picker activity -->
<string name="coordinates_parse_error">Coordinates should be in format xx.xxxxxx</string>

View File

@ -25,7 +25,7 @@ buildscript {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:8.2.2'
classpath 'com.android.tools.build:gradle:8.5.1'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files

Binary file not shown.

Before

Width:  |  Height:  |  Size: 129 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 108 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 64 KiB

View File

@ -0,0 +1,5 @@
Map view
Filter by category
Button to copy coordinates to clipboard
Faster autocomplete
Graphics restyling to match new Nextcloud style

View File

@ -1,4 +1,4 @@
UNOFFICIAL and FOSS Nextcloud Maps client at its earliest stages of developement. Shows your Nextcloud Maps geofavorites list.
UNOFFICIAL and FOSS Nextcloud Maps client. Shows your Nextcloud Maps geofavorites in a list or a map.
Geofavorites can be opened in all apps supporting geo links (i.e. Google Maps, Organic Maps etc...).
A new geofavorite can be created on current location, by sharing a "geo:" uri from another app or manually picking from the map.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 118 KiB

After

Width:  |  Height:  |  Size: 154 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 105 KiB

After

Width:  |  Height:  |  Size: 2.8 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 114 KiB

After

Width:  |  Height:  |  Size: 229 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 108 KiB

View File

@ -1,3 +1,3 @@
Client per Nextcloud Maps non ufficiale e FOSS al suo stato iniziale di sviluppo.
Mostra la lista dei geosegnalibri di Nextcloud Maps e permette di aprirli in qualunque app supporti i "geo:" urls (i.e. Google Maps, Organic Maps etc...).
Mostra i geosegnalibri di Nextcloud Maps in lista o in mappa e permette di aprirli in qualunque app supporti i "geo:" urls (i.e. Google Maps, Organic Maps etc...).
È possibile creare nuovi geosegnalibri nella posizione GPS attuale, scegliendo la posizione dalla mappa o condividendola da altre app sotto forma di "geo:" uri.

View File

@ -1,6 +1,6 @@
#Sun Feb 20 08:50:37 CET 2022
distributionBase=GRADLE_USER_HOME
distributionUrl=https\://services.gradle.org/distributions/gradle-8.2-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
distributionPath=wrapper/dists
zipStorePath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

After

Width:  |  Height:  |  Size: 178 KiB

BIN
screenshots/3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 118 KiB

After

Width:  |  Height:  |  Size: 154 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 105 KiB

After

Width:  |  Height:  |  Size: 2.8 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 114 KiB

After

Width:  |  Height:  |  Size: 229 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 108 KiB