Separated list logic from application logic, support for multiple list fragments
This commit is contained in:
		@@ -3,7 +3,6 @@ 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.List;
 | 
			
		||||
@@ -11,7 +10,7 @@ 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) {
 | 
			
		||||
@@ -17,7 +17,6 @@
 | 
			
		||||
 | 
			
		||||
package it.danieleverducci.nextcloudmaps.activity.main;
 | 
			
		||||
 | 
			
		||||
import android.content.DialogInterface;
 | 
			
		||||
import android.content.Intent;
 | 
			
		||||
import android.content.SharedPreferences;
 | 
			
		||||
import android.os.Bundle;
 | 
			
		||||
@@ -27,20 +26,18 @@ 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.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 com.google.android.material.card.MaterialCardView;
 | 
			
		||||
import com.google.android.material.floatingactionbutton.FloatingActionButton;
 | 
			
		||||
@@ -58,9 +55,9 @@ import it.danieleverducci.nextcloudmaps.activity.main.NavigationAdapter.Navigati
 | 
			
		||||
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.fragments.GeofavoriteListFragment;
 | 
			
		||||
import it.danieleverducci.nextcloudmaps.fragments.GeofavoritesFragment;
 | 
			
		||||
import it.danieleverducci.nextcloudmaps.model.Geofavorite;
 | 
			
		||||
import it.danieleverducci.nextcloudmaps.utils.GeoUriParser;
 | 
			
		||||
import it.danieleverducci.nextcloudmaps.utils.IntentGenerator;
 | 
			
		||||
import it.danieleverducci.nextcloudmaps.utils.SettingsManager;
 | 
			
		||||
 | 
			
		||||
import static android.view.View.GONE;
 | 
			
		||||
@@ -71,7 +68,7 @@ import static it.danieleverducci.nextcloudmaps.activity.main.GeofavoriteAdapter.
 | 
			
		||||
import androidx.lifecycle.Observer;
 | 
			
		||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
 | 
			
		||||
 | 
			
		||||
public class MainActivity extends NextcloudMapsStyledActivity implements OnSortingOrderListener {
 | 
			
		||||
public class MainActivity extends NextcloudMapsStyledActivity {
 | 
			
		||||
 | 
			
		||||
    private static final String TAG = "MainActivity";
 | 
			
		||||
 | 
			
		||||
@@ -80,21 +77,12 @@ public class MainActivity extends NextcloudMapsStyledActivity implements OnSorti
 | 
			
		||||
    private static final String NAVIGATION_KEY_SHOW_ABOUT = "about";
 | 
			
		||||
    private static final String NAVIGATION_KEY_SWITCH_ACCOUNT = "switch_account";
 | 
			
		||||
 | 
			
		||||
    private SharedPreferences preferences;
 | 
			
		||||
 | 
			
		||||
    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;
 | 
			
		||||
@@ -105,75 +93,16 @@ public class MainActivity extends NextcloudMapsStyledActivity implements OnSorti
 | 
			
		||||
        super.onCreate(savedInstanceState);
 | 
			
		||||
        setContentView(R.layout.activity_main);
 | 
			
		||||
 | 
			
		||||
        preferences = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        int sortRule = SettingsManager.getGeofavoriteListSortBy(this);
 | 
			
		||||
        boolean gridViewEnabled = SettingsManager.isGeofavoriteListShownAsGrid(this);
 | 
			
		||||
 | 
			
		||||
        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());
 | 
			
		||||
        boolean showMap = SettingsManager.isGeofavoriteListShownAsMap(this);
 | 
			
		||||
        if (showMap) {
 | 
			
		||||
            // TODO: Map fragment
 | 
			
		||||
        } else {
 | 
			
		||||
            Fragment fragment = new GeofavoriteListFragment();
 | 
			
		||||
            FragmentManager manager = getSupportFragmentManager();
 | 
			
		||||
            FragmentTransaction transaction = manager.beginTransaction();
 | 
			
		||||
            transaction.replace(R.id.fragment_container, fragment);
 | 
			
		||||
            transaction.commit();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        fab = findViewById(R.id.open_fab);
 | 
			
		||||
        fab.setOnClickListener(view -> openFab(!this.isFabOpen));
 | 
			
		||||
@@ -196,7 +125,12 @@ public class MainActivity extends NextcloudMapsStyledActivity implements OnSorti
 | 
			
		||||
 | 
			
		||||
            @Override
 | 
			
		||||
            public boolean onQueryTextChange(String query) {
 | 
			
		||||
                geofavoriteAdapter.getFilter().filter(query);
 | 
			
		||||
                GeofavoritesFragment gff = (GeofavoritesFragment) getSupportFragmentManager().findFragmentById(R.id.fragment_container);
 | 
			
		||||
                if (gff == null) {
 | 
			
		||||
                    Log.e(TAG, "onQueryTextChange: No fragment active!");
 | 
			
		||||
                    return false;
 | 
			
		||||
                }
 | 
			
		||||
                gff.onSearch(query);
 | 
			
		||||
                return false;
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
@@ -214,21 +148,9 @@ public class MainActivity extends NextcloudMapsStyledActivity implements OnSorti
 | 
			
		||||
 | 
			
		||||
        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
 | 
			
		||||
@@ -276,13 +198,6 @@ public class MainActivity extends NextcloudMapsStyledActivity implements OnSorti
 | 
			
		||||
        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)
 | 
			
		||||
@@ -307,69 +222,6 @@ public class MainActivity extends NextcloudMapsStyledActivity implements OnSorti
 | 
			
		||||
        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);
 | 
			
		||||
 
 | 
			
		||||
@@ -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,160 @@
 | 
			
		||||
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 android.widget.Toast;
 | 
			
		||||
 | 
			
		||||
import androidx.annotation.NonNull;
 | 
			
		||||
import androidx.annotation.Nullable;
 | 
			
		||||
import androidx.appcompat.widget.AppCompatImageView;
 | 
			
		||||
import androidx.fragment.app.Fragment;
 | 
			
		||||
import androidx.fragment.app.FragmentManager;
 | 
			
		||||
import androidx.fragment.app.FragmentTransaction;
 | 
			
		||||
import androidx.lifecycle.Observer;
 | 
			
		||||
import androidx.recyclerview.widget.LinearLayoutManager;
 | 
			
		||||
import androidx.recyclerview.widget.RecyclerView;
 | 
			
		||||
import androidx.recyclerview.widget.StaggeredGridLayoutManager;
 | 
			
		||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
 | 
			
		||||
 | 
			
		||||
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.SettingsManager;
 | 
			
		||||
 | 
			
		||||
public class GeofavoriteListFragment extends GeofavoritesFragment implements SortingOrderDialogFragment.OnSortingOrderListener {
 | 
			
		||||
 | 
			
		||||
    private SwipeRefreshLayout swipeRefresh;
 | 
			
		||||
    private RecyclerView recyclerView;
 | 
			
		||||
    private LinearLayoutManager layoutManager;
 | 
			
		||||
    private GeofavoriteAdapter geofavoriteAdapter;
 | 
			
		||||
    private GeofavoriteAdapter.ItemClickListener rvItemClickListener;
 | 
			
		||||
 | 
			
		||||
    @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 = v.findViewById(R.id.recycler_view);
 | 
			
		||||
        layoutManager = new LinearLayoutManager(requireContext());
 | 
			
		||||
        recyclerView.setLayoutManager(layoutManager);
 | 
			
		||||
 | 
			
		||||
        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(this, new Observer<Boolean>() {
 | 
			
		||||
            @Override
 | 
			
		||||
            public void onChanged(@Nullable Boolean changed) {
 | 
			
		||||
                if(Boolean.TRUE.equals(changed)){
 | 
			
		||||
                    swipeRefresh.setRefreshing(true);
 | 
			
		||||
                }
 | 
			
		||||
                else{
 | 
			
		||||
                    swipeRefresh.setRefreshing(false);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
        mGeofavoritesFragmentViewModel.getGeofavorites().observe(this, new Observer<List<Geofavorite>>() {
 | 
			
		||||
            @Override
 | 
			
		||||
            public void onChanged(List<Geofavorite> geofavorites) {
 | 
			
		||||
                geofavoriteAdapter.setGeofavoriteList(geofavorites);
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        // 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()));
 | 
			
		||||
 | 
			
		||||
        return v;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
 | 
			
		||||
        super.onViewCreated(view, savedInstanceState);
 | 
			
		||||
 | 
			
		||||
        // Set icons
 | 
			
		||||
        // Setup list
 | 
			
		||||
        int sortRule = SettingsManager.getGeofavoriteListSortBy(requireContext());
 | 
			
		||||
        updateSortingIcon(sortRule);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void onSearch(String query) {
 | 
			
		||||
        geofavoriteAdapter.getFilter().filter(query);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @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,99 @@
 | 
			
		||||
package it.danieleverducci.nextcloudmaps.fragments;
 | 
			
		||||
 | 
			
		||||
import android.content.DialogInterface;
 | 
			
		||||
import android.content.Intent;
 | 
			
		||||
import android.os.Bundle;
 | 
			
		||||
import android.widget.Toast;
 | 
			
		||||
 | 
			
		||||
import androidx.annotation.Nullable;
 | 
			
		||||
import androidx.appcompat.app.AlertDialog;
 | 
			
		||||
import androidx.fragment.app.Fragment;
 | 
			
		||||
import androidx.lifecycle.Observer;
 | 
			
		||||
import androidx.lifecycle.ViewModelProvider;
 | 
			
		||||
 | 
			
		||||
import it.danieleverducci.nextcloudmaps.R;
 | 
			
		||||
import it.danieleverducci.nextcloudmaps.activity.detail.GeofavoriteDetailActivity;
 | 
			
		||||
import it.danieleverducci.nextcloudmaps.activity.main.GeofavoritesFragmentViewModel;
 | 
			
		||||
import it.danieleverducci.nextcloudmaps.model.Geofavorite;
 | 
			
		||||
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 {
 | 
			
		||||
 | 
			
		||||
    protected GeofavoritesFragmentViewModel mGeofavoritesFragmentViewModel;
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void onCreate(@Nullable Bundle savedInstanceState) {
 | 
			
		||||
        super.onCreate(savedInstanceState);
 | 
			
		||||
 | 
			
		||||
        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 onStart() {
 | 
			
		||||
        super.onStart();
 | 
			
		||||
 | 
			
		||||
        mGeofavoritesFragmentViewModel.updateGeofavorites();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    abstract public void onSearch(String query);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    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();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -1,15 +1,11 @@
 | 
			
		||||
package it.danieleverducci.nextcloudmaps.utils;
 | 
			
		||||
 | 
			
		||||
import android.content.Context;
 | 
			
		||||
 | 
			
		||||
import androidx.preference.PreferenceManager;
 | 
			
		||||
 | 
			
		||||
import it.danieleverducci.nextcloudmaps.R;
 | 
			
		||||
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_GRID_VIEW_ENABLED = "SETTING_GRID_VIEW_ENABLED";
 | 
			
		||||
    static private final String SETTING_LAST_SELECTED_LIST_VIEW = "SETTING_LAST_SELECTED_LIST_VIEW";
 | 
			
		||||
 | 
			
		||||
    public static int getGeofavoriteListSortBy(Context context) {
 | 
			
		||||
@@ -22,16 +18,6 @@ public class SettingsManager {
 | 
			
		||||
            .edit().putInt(SETTING_SORT_BY, value).apply();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static boolean isGeofavoriteListShownAsGrid(Context context) {
 | 
			
		||||
        return PreferenceManager.getDefaultSharedPreferences(context)
 | 
			
		||||
                .getBoolean(SETTING_GRID_VIEW_ENABLED, false);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static void setGeofavoriteListShownAsGrid(Context context, boolean value) {
 | 
			
		||||
        PreferenceManager.getDefaultSharedPreferences(context)
 | 
			
		||||
            .edit().putBoolean(SETTING_GRID_VIEW_ENABLED, value).apply();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static boolean isGeofavoriteListShownAsMap(Context context) {
 | 
			
		||||
        return PreferenceManager.getDefaultSharedPreferences(context)
 | 
			
		||||
                .getBoolean(SETTING_LAST_SELECTED_LIST_VIEW, false);
 | 
			
		||||
 
 | 
			
		||||
@@ -98,35 +98,6 @@
 | 
			
		||||
                        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_marginRight="@dimen/spacer_1x"
 | 
			
		||||
                        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>
 | 
			
		||||
@@ -135,30 +106,12 @@
 | 
			
		||||
 | 
			
		||||
    </com.google.android.material.appbar.AppBarLayout>
 | 
			
		||||
 | 
			
		||||
    <androidx.swiperefreshlayout.widget.SwipeRefreshLayout
 | 
			
		||||
        android:id="@+id/swipe_refresh"
 | 
			
		||||
    <androidx.fragment.app.FragmentContainerView
 | 
			
		||||
        android:id="@+id/fragment_container"
 | 
			
		||||
        android:layout_width="match_parent"
 | 
			
		||||
        android:layout_height="match_parent"
 | 
			
		||||
        android:layout_margin="@dimen/spacer_1hx"
 | 
			
		||||
        app:layout_behavior="@string/appbar_scrolling_view_behavior">
 | 
			
		||||
        android:name="it.danieleverducci.nextcloudmaps.fragments.GeofavoriteListFragment" />
 | 
			
		||||
 | 
			
		||||
        <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
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										40
									
								
								app/src/main/res/layout/fragment_geofavorite_list.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								app/src/main/res/layout/fragment_geofavorite_list.xml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,40 @@
 | 
			
		||||
<?xml version="1.0" encoding="utf-8"?>
 | 
			
		||||
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
 | 
			
		||||
    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/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.appcompat.widget.LinearLayoutCompat
 | 
			
		||||
        android:layout_width="match_parent"
 | 
			
		||||
        android:layout_height="match_parent"
 | 
			
		||||
        android:orientation="vertical">
 | 
			
		||||
 | 
			
		||||
        <androidx.appcompat.widget.AppCompatImageView
 | 
			
		||||
            android:id="@+id/sort_mode"
 | 
			
		||||
            android:layout_width="wrap_content"
 | 
			
		||||
            android:layout_height="@dimen/floating_bar_height"
 | 
			
		||||
            android:background="?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.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.appcompat.widget.LinearLayoutCompat>
 | 
			
		||||
 | 
			
		||||
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
 | 
			
		||||
@@ -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>
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user