Separated list logic from application logic, support for multiple list fragments

This commit is contained in:
Daniele Verducci (Slimpenguin)
2024-02-17 09:07:59 +01:00
parent a1d6f1dabe
commit fa65c33ec6
9 changed files with 333 additions and 236 deletions
@@ -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();
}
}