Adds monster collections.
This commit is contained in:
@@ -0,0 +1,180 @@
|
||||
package com.majinnaibu.monstercards.ui.collections;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.text.TextUtils;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.lifecycle.ViewModelProvider;
|
||||
import androidx.navigation.NavDirections;
|
||||
import androidx.navigation.Navigation;
|
||||
import androidx.recyclerview.widget.GridLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.google.android.material.floatingactionbutton.FloatingActionButton;
|
||||
import com.google.android.material.snackbar.Snackbar;
|
||||
import com.majinnaibu.monstercards.R;
|
||||
import com.majinnaibu.monstercards.data.MonsterRepository;
|
||||
import com.majinnaibu.monstercards.models.Collection;
|
||||
import com.majinnaibu.monstercards.models.Monster;
|
||||
import com.majinnaibu.monstercards.ui.dashboard.DashboardRecyclerViewAdapter;
|
||||
import com.majinnaibu.monstercards.ui.shared.MCFragment;
|
||||
import com.majinnaibu.monstercards.utils.Logger;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.rxjava3.disposables.CompositeDisposable;
|
||||
import io.reactivex.rxjava3.schedulers.Schedulers;
|
||||
|
||||
public class CollectionDetailFragment extends MCFragment {
|
||||
|
||||
private CollectionDetailViewModel mViewModel;
|
||||
private UUID mCollectionId;
|
||||
private DashboardRecyclerViewAdapter mAdapter;
|
||||
private final CompositeDisposable mDisposables = new CompositeDisposable();
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
||||
View root = inflater.inflate(R.layout.fragment_collection_detail, container, false);
|
||||
|
||||
Bundle arguments = getArguments();
|
||||
assert arguments != null;
|
||||
mCollectionId = UUID.fromString(CollectionDetailFragmentArgs.fromBundle(arguments).getCollectionId());
|
||||
|
||||
mViewModel = new ViewModelProvider(this).get(CollectionDetailViewModel.class);
|
||||
|
||||
TextView nameView = root.findViewById(R.id.detail_collection_name);
|
||||
TextView descriptionView = root.findViewById(R.id.detail_collection_description);
|
||||
RecyclerView recyclerView = root.findViewById(R.id.collection_monster_list);
|
||||
FloatingActionButton fab = root.findViewById(R.id.fab_add_monster_to_collection);
|
||||
|
||||
if (fab != null) {
|
||||
fab.setOnClickListener(v -> showAddMonsterDialog());
|
||||
}
|
||||
|
||||
mViewModel.getCollection().observe(getViewLifecycleOwner(), collection -> {
|
||||
if (collection != null) {
|
||||
nameView.setText(collection.name);
|
||||
setTitle(collection.name);
|
||||
if (!TextUtils.isEmpty(collection.description)) {
|
||||
descriptionView.setVisibility(View.VISIBLE);
|
||||
descriptionView.setText(collection.description);
|
||||
} else {
|
||||
descriptionView.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
mViewModel.getMonsters().observe(getViewLifecycleOwner(), monsters -> {
|
||||
if (mAdapter != null) {
|
||||
mAdapter.submitList(monsters);
|
||||
}
|
||||
});
|
||||
|
||||
setupRecyclerView(recyclerView);
|
||||
loadCollectionData();
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
private void loadCollectionData() {
|
||||
MonsterRepository repository = getMonsterRepository();
|
||||
mDisposables.add(repository.getCollection(mCollectionId)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(collection -> {
|
||||
if (collection != null) {
|
||||
mViewModel.setCollection(collection);
|
||||
}
|
||||
}, Logger::logError));
|
||||
|
||||
mDisposables.add(repository.getMonstersForCollection(mCollectionId)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(monsters -> mViewModel.setMonsters(monsters), Logger::logError));
|
||||
}
|
||||
|
||||
private void setupRecyclerView(@NonNull RecyclerView recyclerView) {
|
||||
int columnCount = Math.max(1, getResources().getConfiguration().screenWidthDp / 396);
|
||||
Context context = requireContext();
|
||||
GridLayoutManager layoutManager = new GridLayoutManager(context, columnCount);
|
||||
recyclerView.setLayoutManager(layoutManager);
|
||||
|
||||
mAdapter = new DashboardRecyclerViewAdapter(monster -> {
|
||||
if (monster != null) {
|
||||
navigateToMonsterDetail(monster.id);
|
||||
} else {
|
||||
Logger.logError("Can't navigate to MonsterDetailFragment with a null monster");
|
||||
}
|
||||
});
|
||||
recyclerView.setAdapter(mAdapter);
|
||||
}
|
||||
|
||||
private void showAddMonsterDialog() {
|
||||
MonsterRepository repository = getMonsterRepository();
|
||||
mDisposables.add(repository.getMonsters()
|
||||
.firstOrError()
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(monsters -> {
|
||||
if (monsters.isEmpty()) {
|
||||
View view = getView();
|
||||
if (view != null) {
|
||||
Snackbar.make(view, getString(R.string.snackbar_failed_to_create_monster), Snackbar.LENGTH_LONG).show();
|
||||
}
|
||||
return;
|
||||
}
|
||||
String[] monsterNames = new String[monsters.size()];
|
||||
for (int i = 0; i < monsters.size(); i++) {
|
||||
monsterNames[i] = monsters.get(i).name;
|
||||
}
|
||||
new AlertDialog.Builder(requireContext())
|
||||
.setTitle(R.string.action_add_monster)
|
||||
.setItems(monsterNames, (dialog, which) -> {
|
||||
Monster selectedMonster = monsters.get(which);
|
||||
addMonsterToCollection(selectedMonster);
|
||||
})
|
||||
.setNegativeButton(R.string.dialog_cancel, null)
|
||||
.show();
|
||||
}, Logger::logError));
|
||||
}
|
||||
|
||||
private void addMonsterToCollection(Monster monster) {
|
||||
MonsterRepository repository = getMonsterRepository();
|
||||
mDisposables.add(repository.addMonsterToCollection(mCollectionId, monster.id)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(() -> {
|
||||
View view = getView();
|
||||
if (view != null) {
|
||||
Collection collection = mViewModel.getCollection().getValue();
|
||||
String collectionName = collection != null ? collection.name : "";
|
||||
Snackbar.make(
|
||||
view,
|
||||
getString(R.string.snackbar_monster_added_to_collection, monster.name, collectionName),
|
||||
Snackbar.LENGTH_LONG)
|
||||
.show();
|
||||
}
|
||||
}, Logger::logError));
|
||||
}
|
||||
|
||||
private void navigateToMonsterDetail(@NonNull UUID monsterId) {
|
||||
NavDirections action = CollectionDetailFragmentDirections.actionCollectionDetailFragmentToNavigationMonster(monsterId.toString());
|
||||
Navigation.findNavController(requireView()).navigate(action);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
super.onDestroyView();
|
||||
mDisposables.clear();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package com.majinnaibu.monstercards.ui.collections;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.lifecycle.LiveData;
|
||||
import androidx.lifecycle.MutableLiveData;
|
||||
import androidx.lifecycle.ViewModel;
|
||||
|
||||
import com.majinnaibu.monstercards.models.Collection;
|
||||
import com.majinnaibu.monstercards.models.Monster;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class CollectionDetailViewModel extends ViewModel {
|
||||
private final MutableLiveData<Collection> mCollection = new MutableLiveData<>();
|
||||
private final MutableLiveData<List<Monster>> mMonsters = new MutableLiveData<>(new ArrayList<>());
|
||||
|
||||
public CollectionDetailViewModel() {
|
||||
}
|
||||
|
||||
public LiveData<Collection> getCollection() {
|
||||
return mCollection;
|
||||
}
|
||||
|
||||
public void setCollection(Collection collection) {
|
||||
mCollection.setValue(collection);
|
||||
}
|
||||
|
||||
public LiveData<List<Monster>> getMonsters() {
|
||||
return mMonsters;
|
||||
}
|
||||
|
||||
public void setMonsters(List<Monster> monsters) {
|
||||
mMonsters.setValue(monsters);
|
||||
}
|
||||
}
|
||||
@@ -1,27 +1,158 @@
|
||||
package com.majinnaibu.monstercards.ui.collections;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.text.TextUtils;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
import android.widget.EditText;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.lifecycle.ViewModelProvider;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.navigation.NavDirections;
|
||||
import androidx.navigation.Navigation;
|
||||
import androidx.recyclerview.widget.DividerItemDecoration;
|
||||
import androidx.recyclerview.widget.ItemTouchHelper;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.google.android.material.floatingactionbutton.FloatingActionButton;
|
||||
import com.google.android.material.snackbar.Snackbar;
|
||||
import com.majinnaibu.monstercards.R;
|
||||
import com.majinnaibu.monstercards.data.MonsterRepository;
|
||||
import com.majinnaibu.monstercards.models.Collection;
|
||||
import com.majinnaibu.monstercards.ui.shared.MCFragment;
|
||||
import com.majinnaibu.monstercards.ui.shared.SwipeToDeleteCallback;
|
||||
import com.majinnaibu.monstercards.utils.Logger;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.rxjava3.observers.DisposableCompletableObserver;
|
||||
import io.reactivex.rxjava3.schedulers.Schedulers;
|
||||
|
||||
public class CollectionsFragment extends MCFragment {
|
||||
|
||||
private CollectionsViewModel collectionsViewModel;
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater,
|
||||
ViewGroup container, Bundle savedInstanceState) {
|
||||
collectionsViewModel = new ViewModelProvider(this).get(CollectionsViewModel.class);
|
||||
@Nullable ViewGroup container,
|
||||
@Nullable Bundle savedInstanceState) {
|
||||
View root = inflater.inflate(R.layout.fragment_collections, container, false);
|
||||
final TextView textView = root.findViewById(R.id.text_collections);
|
||||
collectionsViewModel.getText().observe(getViewLifecycleOwner(), textView::setText);
|
||||
|
||||
FloatingActionButton fab = root.findViewById(R.id.fab_add_collection);
|
||||
if (fab != null) {
|
||||
fab.setOnClickListener(v -> showCreateCollectionDialog());
|
||||
}
|
||||
|
||||
RecyclerView recyclerView = root.findViewById(R.id.collection_list);
|
||||
if (recyclerView != null) {
|
||||
setupRecyclerView(recyclerView);
|
||||
}
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
private void setupRecyclerView(@NonNull RecyclerView recyclerView) {
|
||||
Context context = requireContext();
|
||||
MonsterRepository repository = getMonsterRepository();
|
||||
|
||||
CollectionsRecyclerViewAdapter adapter = new CollectionsRecyclerViewAdapter(
|
||||
context,
|
||||
repository.getCollectionsWithCount(),
|
||||
collection -> navigateToCollectionDetail(collection.id),
|
||||
collection -> repository.deleteCollection(collection)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(new DisposableCompletableObserver() {
|
||||
@Override
|
||||
public void onComplete() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(@io.reactivex.rxjava3.annotations.NonNull Throwable e) {
|
||||
Logger.logError(e);
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
recyclerView.setAdapter(adapter);
|
||||
LinearLayoutManager layoutManager = new LinearLayoutManager(context);
|
||||
recyclerView.setLayoutManager(layoutManager);
|
||||
|
||||
DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(context, layoutManager.getOrientation());
|
||||
recyclerView.addItemDecoration(dividerItemDecoration);
|
||||
|
||||
ItemTouchHelper itemTouchHelper = new ItemTouchHelper(new SwipeToDeleteCallback(context, (position, direction) -> adapter.deleteItem(position), null));
|
||||
itemTouchHelper.attachToRecyclerView(recyclerView);
|
||||
}
|
||||
|
||||
private void showCreateCollectionDialog() {
|
||||
Context context = requireContext();
|
||||
LinearLayout layout = new LinearLayout(context);
|
||||
layout.setOrientation(LinearLayout.VERTICAL);
|
||||
int padding = (int) (16 * getResources().getDisplayMetrics().density);
|
||||
layout.setPadding(padding, padding, padding, padding);
|
||||
|
||||
final EditText nameInput = new EditText(context);
|
||||
nameInput.setHint(R.string.label_collection_name);
|
||||
layout.addView(nameInput);
|
||||
|
||||
final EditText descInput = new EditText(context);
|
||||
descInput.setHint(R.string.label_collection_description);
|
||||
layout.addView(descInput);
|
||||
|
||||
new AlertDialog.Builder(context)
|
||||
.setTitle(R.string.title_new_collection)
|
||||
.setView(layout)
|
||||
.setPositiveButton(R.string.dialog_create, (dialog, which) -> {
|
||||
String name = nameInput.getText().toString().trim();
|
||||
String description = descInput.getText().toString().trim();
|
||||
if (TextUtils.isEmpty(name)) {
|
||||
name = getString(R.string.title_new_collection);
|
||||
}
|
||||
createCollection(name, description);
|
||||
})
|
||||
.setNegativeButton(R.string.dialog_cancel, null)
|
||||
.show();
|
||||
}
|
||||
|
||||
private void createCollection(@NonNull String name, @NonNull String description) {
|
||||
Collection collection = new Collection(name, description);
|
||||
MonsterRepository repository = getMonsterRepository();
|
||||
repository.saveCollection(collection)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(new DisposableCompletableObserver() {
|
||||
@Override
|
||||
public void onComplete() {
|
||||
View view = getView();
|
||||
if (view != null) {
|
||||
Snackbar.make(
|
||||
view,
|
||||
getString(R.string.snackbar_collection_created, collection.name),
|
||||
Snackbar.LENGTH_LONG)
|
||||
.setAction("View", v -> navigateToCollectionDetail(collection.id))
|
||||
.show();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(@io.reactivex.rxjava3.annotations.NonNull Throwable e) {
|
||||
Logger.logError("Error creating collection", e);
|
||||
View view = getView();
|
||||
if (view != null) {
|
||||
Snackbar.make(view, getString(R.string.snackbar_failed_to_create_collection), Snackbar.LENGTH_LONG).show();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void navigateToCollectionDetail(@NonNull UUID collectionId) {
|
||||
NavDirections action = CollectionsFragmentDirections.actionNavigationCollectionsToCollectionDetailFragment(collectionId.toString());
|
||||
Navigation.findNavController(requireView()).navigate(action);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,137 @@
|
||||
package com.majinnaibu.monstercards.ui.collections;
|
||||
|
||||
import android.content.Context;
|
||||
import android.text.TextUtils;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.majinnaibu.monstercards.R;
|
||||
import com.majinnaibu.monstercards.models.Collection;
|
||||
import com.majinnaibu.monstercards.models.CollectionWithCount;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.rxjava3.core.Flowable;
|
||||
import io.reactivex.rxjava3.disposables.Disposable;
|
||||
import io.reactivex.rxjava3.schedulers.Schedulers;
|
||||
|
||||
public class CollectionsRecyclerViewAdapter extends RecyclerView.Adapter<CollectionsRecyclerViewAdapter.ViewHolder> {
|
||||
private final Context mContext;
|
||||
private final CollectionCallback mOnClick;
|
||||
private final CollectionCallback mOnDelete;
|
||||
private final Flowable<List<CollectionWithCount>> mItemsObservable;
|
||||
private List<CollectionWithCount> mValues;
|
||||
private Disposable mDisposable;
|
||||
|
||||
private final View.OnClickListener mOnClickListener = new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(@NonNull View view) {
|
||||
Collection collection = (Collection) view.getTag();
|
||||
if (mOnClick != null) {
|
||||
mOnClick.onCallback(collection);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public CollectionsRecyclerViewAdapter(Context context,
|
||||
Flowable<List<CollectionWithCount>> itemsObservable,
|
||||
CollectionCallback onClick,
|
||||
CollectionCallback onDelete) {
|
||||
mContext = context;
|
||||
mItemsObservable = itemsObservable;
|
||||
mOnClick = onClick;
|
||||
mOnDelete = onDelete;
|
||||
mValues = new ArrayList<>();
|
||||
mDisposable = null;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
View view = LayoutInflater.from(parent.getContext())
|
||||
.inflate(R.layout.collection_list_item, parent, false);
|
||||
return new ViewHolder(view);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
|
||||
CollectionWithCount item = mValues.get(position);
|
||||
Collection collection = item.collection;
|
||||
holder.mNameView.setText(collection.name);
|
||||
|
||||
String countText;
|
||||
if (item.monsterCount == 1) {
|
||||
countText = mContext.getString(R.string.format_monster_count_one);
|
||||
} else {
|
||||
countText = mContext.getString(R.string.format_monster_count_other, item.monsterCount);
|
||||
}
|
||||
holder.mCountView.setText(countText);
|
||||
holder.mCountView.setVisibility(View.VISIBLE);
|
||||
|
||||
if (!TextUtils.isEmpty(collection.description)) {
|
||||
holder.mDescriptionView.setVisibility(View.VISIBLE);
|
||||
holder.mDescriptionView.setText(collection.description);
|
||||
} else {
|
||||
holder.mDescriptionView.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
holder.itemView.setTag(collection);
|
||||
holder.itemView.setOnClickListener(mOnClickListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return mValues.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttachedToRecyclerView(@NonNull RecyclerView recyclerView) {
|
||||
super.onAttachedToRecyclerView(recyclerView);
|
||||
mDisposable = mItemsObservable
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(collections -> {
|
||||
mValues = collections;
|
||||
notifyDataSetChanged();
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDetachedFromRecyclerView(@NonNull RecyclerView recyclerView) {
|
||||
super.onDetachedFromRecyclerView(recyclerView);
|
||||
if (mDisposable != null) {
|
||||
mDisposable.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
public void deleteItem(int position) {
|
||||
if (mOnDelete != null && position >= 0 && position < mValues.size()) {
|
||||
Collection collection = mValues.get(position).collection;
|
||||
mOnDelete.onCallback(collection);
|
||||
}
|
||||
}
|
||||
|
||||
public interface CollectionCallback {
|
||||
void onCallback(Collection collection);
|
||||
}
|
||||
|
||||
static class ViewHolder extends RecyclerView.ViewHolder {
|
||||
final TextView mNameView;
|
||||
final TextView mDescriptionView;
|
||||
final TextView mCountView;
|
||||
|
||||
ViewHolder(View view) {
|
||||
super(view);
|
||||
mNameView = view.findViewById(R.id.collection_name);
|
||||
mDescriptionView = view.findViewById(R.id.collection_description);
|
||||
mCountView = view.findViewById(R.id.collection_count);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -38,7 +38,7 @@ public class DashboardRecyclerViewAdapter extends ListAdapter<Monster, Dashboard
|
||||
};
|
||||
private final ItemCallback mOnClick;
|
||||
|
||||
protected DashboardRecyclerViewAdapter(ItemCallback onClick) {
|
||||
public DashboardRecyclerViewAdapter(ItemCallback onClick) {
|
||||
super(DIFF_CALLBACK);
|
||||
mOnClick = onClick;
|
||||
}
|
||||
|
||||
@@ -18,14 +18,17 @@ import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.lifecycle.ViewModelProvider;
|
||||
import androidx.navigation.NavDirections;
|
||||
import androidx.navigation.Navigation;
|
||||
|
||||
import com.google.android.material.snackbar.Snackbar;
|
||||
import com.majinnaibu.monstercards.R;
|
||||
import com.majinnaibu.monstercards.data.MonsterRepository;
|
||||
import com.majinnaibu.monstercards.helpers.CommonMarkHelper;
|
||||
import com.majinnaibu.monstercards.helpers.StringHelper;
|
||||
import com.majinnaibu.monstercards.models.Collection;
|
||||
import com.majinnaibu.monstercards.models.Monster;
|
||||
import com.majinnaibu.monstercards.ui.shared.MCFragment;
|
||||
import com.majinnaibu.monstercards.utils.Logger;
|
||||
@@ -33,7 +36,10 @@ import com.majinnaibu.monstercards.utils.Logger;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.rxjava3.observers.DisposableCompletableObserver;
|
||||
import io.reactivex.rxjava3.observers.DisposableSingleObserver;
|
||||
import io.reactivex.rxjava3.schedulers.Schedulers;
|
||||
|
||||
public class MonsterDetailFragment extends MCFragment {
|
||||
private ViewHolder mHolder;
|
||||
@@ -172,10 +178,83 @@ public class MonsterDetailFragment extends MCFragment {
|
||||
Logger.logWTF("monsterId cannot be null.");
|
||||
}
|
||||
return true;
|
||||
} else if (item.getItemId() == R.id.menu_action_add_to_collection) {
|
||||
showAddToCollectionDialog();
|
||||
return true;
|
||||
}
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
private void showAddToCollectionDialog() {
|
||||
UUID monsterId = mViewModel.getId().getValue();
|
||||
if (monsterId == null) {
|
||||
return;
|
||||
}
|
||||
MonsterRepository repository = getMonsterRepository();
|
||||
repository.getCollections()
|
||||
.firstOrError()
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(new DisposableSingleObserver<List<Collection>>() {
|
||||
@Override
|
||||
public void onSuccess(@io.reactivex.rxjava3.annotations.NonNull List<Collection> collections) {
|
||||
if (collections.isEmpty()) {
|
||||
View view = getView();
|
||||
if (view != null) {
|
||||
Snackbar.make(view, getString(R.string.no_collections_available), Snackbar.LENGTH_LONG).show();
|
||||
}
|
||||
dispose();
|
||||
return;
|
||||
}
|
||||
String[] collectionNames = new String[collections.size()];
|
||||
for (int i = 0; i < collections.size(); i++) {
|
||||
collectionNames[i] = collections.get(i).name;
|
||||
}
|
||||
new AlertDialog.Builder(requireContext())
|
||||
.setTitle(R.string.title_select_collection)
|
||||
.setItems(collectionNames, (dialog, which) -> {
|
||||
Collection selectedCollection = collections.get(which);
|
||||
addMonsterToCollection(selectedCollection, monsterId);
|
||||
})
|
||||
.setNegativeButton(R.string.dialog_cancel, null)
|
||||
.show();
|
||||
dispose();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(@io.reactivex.rxjava3.annotations.NonNull Throwable e) {
|
||||
Logger.logError(e);
|
||||
dispose();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void addMonsterToCollection(@NonNull Collection collection, @NonNull UUID monsterId) {
|
||||
MonsterRepository repository = getMonsterRepository();
|
||||
repository.addMonsterToCollection(collection.id, monsterId)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(new DisposableCompletableObserver() {
|
||||
@Override
|
||||
public void onComplete() {
|
||||
View view = getView();
|
||||
if (view != null) {
|
||||
String monsterName = mViewModel.getName().getValue();
|
||||
Snackbar.make(
|
||||
view,
|
||||
getString(R.string.snackbar_monster_added_to_collection, monsterName, collection.name),
|
||||
Snackbar.LENGTH_LONG)
|
||||
.show();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(@io.reactivex.rxjava3.annotations.NonNull Throwable e) {
|
||||
Logger.logError(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static class ViewHolder {
|
||||
final TextView name;
|
||||
final TextView meta;
|
||||
|
||||
Reference in New Issue
Block a user