diff --git a/Android/.idea/inspectionProfiles/Project_Default.xml b/Android/.idea/inspectionProfiles/Project_Default.xml
index 082b356..5d018a6 100644
--- a/Android/.idea/inspectionProfiles/Project_Default.xml
+++ b/Android/.idea/inspectionProfiles/Project_Default.xml
@@ -1,6 +1,7 @@
+
\ No newline at end of file
diff --git a/Android/app/src/main/java/com/majinnaibu/monstercards/ui/collections/CollectionsFragment.java b/Android/app/src/main/java/com/majinnaibu/monstercards/ui/collections/CollectionsFragment.java
index 45b711d..1245bcb 100644
--- a/Android/app/src/main/java/com/majinnaibu/monstercards/ui/collections/CollectionsFragment.java
+++ b/Android/app/src/main/java/com/majinnaibu/monstercards/ui/collections/CollectionsFragment.java
@@ -8,20 +8,19 @@ import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
-import androidx.fragment.app.Fragment;
import androidx.lifecycle.Observer;
-import androidx.lifecycle.ViewModelProviders;
+import androidx.lifecycle.ViewModelProvider;
import com.majinnaibu.monstercards.R;
+import com.majinnaibu.monstercards.ui.shared.MCFragment;
-public class CollectionsFragment extends Fragment {
+public class CollectionsFragment extends MCFragment {
private CollectionsViewModel collectionsViewModel;
public View onCreateView(@NonNull LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
- collectionsViewModel =
- ViewModelProviders.of(this).get(CollectionsViewModel.class);
+ collectionsViewModel = new ViewModelProvider(this).get(CollectionsViewModel.class);
View root = inflater.inflate(R.layout.fragment_collections, container, false);
final TextView textView = root.findViewById(R.id.text_collections);
collectionsViewModel.getText().observe(getViewLifecycleOwner(), new Observer() {
diff --git a/Android/app/src/main/java/com/majinnaibu/monstercards/ui/dashboard/DashboardFragment.java b/Android/app/src/main/java/com/majinnaibu/monstercards/ui/dashboard/DashboardFragment.java
index 22ac979..1b1eb5f 100644
--- a/Android/app/src/main/java/com/majinnaibu/monstercards/ui/dashboard/DashboardFragment.java
+++ b/Android/app/src/main/java/com/majinnaibu/monstercards/ui/dashboard/DashboardFragment.java
@@ -7,29 +7,21 @@ import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.fragment.app.Fragment;
-import androidx.lifecycle.Observer;
-import androidx.lifecycle.ViewModelProviders;
+import androidx.lifecycle.ViewModelProvider;
import com.majinnaibu.monstercards.R;
+import com.majinnaibu.monstercards.ui.shared.MCFragment;
-public class DashboardFragment extends Fragment {
+public class DashboardFragment extends MCFragment {
private DashboardViewModel dashboardViewModel;
public View onCreateView(@NonNull LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
- dashboardViewModel =
- ViewModelProviders.of(this).get(DashboardViewModel.class);
+ dashboardViewModel = new ViewModelProvider(this).get(DashboardViewModel.class);
View root = inflater.inflate(R.layout.fragment_dashboard, container, false);
final TextView textView = root.findViewById(R.id.text_dashboard);
- dashboardViewModel.getText().observe(getViewLifecycleOwner(), new Observer() {
- @Override
- public void onChanged(@Nullable String s) {
- textView.setText(s);
- }
- });
+ dashboardViewModel.getText().observe(getViewLifecycleOwner(), textView::setText);
return root;
}
}
\ No newline at end of file
diff --git a/Android/app/src/main/java/com/majinnaibu/monstercards/ui/dashboard/DashboardViewModel.java b/Android/app/src/main/java/com/majinnaibu/monstercards/ui/dashboard/DashboardViewModel.java
index 4748dd1..97d3340 100644
--- a/Android/app/src/main/java/com/majinnaibu/monstercards/ui/dashboard/DashboardViewModel.java
+++ b/Android/app/src/main/java/com/majinnaibu/monstercards/ui/dashboard/DashboardViewModel.java
@@ -5,8 +5,7 @@ import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;
public class DashboardViewModel extends ViewModel {
-
- private MutableLiveData mText;
+ private final MutableLiveData mText;
public DashboardViewModel() {
mText = new MutableLiveData<>();
diff --git a/Android/app/src/main/java/com/majinnaibu/monstercards/ui/editmonster/EditAbilityScoresFragment.java b/Android/app/src/main/java/com/majinnaibu/monstercards/ui/editmonster/EditAbilityScoresFragment.java
index 697a287..c1eea6e 100644
--- a/Android/app/src/main/java/com/majinnaibu/monstercards/ui/editmonster/EditAbilityScoresFragment.java
+++ b/Android/app/src/main/java/com/majinnaibu/monstercards/ui/editmonster/EditAbilityScoresFragment.java
@@ -13,6 +13,7 @@ import androidx.navigation.Navigation;
import com.majinnaibu.monstercards.R;
import com.majinnaibu.monstercards.ui.components.Stepper;
+import com.majinnaibu.monstercards.ui.shared.MCFragment;
public class EditAbilityScoresFragment extends Fragment {
private final String ABILITY_SCORE_FORMAT = "%d (%+d)";
diff --git a/Android/app/src/main/java/com/majinnaibu/monstercards/ui/editmonster/EditArmorFragment.java b/Android/app/src/main/java/com/majinnaibu/monstercards/ui/editmonster/EditArmorFragment.java
index a913d27..75b159a 100644
--- a/Android/app/src/main/java/com/majinnaibu/monstercards/ui/editmonster/EditArmorFragment.java
+++ b/Android/app/src/main/java/com/majinnaibu/monstercards/ui/editmonster/EditArmorFragment.java
@@ -13,7 +13,6 @@ import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.SwitchCompat;
-import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;
import androidx.navigation.NavBackStackEntry;
import androidx.navigation.NavController;
@@ -22,10 +21,10 @@ import androidx.navigation.Navigation;
import com.majinnaibu.monstercards.R;
import com.majinnaibu.monstercards.data.enums.ArmorType;
import com.majinnaibu.monstercards.helpers.ArrayHelper;
+import com.majinnaibu.monstercards.ui.shared.MCFragment;
import com.majinnaibu.monstercards.utils.TextChangedListener;
-@SuppressWarnings("FieldCanBeLocal")
-public class EditArmorFragment extends Fragment {
+public class EditArmorFragment extends MCFragment {
private EditMonsterViewModel mViewModel;
private ViewHolder mHolder;
diff --git a/Android/app/src/main/java/com/majinnaibu/monstercards/ui/editmonster/EditBasicInfoFragment.java b/Android/app/src/main/java/com/majinnaibu/monstercards/ui/editmonster/EditBasicInfoFragment.java
index 9a99c88..1ccf3e1 100644
--- a/Android/app/src/main/java/com/majinnaibu/monstercards/ui/editmonster/EditBasicInfoFragment.java
+++ b/Android/app/src/main/java/com/majinnaibu/monstercards/ui/editmonster/EditBasicInfoFragment.java
@@ -13,10 +13,9 @@ import androidx.navigation.Navigation;
import com.google.android.material.switchmaterial.SwitchMaterial;
import com.majinnaibu.monstercards.R;
-import com.majinnaibu.monstercards.ui.MCFragment;
+import com.majinnaibu.monstercards.ui.shared.MCFragment;
import com.majinnaibu.monstercards.utils.TextChangedListener;
-@SuppressWarnings("FieldCanBeLocal")
public class EditBasicInfoFragment extends MCFragment {
private EditMonsterViewModel mViewModel;
private ViewHolder mHolder;
diff --git a/Android/app/src/main/java/com/majinnaibu/monstercards/ui/editmonster/EditChallengeRatingFragment.java b/Android/app/src/main/java/com/majinnaibu/monstercards/ui/editmonster/EditChallengeRatingFragment.java
index ec4b724..c2b0008 100644
--- a/Android/app/src/main/java/com/majinnaibu/monstercards/ui/editmonster/EditChallengeRatingFragment.java
+++ b/Android/app/src/main/java/com/majinnaibu/monstercards/ui/editmonster/EditChallengeRatingFragment.java
@@ -12,7 +12,6 @@ import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
-import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;
import androidx.navigation.NavBackStackEntry;
import androidx.navigation.NavController;
@@ -21,9 +20,10 @@ import androidx.navigation.Navigation;
import com.majinnaibu.monstercards.R;
import com.majinnaibu.monstercards.data.enums.ChallengeRating;
import com.majinnaibu.monstercards.helpers.ArrayHelper;
+import com.majinnaibu.monstercards.ui.shared.MCFragment;
import com.majinnaibu.monstercards.utils.TextChangedListener;
-public class EditChallengeRatingFragment extends Fragment {
+public class EditChallengeRatingFragment extends MCFragment {
private EditMonsterViewModel mViewModel;
private ViewHolder mHolder;
diff --git a/Android/app/src/main/java/com/majinnaibu/monstercards/ui/editmonster/EditConditionImmunitiesFragment.java b/Android/app/src/main/java/com/majinnaibu/monstercards/ui/editmonster/EditConditionImmunitiesFragment.java
new file mode 100644
index 0000000..ac3e605
--- /dev/null
+++ b/Android/app/src/main/java/com/majinnaibu/monstercards/ui/editmonster/EditConditionImmunitiesFragment.java
@@ -0,0 +1,95 @@
+package com.majinnaibu.monstercards.ui.editmonster;
+
+import android.content.Context;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.fragment.app.Fragment;
+import androidx.lifecycle.ViewModelProvider;
+import androidx.navigation.NavBackStackEntry;
+import androidx.navigation.NavController;
+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.majinnaibu.monstercards.R;
+import com.majinnaibu.monstercards.ui.shared.SwipeToDeleteCallback;
+import com.majinnaibu.monstercards.utils.Logger;
+
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * A fragment representing a list of Items.
+ */
+public class EditConditionImmunitiesFragment extends Fragment {
+ private EditMonsterViewModel mViewModel;
+ private ViewHolder mHolder;
+
+ private void navigateToEditConditionImmunity(String condition) {
+ NavDirections action = EditConditionImmunitiesFragmentDirections.actionEditConditionImmunitiesFragmentToEditConditionImmunity(condition);
+ View view = getView();
+ assert view != null;
+ Navigation.findNavController(view).navigate(action);
+ }
+
+ @Nullable
+ @Override
+ public View onCreateView(@NonNull @NotNull LayoutInflater inflater, @Nullable @org.jetbrains.annotations.Nullable ViewGroup container, @Nullable @org.jetbrains.annotations.Nullable Bundle savedInstanceState) {
+ NavController navController = Navigation.findNavController(requireActivity(), R.id.nav_host_fragment);
+ NavBackStackEntry backStackEntry = navController.getBackStackEntry(R.id.edit_monster_navigation);
+ mViewModel = new ViewModelProvider(backStackEntry).get(EditMonsterViewModel.class);
+ View root = inflater.inflate(R.layout.fragment_edit_condition_immunities_list, container, false);
+ mHolder = new ViewHolder(root);
+ setupRecyclerView(mHolder.list);
+ setupAddConditionImmunityButton(mHolder.addConditionImmunity);
+ return root;
+ }
+
+ private void setupRecyclerView(@NonNull RecyclerView recyclerView) {
+ Context context = requireContext();
+ LinearLayoutManager layoutManager = new LinearLayoutManager(context);
+ recyclerView.setLayoutManager(layoutManager);
+
+ mViewModel.getConditionImmunities().observe(getViewLifecycleOwner(), conditionImmunities -> {
+ EditConditionImmunitiesRecyclerViewAdapter adapter = new EditConditionImmunitiesRecyclerViewAdapter(mViewModel.getConditionImmunitiesArray(), condition -> {
+ if (condition != null) {
+ navigateToEditConditionImmunity(condition);
+ } else {
+ Logger.logError("Can't navigate to EditConditionImmunityFragment with a null condition");
+ }
+ });
+ recyclerView.setAdapter(adapter);
+ });
+
+ DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(context, layoutManager.getOrientation());
+ recyclerView.addItemDecoration(dividerItemDecoration);
+
+ ItemTouchHelper itemTouchHelper = new ItemTouchHelper(new SwipeToDeleteCallback(context, mViewModel::removeConditionImmunity));
+ itemTouchHelper.attachToRecyclerView(recyclerView);
+ }
+
+ private void setupAddConditionImmunityButton(@NonNull FloatingActionButton fab) {
+ fab.setOnClickListener(view -> {
+ String condition = mViewModel.addNewConditionImmunity();
+ navigateToEditConditionImmunity(condition);
+ });
+ }
+
+ private static class ViewHolder {
+ RecyclerView list;
+ FloatingActionButton addConditionImmunity;
+
+ ViewHolder(View root) {
+ list = root.findViewById(R.id.list);
+ addConditionImmunity = root.findViewById(R.id.add_condition_immunity);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Android/app/src/main/java/com/majinnaibu/monstercards/ui/editmonster/EditMonsterFragment.java b/Android/app/src/main/java/com/majinnaibu/monstercards/ui/editmonster/EditMonsterFragment.java
index e461b0b..4af2a85 100644
--- a/Android/app/src/main/java/com/majinnaibu/monstercards/ui/editmonster/EditMonsterFragment.java
+++ b/Android/app/src/main/java/com/majinnaibu/monstercards/ui/editmonster/EditMonsterFragment.java
@@ -20,8 +20,8 @@ import com.google.android.material.snackbar.Snackbar;
import com.majinnaibu.monstercards.R;
import com.majinnaibu.monstercards.data.MonsterRepository;
import com.majinnaibu.monstercards.models.Monster;
-import com.majinnaibu.monstercards.ui.MCFragment;
import com.majinnaibu.monstercards.ui.monster.MonsterDetailFragmentArgs;
+import com.majinnaibu.monstercards.ui.shared.MCFragment;
import com.majinnaibu.monstercards.utils.Logger;
import java.util.Objects;
@@ -32,7 +32,6 @@ import io.reactivex.rxjava3.observers.DisposableCompletableObserver;
import io.reactivex.rxjava3.observers.DisposableSingleObserver;
import io.reactivex.rxjava3.schedulers.Schedulers;
-@SuppressWarnings("FieldCanBeLocal")
public class EditMonsterFragment extends MCFragment {
private EditMonsterViewModel mViewModel;
diff --git a/Android/app/src/main/java/com/majinnaibu/monstercards/ui/editmonster/EditMonsterViewModel.java b/Android/app/src/main/java/com/majinnaibu/monstercards/ui/editmonster/EditMonsterViewModel.java
index 6fa13a8..1af08b7 100644
--- a/Android/app/src/main/java/com/majinnaibu/monstercards/ui/editmonster/EditMonsterViewModel.java
+++ b/Android/app/src/main/java/com/majinnaibu/monstercards/ui/editmonster/EditMonsterViewModel.java
@@ -3,7 +3,6 @@ package com.majinnaibu.monstercards.ui.editmonster;
import androidx.annotation.NonNull;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
-import androidx.lifecycle.ViewModel;
import com.majinnaibu.monstercards.data.enums.AbilityScore;
import com.majinnaibu.monstercards.data.enums.AdvantageType;
@@ -15,22 +14,22 @@ import com.majinnaibu.monstercards.models.Language;
import com.majinnaibu.monstercards.models.Monster;
import com.majinnaibu.monstercards.models.Skill;
import com.majinnaibu.monstercards.models.Trait;
+import com.majinnaibu.monstercards.ui.shared.ChangeTrackedViewModel;
import com.majinnaibu.monstercards.utils.ChangeTrackedLiveData;
import java.util.ArrayList;
import java.util.Collections;
+import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
-import java.util.Set;
import java.util.UUID;
@SuppressWarnings({"ConstantConditions", "unused"})
-public class EditMonsterViewModel extends ViewModel {
+public class EditMonsterViewModel extends ChangeTrackedViewModel {
private final ChangeTrackedLiveData mMonsterId;
private final MutableLiveData mHasError;
private final MutableLiveData mHasLoaded;
- private final MutableLiveData mHasChanges;
private final ChangeTrackedLiveData mHasCustomHitPoints;
private final ChangeTrackedLiveData mHasShield;
private final ChangeTrackedLiveData mCanHover;
@@ -78,83 +77,82 @@ public class EditMonsterViewModel extends ViewModel {
private final ChangeTrackedLiveData mUnderstandsButDescription;
private final ChangeTrackedLiveData> mSkills;
private final ChangeTrackedLiveData> mSenses;
- private final ChangeTrackedLiveData> mDamageImmunities;
- private final ChangeTrackedLiveData> mDamageResistances;
- private final ChangeTrackedLiveData> mDamageVulnerabilities;
- private final ChangeTrackedLiveData> mConditionImmunities;
- private final ChangeTrackedLiveData> mLanguages;
- private final ChangeTrackedLiveData> mAbilities;
- private final ChangeTrackedLiveData> mActions;
- private final ChangeTrackedLiveData> mReactions;
- private final ChangeTrackedLiveData> mLairActions;
- private final ChangeTrackedLiveData> mLegendaryActions;
- private final ChangeTrackedLiveData> mRegionalActions;
+ private final ChangeTrackedLiveData> mDamageImmunities;
+ private final ChangeTrackedLiveData> mDamageResistances;
+ private final ChangeTrackedLiveData> mDamageVulnerabilities;
+ private final ChangeTrackedLiveData> mConditionImmunities;
+ private final ChangeTrackedLiveData> mLanguages;
+ private final ChangeTrackedLiveData> mAbilities;
+ private final ChangeTrackedLiveData> mActions;
+ private final ChangeTrackedLiveData> mReactions;
+ private final ChangeTrackedLiveData> mLairActions;
+ private final ChangeTrackedLiveData> mLegendaryActions;
+ private final ChangeTrackedLiveData> mRegionalActions;
public EditMonsterViewModel() {
+ super();
mErrorMessage = new MutableLiveData<>("");
mHasError = new MutableLiveData<>(false);
mHasLoaded = new MutableLiveData<>(false);
- mHasChanges = new MutableLiveData<>(false);
- ChangeTrackedLiveData.OnValueDirtiedCallback onDirtied = () -> mHasChanges.setValue(true);
- mName = new ChangeTrackedLiveData<>("", onDirtied);
- mMonsterId = new ChangeTrackedLiveData<>(UUID.randomUUID(), onDirtied);
- mSize = new ChangeTrackedLiveData<>("", onDirtied);
- mType = new ChangeTrackedLiveData<>("", onDirtied);
- mSubtype = new ChangeTrackedLiveData<>("", onDirtied);
- mAlignment = new ChangeTrackedLiveData<>("", onDirtied);
- mCustomHitPoints = new ChangeTrackedLiveData<>("", onDirtied);
- mHitDice = new ChangeTrackedLiveData<>(0, onDirtied);
- mNaturalArmorBonus = new ChangeTrackedLiveData<>(0, onDirtied);
- mHasCustomHitPoints = new ChangeTrackedLiveData<>(false, onDirtied);
- mArmorType = new ChangeTrackedLiveData<>(ArmorType.NONE, onDirtied);
- mHasShield = new ChangeTrackedLiveData<>(false, onDirtied);
- mShieldBonus = new ChangeTrackedLiveData<>(0, onDirtied);
- mCustomArmor = new ChangeTrackedLiveData<>("", onDirtied);
- mWalkSpeed = new ChangeTrackedLiveData<>(0, onDirtied);
- mBurrowSpeed = new ChangeTrackedLiveData<>(0, onDirtied);
- mClimbSpeed = new ChangeTrackedLiveData<>(0, onDirtied);
- mFlySpeed = new ChangeTrackedLiveData<>(0, onDirtied);
- mSwimSpeed = new ChangeTrackedLiveData<>(0, onDirtied);
- mCanHover = new ChangeTrackedLiveData<>(false, onDirtied);
- mHasCustomSpeed = new ChangeTrackedLiveData<>(false, onDirtied);
- mCustomSpeed = new ChangeTrackedLiveData<>("", onDirtied);
- mStrength = new ChangeTrackedLiveData<>(10, onDirtied);
- mDexterity = new ChangeTrackedLiveData<>(10, onDirtied);
- mConstitution = new ChangeTrackedLiveData<>(10, onDirtied);
- mIntelligence = new ChangeTrackedLiveData<>(10, onDirtied);
- mWisdom = new ChangeTrackedLiveData<>(10, onDirtied);
- mCharisma = new ChangeTrackedLiveData<>(10, onDirtied);
- mStrengthProficiency = new ChangeTrackedLiveData<>(ProficiencyType.NONE, onDirtied);
- mStrengthAdvantage = new ChangeTrackedLiveData<>(AdvantageType.NONE, onDirtied);
- mDexterityProficiency = new ChangeTrackedLiveData<>(ProficiencyType.NONE, onDirtied);
- mDexterityAdvantage = new ChangeTrackedLiveData<>(AdvantageType.NONE, onDirtied);
- mConstitutionProficiency = new ChangeTrackedLiveData<>(ProficiencyType.NONE, onDirtied);
- mConstitutionAdvantage = new ChangeTrackedLiveData<>(AdvantageType.NONE, onDirtied);
- mIntelligenceProficiency = new ChangeTrackedLiveData<>(ProficiencyType.NONE, onDirtied);
- mIntelligenceAdvantage = new ChangeTrackedLiveData<>(AdvantageType.NONE, onDirtied);
- mWisdomProficiency = new ChangeTrackedLiveData<>(ProficiencyType.NONE, onDirtied);
- mWisdomAdvantage = new ChangeTrackedLiveData<>(AdvantageType.NONE, onDirtied);
- mCharismaProficiency = new ChangeTrackedLiveData<>(ProficiencyType.NONE, onDirtied);
- mCharismaAdvantage = new ChangeTrackedLiveData<>(AdvantageType.NONE, onDirtied);
- mChallengeRating = new ChangeTrackedLiveData<>(ChallengeRating.ONE_EIGHTH, onDirtied);
- mCustomChallengeRatingDescription = new ChangeTrackedLiveData<>("", onDirtied);
- mCustomProficiencyBonus = new ChangeTrackedLiveData<>(0, onDirtied);
- mTelepathyRange = new ChangeTrackedLiveData<>(0, onDirtied);
- mUnderstandsButDescription = new ChangeTrackedLiveData<>("", onDirtied);
- mSkills = new ChangeTrackedLiveData<>(new ArrayList<>(), onDirtied);
- mSenses = new ChangeTrackedLiveData<>(new ArrayList<>(), onDirtied);
- mDamageImmunities = new ChangeTrackedLiveData<>(new HashSet<>(), onDirtied);
- mDamageResistances = new ChangeTrackedLiveData<>(new HashSet<>(), onDirtied);
- mDamageVulnerabilities = new ChangeTrackedLiveData<>(new HashSet<>(), onDirtied);
- mConditionImmunities = new ChangeTrackedLiveData<>(new HashSet<>(), onDirtied);
- mLanguages = new ChangeTrackedLiveData<>(new HashSet<>(), onDirtied);
- mAbilities = new ChangeTrackedLiveData<>(new HashSet<>(), onDirtied);
- mActions = new ChangeTrackedLiveData<>(new HashSet<>(), onDirtied);
- mReactions = new ChangeTrackedLiveData<>(new HashSet<>(), onDirtied);
- mLairActions = new ChangeTrackedLiveData<>(new HashSet<>(), onDirtied);
- mLegendaryActions = new ChangeTrackedLiveData<>(new HashSet<>(), onDirtied);
- mRegionalActions = new ChangeTrackedLiveData<>(new HashSet<>(), onDirtied);
+ mName = new ChangeTrackedLiveData<>("", this::makeDirty);
+ mMonsterId = new ChangeTrackedLiveData<>(UUID.randomUUID(), this::makeDirty);
+ mSize = new ChangeTrackedLiveData<>("", this::makeDirty);
+ mType = new ChangeTrackedLiveData<>("", this::makeDirty);
+ mSubtype = new ChangeTrackedLiveData<>("", this::makeDirty);
+ mAlignment = new ChangeTrackedLiveData<>("", this::makeDirty);
+ mCustomHitPoints = new ChangeTrackedLiveData<>("", this::makeDirty);
+ mHitDice = new ChangeTrackedLiveData<>(0, this::makeDirty);
+ mNaturalArmorBonus = new ChangeTrackedLiveData<>(0, this::makeDirty);
+ mHasCustomHitPoints = new ChangeTrackedLiveData<>(false, this::makeDirty);
+ mArmorType = new ChangeTrackedLiveData<>(ArmorType.NONE, this::makeDirty);
+ mHasShield = new ChangeTrackedLiveData<>(false, this::makeDirty);
+ mShieldBonus = new ChangeTrackedLiveData<>(0, this::makeDirty);
+ mCustomArmor = new ChangeTrackedLiveData<>("", this::makeDirty);
+ mWalkSpeed = new ChangeTrackedLiveData<>(0, this::makeDirty);
+ mBurrowSpeed = new ChangeTrackedLiveData<>(0, this::makeDirty);
+ mClimbSpeed = new ChangeTrackedLiveData<>(0, this::makeDirty);
+ mFlySpeed = new ChangeTrackedLiveData<>(0, this::makeDirty);
+ mSwimSpeed = new ChangeTrackedLiveData<>(0, this::makeDirty);
+ mCanHover = new ChangeTrackedLiveData<>(false, this::makeDirty);
+ mHasCustomSpeed = new ChangeTrackedLiveData<>(false, this::makeDirty);
+ mCustomSpeed = new ChangeTrackedLiveData<>("", this::makeDirty);
+ mStrength = new ChangeTrackedLiveData<>(10, this::makeDirty);
+ mDexterity = new ChangeTrackedLiveData<>(10, this::makeDirty);
+ mConstitution = new ChangeTrackedLiveData<>(10, this::makeDirty);
+ mIntelligence = new ChangeTrackedLiveData<>(10, this::makeDirty);
+ mWisdom = new ChangeTrackedLiveData<>(10, this::makeDirty);
+ mCharisma = new ChangeTrackedLiveData<>(10, this::makeDirty);
+ mStrengthProficiency = new ChangeTrackedLiveData<>(ProficiencyType.NONE, this::makeDirty);
+ mStrengthAdvantage = new ChangeTrackedLiveData<>(AdvantageType.NONE, this::makeDirty);
+ mDexterityProficiency = new ChangeTrackedLiveData<>(ProficiencyType.NONE, this::makeDirty);
+ mDexterityAdvantage = new ChangeTrackedLiveData<>(AdvantageType.NONE, this::makeDirty);
+ mConstitutionProficiency = new ChangeTrackedLiveData<>(ProficiencyType.NONE, this::makeDirty);
+ mConstitutionAdvantage = new ChangeTrackedLiveData<>(AdvantageType.NONE, this::makeDirty);
+ mIntelligenceProficiency = new ChangeTrackedLiveData<>(ProficiencyType.NONE, this::makeDirty);
+ mIntelligenceAdvantage = new ChangeTrackedLiveData<>(AdvantageType.NONE, this::makeDirty);
+ mWisdomProficiency = new ChangeTrackedLiveData<>(ProficiencyType.NONE, this::makeDirty);
+ mWisdomAdvantage = new ChangeTrackedLiveData<>(AdvantageType.NONE, this::makeDirty);
+ mCharismaProficiency = new ChangeTrackedLiveData<>(ProficiencyType.NONE, this::makeDirty);
+ mCharismaAdvantage = new ChangeTrackedLiveData<>(AdvantageType.NONE, this::makeDirty);
+ mChallengeRating = new ChangeTrackedLiveData<>(ChallengeRating.ONE_EIGHTH, this::makeDirty);
+ mCustomChallengeRatingDescription = new ChangeTrackedLiveData<>("", this::makeDirty);
+ mCustomProficiencyBonus = new ChangeTrackedLiveData<>(0, this::makeDirty);
+ mTelepathyRange = new ChangeTrackedLiveData<>(0, this::makeDirty);
+ mUnderstandsButDescription = new ChangeTrackedLiveData<>("", this::makeDirty);
+ mSkills = new ChangeTrackedLiveData<>(new ArrayList<>(), this::makeDirty);
+ mSenses = new ChangeTrackedLiveData<>(new ArrayList<>(), this::makeDirty);
+ mDamageImmunities = new ChangeTrackedLiveData<>(new ArrayList<>(), this::makeDirty);
+ mDamageResistances = new ChangeTrackedLiveData<>(new ArrayList<>(), this::makeDirty);
+ mDamageVulnerabilities = new ChangeTrackedLiveData<>(new ArrayList<>(), this::makeDirty);
+ mConditionImmunities = new ChangeTrackedLiveData<>(new ArrayList<>(), this::makeDirty);
+ mLanguages = new ChangeTrackedLiveData<>(new ArrayList<>(), this::makeDirty);
+ mAbilities = new ChangeTrackedLiveData<>(new ArrayList<>(), this::makeDirty);
+ mActions = new ChangeTrackedLiveData<>(new ArrayList<>(), this::makeDirty);
+ mReactions = new ChangeTrackedLiveData<>(new ArrayList<>(), this::makeDirty);
+ mLairActions = new ChangeTrackedLiveData<>(new ArrayList<>(), this::makeDirty);
+ mLegendaryActions = new ChangeTrackedLiveData<>(new ArrayList<>(), this::makeDirty);
+ mRegionalActions = new ChangeTrackedLiveData<>(new ArrayList<>(), this::makeDirty);
}
public void copyFromMonster(Monster monster) {
@@ -210,18 +208,28 @@ public class EditMonsterViewModel extends ViewModel {
ArrayList senses = new ArrayList<>(monster.senses);
Collections.sort(senses, String::compareToIgnoreCase);
mSenses.resetValue(senses);
- mDamageImmunities.resetValue(monster.damageImmunities);
- mDamageResistances.resetValue(monster.damageResistances);
- mDamageVulnerabilities.resetValue(monster.damageVulnerabilities);
- mConditionImmunities.resetValue(monster.conditionImmunities);
- mLanguages.resetValue(monster.languages);
- mAbilities.resetValue(monster.abilities);
- mActions.resetValue(monster.actions);
- mReactions.resetValue(monster.reactions);
- mLairActions.resetValue(monster.lairActions);
- mLegendaryActions.resetValue(monster.legendaryActions);
- mRegionalActions.resetValue(monster.regionalActions);
- mHasChanges.setValue(false);
+ ArrayList damageImmunities = new ArrayList<>(monster.damageImmunities);
+ Collections.sort(damageImmunities, String::compareToIgnoreCase);
+ mDamageImmunities.resetValue(damageImmunities);
+ ArrayList damageResistances = new ArrayList<>(monster.damageResistances);
+ Collections.sort(damageResistances, String::compareToIgnoreCase);
+ mDamageResistances.resetValue(damageResistances);
+ ArrayList damageVulnerabilities = new ArrayList<>(monster.damageVulnerabilities);
+ Collections.sort(damageVulnerabilities, String::compareToIgnoreCase);
+ mDamageVulnerabilities.resetValue(damageVulnerabilities);
+ ArrayList conditionImmunities = new ArrayList<>(monster.conditionImmunities);
+ Collections.sort(conditionImmunities, String::compareToIgnoreCase);
+ mConditionImmunities.resetValue(conditionImmunities);
+ ArrayList languages = new ArrayList<>(monster.languages);
+ Collections.sort(languages, (lang1, lang2) -> lang1.getName().compareToIgnoreCase(lang2.getName()));
+ mLanguages.resetValue(languages);
+ mAbilities.resetValue(new ArrayList<>(monster.abilities));
+ mActions.resetValue(new ArrayList<>(monster.actions));
+ mReactions.resetValue(new ArrayList<>(monster.reactions));
+ mLairActions.resetValue(new ArrayList<>(monster.lairActions));
+ mLegendaryActions.resetValue(new ArrayList<>(monster.legendaryActions));
+ mRegionalActions.resetValue(new ArrayList<>(monster.regionalActions));
+ makeClean();
}
public LiveData getName() {
@@ -308,14 +316,6 @@ public class EditMonsterViewModel extends ViewModel {
mCustomHitPoints.setValue(customHitPoints);
}
- public LiveData getHasChanges() {
- return mHasChanges;
- }
-
- public boolean hasChanges() {
- return mHasChanges.getValue();
- }
-
public LiveData getHitDice() {
return mHitDice;
}
@@ -756,13 +756,295 @@ public class EditMonsterViewModel extends ViewModel {
return mSkills;
}
+ public List getSkillsArray() {
+ return mSkills.getValue();
+ }
+
+ public Skill addNewSkill() {
+ Skill newSkill = new Skill("Unnamed Skill", AbilityScore.DEXTERITY);
+ ArrayList newSkills = new ArrayList<>(mSkills.getValue());
+ newSkills.add(newSkill);
+ Collections.sort(newSkills, (skill1, skill2) -> skill1.name.compareToIgnoreCase(skill2.name));
+ mSkills.setValue(newSkills);
+ return newSkill;
+ }
+
+ public void removeSkill(int position) {
+ List skills = mSkills.getValue();
+ ArrayList newSkills = new ArrayList<>(skills);
+ newSkills.remove(position);
+ mSkills.setValue(newSkills);
+ }
+
+ public void replaceSkill(Skill newSkill, Skill oldSkill) {
+ List oldSkills = mSkills.getValue();
+ if (oldSkills == null) {
+ oldSkills = new ArrayList<>();
+ }
+ boolean hasReplaced = false;
+ ArrayList newSkills = new ArrayList<>(oldSkills.size());
+ for (Skill skill : oldSkills) {
+ if (Objects.equals(skill, oldSkill)) {
+ newSkills.add(newSkill);
+ hasReplaced = true;
+ } else {
+ newSkills.add(skill);
+ }
+ }
+ if (!hasReplaced) {
+ newSkills.add(newSkill);
+ }
+ Collections.sort(newSkills, (skill1, skill2) -> skill1.name.compareToIgnoreCase(skill2.name));
+ mSkills.setValue(newSkills);
+ }
+
+ public LiveData> getSenses() {
+ return mSenses;
+ }
+
public List getSensesArray() {
return mSenses.getValue();
}
- // TODO: add getters and setters for lists of strings (Senses, Damage Immunities, Damage Resistances, Damage Vulnerabilities, and Condition Immunities)
- // TODO: add getters and setters for Languages
- // TODO: add getters and setters for traits (Abilities, Actions, Reactions, Lair Actions, Legendary Actions, and Regional Actions)
+ public String addNewSense() {
+ return Helpers.addItemToList(mSenses, "", String::compareToIgnoreCase);
+ }
+
+ public void removeSense(int position) {
+ Helpers.removeFromList(mSenses, position);
+ }
+
+ public void replaceSense(String oldSense, String newSense) {
+ Helpers.replaceItemInList(mSenses, oldSense, newSense, String::compareToIgnoreCase);
+ }
+
+ public LiveData> getDamageImmunities() {
+ return mDamageImmunities;
+ }
+
+ public List getDamageImmunitiesArray() {
+ return mDamageImmunities.getValue();
+ }
+
+ public String addNewDamageImmunity() {
+ return Helpers.addStringToList("", mDamageImmunities);
+ }
+
+ public void removeDamageImmunity(int position) {
+ Helpers.removeFromList(mDamageImmunities, position);
+ }
+
+ public void replaceDamageImmunity(String oldDamageType, String newDamageType) {
+ Helpers.replaceItemInList(mDamageImmunities, oldDamageType, newDamageType, String::compareToIgnoreCase);
+ }
+
+ public LiveData> getDamageResistances() {
+ return mDamageResistances;
+ }
+
+ public List getDamageResistancesArray() {
+ return mDamageResistances.getValue();
+ }
+
+ public String addNewDamageResistance() {
+ return Helpers.addStringToList("", mDamageResistances);
+ }
+
+ public void removeDamageResistance(int position) {
+ Helpers.removeFromList(mDamageResistances, position);
+ }
+
+ public void replaceDamageResistance(String oldDamageType, String newDamageType) {
+ Helpers.replaceItemInList(mDamageResistances, oldDamageType, newDamageType, String::compareToIgnoreCase);
+ }
+
+ public LiveData> getDamageVulnerabilities() {
+ return mDamageVulnerabilities;
+ }
+
+ public List getDamageVulnerabilitiesArray() {
+ return mDamageVulnerabilities.getValue();
+ }
+
+ public String addNewDamageVulnerability() {
+ return Helpers.addStringToList("", mDamageVulnerabilities);
+ }
+
+ public void removeDamageVulnerability(int position) {
+ Helpers.removeFromList(mDamageVulnerabilities, position);
+ }
+
+ public void replaceDamageVulnerability(String oldDamageType, String newDamageType) {
+ Helpers.replaceItemInList(mDamageVulnerabilities, oldDamageType, newDamageType, String::compareToIgnoreCase);
+ }
+
+ public LiveData> getConditionImmunities() {
+ return mConditionImmunities;
+ }
+
+ public List getConditionImmunitiesArray() {
+ return mConditionImmunities.getValue();
+ }
+
+ public String addNewConditionImmunity() {
+ return Helpers.addStringToList("", mConditionImmunities);
+ }
+
+ public void removeConditionImmunity(int position) {
+ Helpers.removeFromList(mConditionImmunities, position);
+ }
+
+ public void replaceConditionImmunity(String oldDamageType, String newDamageType) {
+ Helpers.replaceItemInList(mConditionImmunities, oldDamageType, newDamageType, String::compareToIgnoreCase);
+ }
+
+ public LiveData> getLanguages() {
+ return mLanguages;
+ }
+
+ public List getLanguagesArray() {
+ return mLanguages.getValue();
+ }
+
+ public Language addNewLanguage() {
+ Language newLanguage = new Language("", true);
+ return Helpers.addItemToList(mLanguages, newLanguage, Language::compareTo);
+ }
+
+ public void removeLanguage(int position) {
+ Helpers.removeFromList(mLanguages, position);
+ }
+
+ public void replaceLanguage(Language oldLanguage, Language newLanguage) {
+ Helpers.replaceItemInList(mLanguages, oldLanguage, newLanguage, Language::compareTo);
+ }
+
+ public LiveData> getAbilities() {
+ return mAbilities;
+ }
+
+ public List getAbilitiesArray() {
+ return mAbilities.getValue();
+ }
+
+ public Trait addNewAbility() {
+ Trait newAbility = new Trait("", "");
+ return Helpers.addItemToList(mAbilities, newAbility, Trait::compareTo);
+ }
+
+ public void removeAbility(int position) {
+ Helpers.removeFromList(mAbilities, position);
+ }
+
+ public void replaceAbility(Trait oldAbility, Trait newAbility) {
+ Helpers.replaceItemInList(mAbilities, oldAbility, newAbility);
+ }
+
+
+ public LiveData> getActions() {
+ return mActions;
+ }
+
+ public List getActionsArray() {
+ return mActions.getValue();
+ }
+
+ public Trait addNewAction() {
+ Trait newAction = new Trait("", "");
+ return Helpers.addItemToList(mActions, newAction, Trait::compareTo);
+ }
+
+ public void removeAction(int position) {
+ Helpers.removeFromList(mActions, position);
+ }
+
+ public void replaceAction(Trait oldAction, Trait newAction) {
+ Helpers.replaceItemInList(mActions, oldAction, newAction);
+ }
+
+ public LiveData> getReactions() {
+ return mReactions;
+ }
+
+ public List getReactionsArray() {
+ return mReactions.getValue();
+ }
+
+ public Trait addNewReaction() {
+ Trait newReaction = new Trait("", "");
+ return Helpers.addItemToList(mReactions, newReaction, Trait::compareTo);
+ }
+
+ public void removeReaction(int position) {
+ Helpers.removeFromList(mReactions, position);
+ }
+
+ public void replaceReaction(Trait oldReaction, Trait newReaction) {
+ Helpers.replaceItemInList(mReactions, oldReaction, newReaction);
+ }
+
+ public LiveData> getLairActions() {
+ return mLairActions;
+ }
+
+ public List getLairActionsArray() {
+ return mLairActions.getValue();
+ }
+
+ public Trait addNewLairAction() {
+ Trait newLairAction = new Trait("", "");
+ return Helpers.addItemToList(mLairActions, newLairAction, Trait::compareTo);
+ }
+
+ public void removeLairAction(int position) {
+ Helpers.removeFromList(mLairActions, position);
+ }
+
+ public void replaceLairAction(Trait oldLairAction, Trait newLairAction) {
+ Helpers.replaceItemInList(mLairActions, oldLairAction, newLairAction);
+ }
+
+ public LiveData> getLegendaryActions() {
+ return mLegendaryActions;
+ }
+
+ public List getLegendaryActionsArray() {
+ return mLegendaryActions.getValue();
+ }
+
+ public Trait addNewLegendaryAction() {
+ Trait newLegendaryAction = new Trait("", "");
+ return Helpers.addItemToList(mLegendaryActions, newLegendaryAction, Trait::compareTo);
+ }
+
+ public void removeLegendaryAction(int position) {
+ Helpers.removeFromList(mLegendaryActions, position);
+ }
+
+ public void replaceLegendaryAction(Trait oldLegendaryAction, Trait newLegendaryAction) {
+ Helpers.replaceItemInList(mLegendaryActions, oldLegendaryAction, newLegendaryAction);
+ }
+
+ public LiveData> getRegionalActions() {
+ return mRegionalActions;
+ }
+
+ public List getRegionalActionsArray() {
+ return mRegionalActions.getValue();
+ }
+
+ public Trait addNewRegionalAction() {
+ Trait newRegionalAction = new Trait("", "");
+ return Helpers.addItemToList(mRegionalActions, newRegionalAction, Trait::compareTo);
+ }
+
+ public void removeRegionalAction(int position) {
+ Helpers.removeFromList(mRegionalActions, position);
+ }
+
+ public void replaceRegionalAction(Trait oldRegionalAction, Trait newRegionalAction) {
+ Helpers.replaceItemInList(mRegionalActions, oldRegionalAction, newRegionalAction);
+ }
public Monster buildMonster() {
Monster monster = new Monster();
@@ -813,60 +1095,99 @@ public class EditMonsterViewModel extends ViewModel {
monster.understandsButDescription = mUnderstandsButDescription.getValue();
monster.skills = new HashSet<>(mSkills.getValue());
monster.senses = new HashSet<>(mSenses.getValue());
- monster.damageImmunities = mDamageImmunities.getValue();
- monster.damageResistances = mDamageResistances.getValue();
- monster.damageVulnerabilities = mDamageVulnerabilities.getValue();
- monster.conditionImmunities = mConditionImmunities.getValue();
- monster.languages = mLanguages.getValue();
- monster.abilities = mAbilities.getValue();
- monster.actions = mActions.getValue();
- monster.reactions = mReactions.getValue();
- monster.lairActions = mLairActions.getValue();
- monster.legendaryActions = mLegendaryActions.getValue();
- monster.regionalActions = mRegionalActions.getValue();
+ monster.damageImmunities = new HashSet<>(mDamageImmunities.getValue());
+ monster.damageResistances = new HashSet<>(mDamageResistances.getValue());
+ monster.damageVulnerabilities = new HashSet<>(mDamageVulnerabilities.getValue());
+ monster.conditionImmunities = new HashSet<>(mConditionImmunities.getValue());
+ monster.languages = new HashSet<>(mLanguages.getValue());
+ monster.abilities = new HashSet<>(mAbilities.getValue());
+ monster.actions = new HashSet<>(mActions.getValue());
+ monster.reactions = new HashSet<>(mReactions.getValue());
+ monster.lairActions = new HashSet<>(mLairActions.getValue());
+ monster.legendaryActions = new HashSet<>(mLegendaryActions.getValue());
+ monster.regionalActions = new HashSet<>(mRegionalActions.getValue());
return monster;
}
- public List getSkillsArray() {
- return mSkills.getValue();
- }
-
- public Skill addNewSkill() {
- Skill newSkill = new Skill("Unnamed Skill", AbilityScore.DEXTERITY);
- ArrayList newSkills = new ArrayList<>(mSkills.getValue());
- newSkills.add(newSkill);
- Collections.sort(newSkills, (skill1, skill2) -> skill1.name.compareToIgnoreCase(skill2.name));
- mSkills.setValue(newSkills);
- return newSkill;
- }
-
- public void removeSkill(int position) {
- List skills = mSkills.getValue();
- ArrayList newSkills = new ArrayList<>(skills);
- newSkills.remove(position);
- mSkills.setValue(newSkills);
- }
-
- public void replaceSkill(Skill newSkill, Skill oldSkill) {
- List oldSkills = mSkills.getValue();
- if (oldSkills == null) {
- oldSkills = new ArrayList<>();
+ @SuppressWarnings("SameParameterValue")
+ private static class Helpers {
+ static String addStringToList(String newString, MutableLiveData> strings) {
+ return addItemToList(strings, newString, String::compareToIgnoreCase);
}
- boolean hasReplaced = false;
- ArrayList newSkills = new ArrayList<>(oldSkills.size());
- for (Skill skill : oldSkills) {
- if (Objects.equals(skill, oldSkill)) {
- newSkills.add(newSkill);
- hasReplaced = true;
- } else {
- newSkills.add(skill);
+
+ static T addItemToList(MutableLiveData> listData, T newItem, Comparator super T> comparator) {
+ ArrayList newList = new ArrayList<>(listData.getValue());
+ newList.add(newItem);
+ if (comparator != null) {
+ Collections.sort(newList, comparator);
}
+ listData.setValue(newList);
+ return newItem;
}
- if (!hasReplaced) {
- newSkills.add(newSkill);
+
+ static void removeFromList(MutableLiveData> listData, int position) {
+ List oldList = listData.getValue();
+ ArrayList newList = new ArrayList<>(oldList);
+ newList.remove(position);
+ listData.setValue(newList);
+ }
+
+ static void replaceItemInList(MutableLiveData> listData, int position, T newItem, Comparator super T> comparator) {
+ List oldList = listData.getValue();
+ if (oldList == null) {
+ oldList = new ArrayList<>();
+ }
+ int size = oldList.size();
+ boolean hasReplaced = false;
+ ArrayList newList = new ArrayList<>(size);
+ for (int index = 0; index < size; index++) {
+ if (index == position) {
+ newList.add(newItem);
+ hasReplaced = true;
+ } else {
+ newList.add(oldList.get(index));
+ }
+ }
+ if (!hasReplaced) {
+ newList.add(newItem);
+ }
+ if (comparator != null) {
+ Collections.sort(newList, comparator);
+ }
+ listData.setValue(newList);
+ }
+
+ static void replaceItemInList(MutableLiveData> listData, int position, T newItem) {
+ replaceItemInList(listData, position, newItem, null);
+ }
+
+ static void replaceItemInList(MutableLiveData> listData, T oldItem, T newItem, Comparator super T> comparator) {
+ List oldList = listData.getValue();
+ if (oldList == null) {
+ oldList = new ArrayList<>();
+ }
+ boolean hasReplaced = false;
+ ArrayList newList = new ArrayList<>(oldList.size());
+ for (T item : oldList) {
+ if (Objects.equals(item, oldItem)) {
+ newList.add(newItem);
+ hasReplaced = true;
+ } else {
+ newList.add(item);
+ }
+ }
+ if (!hasReplaced) {
+ newList.add(newItem);
+ }
+ if (comparator != null) {
+ Collections.sort(newList, comparator);
+ }
+ listData.setValue(newList);
+ }
+
+ static void replaceItemInList(MutableLiveData> listData, T oldItem, T newItem) {
+ replaceItemInList(listData, oldItem, newItem, null);
}
- Collections.sort(newSkills, (skill1, skill2) -> skill1.name.compareToIgnoreCase(skill2.name));
- mSkills.setValue(newSkills);
}
}
diff --git a/Android/app/src/main/java/com/majinnaibu/monstercards/ui/editmonster/EditSavingThrowsFragment.java b/Android/app/src/main/java/com/majinnaibu/monstercards/ui/editmonster/EditSavingThrowsFragment.java
index c1a0f76..e66fe9d 100644
--- a/Android/app/src/main/java/com/majinnaibu/monstercards/ui/editmonster/EditSavingThrowsFragment.java
+++ b/Android/app/src/main/java/com/majinnaibu/monstercards/ui/editmonster/EditSavingThrowsFragment.java
@@ -14,6 +14,7 @@ import androidx.navigation.Navigation;
import com.majinnaibu.monstercards.R;
import com.majinnaibu.monstercards.ui.components.AdvantagePicker;
import com.majinnaibu.monstercards.ui.components.ProficiencyPicker;
+import com.majinnaibu.monstercards.ui.shared.MCFragment;
public class EditSavingThrowsFragment extends Fragment {
private EditMonsterViewModel mViewModel;
diff --git a/Android/app/src/main/java/com/majinnaibu/monstercards/ui/editmonster/EditSenseFragment.java b/Android/app/src/main/java/com/majinnaibu/monstercards/ui/editmonster/EditSenseFragment.java
new file mode 100644
index 0000000..4d99588
--- /dev/null
+++ b/Android/app/src/main/java/com/majinnaibu/monstercards/ui/editmonster/EditSenseFragment.java
@@ -0,0 +1,77 @@
+package com.majinnaibu.monstercards.ui.editmonster;
+
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.EditText;
+
+import androidx.activity.OnBackPressedCallback;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.lifecycle.ViewModelProvider;
+import androidx.navigation.NavBackStackEntry;
+import androidx.navigation.NavController;
+import androidx.navigation.Navigation;
+
+import com.majinnaibu.monstercards.R;
+import com.majinnaibu.monstercards.ui.shared.MCFragment;
+import com.majinnaibu.monstercards.utils.Logger;
+import com.majinnaibu.monstercards.utils.TextChangedListener;
+
+public class EditSenseFragment extends MCFragment {
+ private EditMonsterViewModel mEditMonsterViewModel;
+ private EditStringViewModel mViewModel;
+ private ViewHolder mHolder;
+ private String mOldSense;
+
+ @Override
+ public void onCreate(@Nullable Bundle savedInstanceState) {
+ mViewModel = new ViewModelProvider(this).get(EditStringViewModel.class);
+ if (getArguments() != null) {
+ EditSenseFragmentArgs args = EditSenseFragmentArgs.fromBundle(getArguments());
+ mOldSense = args.getSense();
+ mViewModel.resetValue(mOldSense);
+ } else {
+ Logger.logWTF("EditSenseFragment needs arguments");
+ mOldSense = null;
+ }
+ super.onCreate(savedInstanceState);
+ }
+
+ @Override
+ public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
+ @Nullable Bundle savedInstanceState) {
+ NavController navController = Navigation.findNavController(requireActivity(), R.id.nav_host_fragment);
+ NavBackStackEntry backStackEntry = navController.getBackStackEntry(R.id.edit_monster_navigation);
+ mEditMonsterViewModel = new ViewModelProvider(backStackEntry).get(EditMonsterViewModel.class);
+
+ View root = inflater.inflate(R.layout.fragment_edit_sense, container, false);
+
+ mHolder = new ViewHolder(root);
+
+ mHolder.description.setText(mViewModel.getValueAsString());
+ mHolder.description.addTextChangedListener(new TextChangedListener((TextChangedListener.OnTextChangedCallback) (s, start, before, count) -> mViewModel.setValue(s.toString())));
+
+ requireActivity().getOnBackPressedDispatcher().addCallback(getViewLifecycleOwner(), new OnBackPressedCallback(true) {
+ @Override
+ public void handleOnBackPressed() {
+ if (mViewModel.hasChanges()) {
+ mEditMonsterViewModel.replaceSense(mOldSense, mViewModel.getValueAsString());
+ }
+ Navigation.findNavController(requireView()).navigateUp();
+ }
+ });
+
+ return root;
+ }
+
+ private static class ViewHolder {
+ EditText description;
+
+ ViewHolder(View root) {
+ description = root.findViewById(R.id.name);
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/Android/app/src/main/java/com/majinnaibu/monstercards/ui/editmonster/EditSensesFragment.java b/Android/app/src/main/java/com/majinnaibu/monstercards/ui/editmonster/EditSensesFragment.java
new file mode 100644
index 0000000..5c7482a
--- /dev/null
+++ b/Android/app/src/main/java/com/majinnaibu/monstercards/ui/editmonster/EditSensesFragment.java
@@ -0,0 +1,92 @@
+package com.majinnaibu.monstercards.ui.editmonster;
+
+import android.content.Context;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import androidx.annotation.NonNull;
+import androidx.lifecycle.ViewModelProvider;
+import androidx.navigation.NavBackStackEntry;
+import androidx.navigation.NavController;
+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.majinnaibu.monstercards.R;
+import com.majinnaibu.monstercards.ui.shared.MCFragment;
+import com.majinnaibu.monstercards.ui.shared.SwipeToDeleteCallback;
+import com.majinnaibu.monstercards.utils.Logger;
+
+/**
+ * A fragment representing a list of Items.
+ */
+public class EditSensesFragment extends MCFragment {
+ private EditMonsterViewModel mViewModel;
+ private ViewHolder mHolder;
+
+ private void navigateToEditSense(String sense) {
+ NavDirections action = EditSensesFragmentDirections.actionEditSensesFragmentToEditSenseFragment(sense);
+ View view = getView();
+ assert view != null;
+ Navigation.findNavController(view).navigate(action);
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ NavController navController = Navigation.findNavController(requireActivity(), R.id.nav_host_fragment);
+ NavBackStackEntry backStackEntry = navController.getBackStackEntry(R.id.edit_monster_navigation);
+ mViewModel = new ViewModelProvider(backStackEntry).get(EditMonsterViewModel.class);
+ View root = inflater.inflate(R.layout.fragment_edit_senses_list, container, false);
+ mHolder = new ViewHolder(root);
+ setupRecyclerView(mHolder.list);
+ setupAddSenseButton(mHolder.addSense);
+ return root;
+ }
+
+ private void setupRecyclerView(@NonNull RecyclerView recyclerView) {
+ Context context = requireContext();
+ LinearLayoutManager layoutManager = new LinearLayoutManager(context);
+ recyclerView.setLayoutManager(layoutManager);
+
+ mViewModel.getSenses().observe(getViewLifecycleOwner(), senses -> {
+ EditSensesRecyclerViewAdapter adapter = new EditSensesRecyclerViewAdapter(mViewModel.getSensesArray(), sense -> {
+ if (sense != null) {
+ navigateToEditSense(sense);
+ } else {
+ Logger.logError("Can't navigate to EditSense with a null sense");
+ }
+ });
+ recyclerView.setAdapter(adapter);
+ });
+
+ DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(context, layoutManager.getOrientation());
+ recyclerView.addItemDecoration(dividerItemDecoration);
+
+ ItemTouchHelper itemTouchHelper = new ItemTouchHelper(new SwipeToDeleteCallback(context, mViewModel::removeSense));
+ itemTouchHelper.attachToRecyclerView(recyclerView);
+ }
+
+ private void setupAddSenseButton(@NonNull FloatingActionButton fab) {
+ fab.setOnClickListener(view -> {
+ String newSense = mViewModel.addNewSense();
+ navigateToEditSense(newSense);
+ });
+ }
+
+ private static class ViewHolder {
+ RecyclerView list;
+ FloatingActionButton addSense;
+
+ ViewHolder(View root) {
+ list = root.findViewById(R.id.list);
+ addSense = root.findViewById(R.id.add_sense);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Android/app/src/main/java/com/majinnaibu/monstercards/ui/editmonster/EditSkillFragment.java b/Android/app/src/main/java/com/majinnaibu/monstercards/ui/editmonster/EditSkillFragment.java
index 1eb08dc..c744460 100644
--- a/Android/app/src/main/java/com/majinnaibu/monstercards/ui/editmonster/EditSkillFragment.java
+++ b/Android/app/src/main/java/com/majinnaibu/monstercards/ui/editmonster/EditSkillFragment.java
@@ -20,6 +20,7 @@ import com.majinnaibu.monstercards.models.Skill;
import com.majinnaibu.monstercards.ui.components.AbilityScorePicker;
import com.majinnaibu.monstercards.ui.components.AdvantagePicker;
import com.majinnaibu.monstercards.ui.components.ProficiencyPicker;
+import com.majinnaibu.monstercards.ui.shared.MCFragment;
import com.majinnaibu.monstercards.utils.Logger;
import com.majinnaibu.monstercards.utils.TextChangedListener;
@@ -37,7 +38,7 @@ public class EditSkillFragment extends Fragment {
mViewModel.copyFromSkill(args.getName(), args.getAbilityScore(), args.getProficiency(), args.getAdvantage());
mOldSkill = new Skill(args.getName(), args.getAbilityScore(), args.getAdvantage(), args.getProficiency());
} else {
- Logger.logWTF("This should never happen. EditSkillFragment needs arguments.");
+ Logger.logWTF("EditSkillFragment needs arguments.");
mOldSkill = null;
}
super.onCreate(savedInstanceState);
diff --git a/Android/app/src/main/java/com/majinnaibu/monstercards/ui/editmonster/EditSkillViewModel.java b/Android/app/src/main/java/com/majinnaibu/monstercards/ui/editmonster/EditSkillViewModel.java
index 1d33390..6af3d26 100644
--- a/Android/app/src/main/java/com/majinnaibu/monstercards/ui/editmonster/EditSkillViewModel.java
+++ b/Android/app/src/main/java/com/majinnaibu/monstercards/ui/editmonster/EditSkillViewModel.java
@@ -1,43 +1,28 @@
package com.majinnaibu.monstercards.ui.editmonster;
import androidx.lifecycle.LiveData;
-import androidx.lifecycle.MutableLiveData;
-import androidx.lifecycle.ViewModel;
import com.majinnaibu.monstercards.data.enums.AbilityScore;
import com.majinnaibu.monstercards.data.enums.AdvantageType;
import com.majinnaibu.monstercards.data.enums.ProficiencyType;
import com.majinnaibu.monstercards.models.Skill;
+import com.majinnaibu.monstercards.ui.shared.ChangeTrackedViewModel;
import com.majinnaibu.monstercards.utils.ChangeTrackedLiveData;
-public class EditSkillViewModel extends ViewModel {
+public class EditSkillViewModel extends ChangeTrackedViewModel {
private final ChangeTrackedLiveData mAbilityScore;
private final ChangeTrackedLiveData mAdvantageType;
- private final MutableLiveData mHasChanges;
private final ChangeTrackedLiveData mProficiencyType;
private final ChangeTrackedLiveData mName;
private final ChangeTrackedLiveData mSkill;
public EditSkillViewModel() {
- mHasChanges = new MutableLiveData<>(false);
- ChangeTrackedLiveData.OnValueDirtiedCallback onDirtied = () -> mHasChanges.setValue(true);
-
- mAbilityScore = new ChangeTrackedLiveData<>(AbilityScore.STRENGTH, onDirtied);
- mAdvantageType = new ChangeTrackedLiveData<>(AdvantageType.NONE, onDirtied);
- mProficiencyType = new ChangeTrackedLiveData<>(ProficiencyType.NONE, onDirtied);
- mName = new ChangeTrackedLiveData<>("Unknown Skill", onDirtied);
- mSkill = new ChangeTrackedLiveData<>(makeSkill(), onDirtied);
- }
-
- public EditSkillViewModel(Skill skill) {
- mHasChanges = new MutableLiveData<>(false);
- ChangeTrackedLiveData.OnValueDirtiedCallback onDirtied = () -> mHasChanges.setValue(true);
-
- mAbilityScore = new ChangeTrackedLiveData<>(skill.abilityScore, onDirtied);
- mAdvantageType = new ChangeTrackedLiveData<>(skill.advantageType, onDirtied);
- mProficiencyType = new ChangeTrackedLiveData<>(skill.proficiencyType, onDirtied);
- mName = new ChangeTrackedLiveData<>(skill.name, onDirtied);
- mSkill = new ChangeTrackedLiveData<>(makeSkill(), onDirtied);
+ super();
+ mAbilityScore = new ChangeTrackedLiveData<>(AbilityScore.STRENGTH, this::makeDirty);
+ mAdvantageType = new ChangeTrackedLiveData<>(AdvantageType.NONE, this::makeDirty);
+ mProficiencyType = new ChangeTrackedLiveData<>(ProficiencyType.NONE, this::makeDirty);
+ mName = new ChangeTrackedLiveData<>("Unknown Skill", this::makeDirty);
+ mSkill = new ChangeTrackedLiveData<>(makeSkill(), this::makeDirty);
}
public void copyFromSkill(Skill skill) {
@@ -47,13 +32,6 @@ public class EditSkillViewModel extends ViewModel {
mName.resetValue(skill.name);
}
- public void copyFromSkill(String name, AbilityScore abilityScore, ProficiencyType proficiency, AdvantageType advantage) {
- mAbilityScore.resetValue(abilityScore);
- mAdvantageType.resetValue(advantage);
- mProficiencyType.resetValue(proficiency);
- mName.resetValue(name);
- }
-
public LiveData getSkill() {
return mSkill;
}
@@ -94,14 +72,6 @@ public class EditSkillViewModel extends ViewModel {
mSkill.setValue(makeSkill());
}
- public LiveData getHasChanges() {
- return mHasChanges;
- }
-
- public boolean hasChanges() {
- return mHasChanges.getValue();
- }
-
private Skill makeSkill() {
return new Skill(mName.getValue(), mAbilityScore.getValue(), mAdvantageType.getValue(), mProficiencyType.getValue());
}
diff --git a/Android/app/src/main/java/com/majinnaibu/monstercards/ui/editmonster/EditSkillsFragment.java b/Android/app/src/main/java/com/majinnaibu/monstercards/ui/editmonster/EditSkillsFragment.java
index 13de066..608896f 100644
--- a/Android/app/src/main/java/com/majinnaibu/monstercards/ui/editmonster/EditSkillsFragment.java
+++ b/Android/app/src/main/java/com/majinnaibu/monstercards/ui/editmonster/EditSkillsFragment.java
@@ -7,7 +7,6 @@ import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
-import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;
import androidx.navigation.NavBackStackEntry;
import androidx.navigation.NavController;
@@ -21,14 +20,14 @@ import androidx.recyclerview.widget.RecyclerView;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.majinnaibu.monstercards.R;
import com.majinnaibu.monstercards.models.Skill;
+import com.majinnaibu.monstercards.ui.shared.MCFragment;
import com.majinnaibu.monstercards.ui.shared.SwipeToDeleteCallback;
import com.majinnaibu.monstercards.utils.Logger;
/**
* A fragment representing a list of Items.
*/
-@SuppressWarnings("FieldCanBeLocal")
-public class EditSkillsFragment extends Fragment {
+public class EditSkillsFragment extends MCFragment {
private EditMonsterViewModel mViewModel;
private ViewHolder mHolder;
@@ -67,7 +66,7 @@ public class EditSkillsFragment extends Fragment {
} else {
Logger.logError("Can't navigate to EditSkill with a null skill");
}
- }, null);
+ });
recyclerView.setAdapter(adapter);
});
diff --git a/Android/app/src/main/java/com/majinnaibu/monstercards/ui/editmonster/EditSpeedFragment.java b/Android/app/src/main/java/com/majinnaibu/monstercards/ui/editmonster/EditSpeedFragment.java
index 0cf820e..8d53f8a 100644
--- a/Android/app/src/main/java/com/majinnaibu/monstercards/ui/editmonster/EditSpeedFragment.java
+++ b/Android/app/src/main/java/com/majinnaibu/monstercards/ui/editmonster/EditSpeedFragment.java
@@ -15,6 +15,7 @@ import androidx.navigation.Navigation;
import com.majinnaibu.monstercards.R;
import com.majinnaibu.monstercards.ui.components.Stepper;
+import com.majinnaibu.monstercards.ui.shared.MCFragment;
import com.majinnaibu.monstercards.utils.TextChangedListener;
public class EditSpeedFragment extends Fragment {
diff --git a/Android/app/src/main/java/com/majinnaibu/monstercards/ui/editmonster/EditStringFragment.java b/Android/app/src/main/java/com/majinnaibu/monstercards/ui/editmonster/EditStringFragment.java
index 54e4ee4..4a37439 100644
--- a/Android/app/src/main/java/com/majinnaibu/monstercards/ui/editmonster/EditStringFragment.java
+++ b/Android/app/src/main/java/com/majinnaibu/monstercards/ui/editmonster/EditStringFragment.java
@@ -9,49 +9,45 @@ import android.widget.EditText;
import androidx.activity.OnBackPressedCallback;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;
import androidx.navigation.NavBackStackEntry;
import androidx.navigation.NavController;
import androidx.navigation.Navigation;
import com.majinnaibu.monstercards.R;
-import com.majinnaibu.monstercards.data.enums.StringType;
-import com.majinnaibu.monstercards.ui.shared.MCFragment;
import com.majinnaibu.monstercards.utils.Logger;
import com.majinnaibu.monstercards.utils.TextChangedListener;
-public class EditStringFragment extends MCFragment {
+public class EditConditionImmunityFragment extends Fragment {
private EditMonsterViewModel mEditMonsterViewModel;
private EditStringViewModel mViewModel;
private ViewHolder mHolder;
private String mOldValue;
- private StringType mStringType;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
mViewModel = new ViewModelProvider(this).get(EditStringViewModel.class);
if (getArguments() != null) {
- EditStringFragmentArgs args = EditStringFragmentArgs.fromBundle(getArguments());
- mOldValue = args.getValue();
- mViewModel.setValue(mOldValue);
- mStringType = args.getStringType();
+ EditConditionImmunityFragmentArgs args = EditConditionImmunityFragmentArgs.fromBundle(getArguments());
+ mOldValue = args.getCondition();
+ mViewModel.resetValue(mOldValue);
} else {
- Logger.logWTF("EditStringFragment needs arguments");
+ Logger.logWTF("EditConditionImmunityFragment needs arguments");
mOldValue = null;
}
+
super.onCreate(savedInstanceState);
}
- @Nullable
@Override
- public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
+ public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
+ @Nullable Bundle savedInstanceState) {
NavController navController = Navigation.findNavController(requireActivity(), R.id.nav_host_fragment);
NavBackStackEntry backStackEntry = navController.getBackStackEntry(R.id.edit_monster_navigation);
mEditMonsterViewModel = new ViewModelProvider(backStackEntry).get(EditMonsterViewModel.class);
- View root = inflater.inflate(R.layout.fragment_edit_string, container, false);
+ View root = inflater.inflate(R.layout.fragment_edit_condition_immunity, container, false);
mHolder = new ViewHolder(root);
- setTitle(getTitleForStringType(mStringType));
-
mHolder.description.setText(mViewModel.getValueAsString());
mHolder.description.addTextChangedListener(new TextChangedListener((TextChangedListener.OnTextChangedCallback) (s, start, before, count) -> mViewModel.setValue(s.toString())));
@@ -59,7 +55,7 @@ public class EditStringFragment extends MCFragment {
@Override
public void handleOnBackPressed() {
if (mViewModel.hasChanges()) {
- mEditMonsterViewModel.replaceString(mStringType, mOldValue, mViewModel.getValueAsString());
+ mEditMonsterViewModel.replaceConditionImmunity(mOldValue, mViewModel.getValueAsString());
}
Navigation.findNavController(requireView()).navigateUp();
}
@@ -68,35 +64,11 @@ public class EditStringFragment extends MCFragment {
return root;
}
- @NonNull
- private String getTitleForStringType(@NonNull StringType type) {
- switch (type) {
- case CONDITION_IMMUNITY:
- return getString(R.string.title_editConditionImmunity);
- case DAMAGE_IMMUNITY:
- return getString(R.string.title_editDamageImmunity);
- case DAMAGE_RESISTANCE:
- return getString(R.string.title_editDamageResistance);
- case DAMAGE_VULNERABILITY:
- return getString(R.string.title_editDamageVulnerability);
- case SENSE:
- return getString(R.string.title_editSense);
- default:
- return getString(R.string.title_editString);
- }
- }
-
- @Override
- public void onStart() {
- super.onStart();
- mHolder.description.requestFocus();
- }
-
private static class ViewHolder {
EditText description;
- ViewHolder(@NonNull View root) {
+ ViewHolder(View root) {
description = root.findViewById(R.id.description);
}
}
-}
+}
\ No newline at end of file
diff --git a/Android/app/src/main/java/com/majinnaibu/monstercards/ui/editmonster/EditStringsRecyclerViewAdapter.java b/Android/app/src/main/java/com/majinnaibu/monstercards/ui/editmonster/EditStringsRecyclerViewAdapter.java
index fda532c..a0cc370 100644
--- a/Android/app/src/main/java/com/majinnaibu/monstercards/ui/editmonster/EditStringsRecyclerViewAdapter.java
+++ b/Android/app/src/main/java/com/majinnaibu/monstercards/ui/editmonster/EditStringsRecyclerViewAdapter.java
@@ -4,30 +4,34 @@ import android.view.LayoutInflater;
import android.view.ViewGroup;
import android.widget.TextView;
-import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
-import com.majinnaibu.monstercards.databinding.FragmentEditStringsListItemBinding;
+import com.majinnaibu.monstercards.databinding.FragmentEditConditionImmunitiesListItemBinding;
+
+import org.jetbrains.annotations.NotNull;
import java.util.List;
-public class EditStringsRecyclerViewAdapter extends RecyclerView.Adapter {
+/**
+ * {@link RecyclerView.Adapter} that can display a {@link String}.
+ */
+public class EditConditionImmunitiesRecyclerViewAdapter extends RecyclerView.Adapter {
private final List mValues;
private final ItemCallback mOnClick;
- public EditStringsRecyclerViewAdapter(List items, ItemCallback onClick) {
+ public EditConditionImmunitiesRecyclerViewAdapter(List items, ItemCallback onClick) {
mValues = items;
mOnClick = onClick;
}
- @NonNull
+ @NotNull
@Override
- public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
- return new ViewHolder(FragmentEditStringsListItemBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false));
+ public ViewHolder onCreateViewHolder(@NotNull ViewGroup parent, int viewType) {
+ return new ViewHolder(FragmentEditConditionImmunitiesListItemBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false));
}
@Override
- public void onBindViewHolder(@NonNull final ViewHolder holder, int position) {
+ public void onBindViewHolder(final ViewHolder holder, int position) {
holder.mItem = mValues.get(position);
holder.mContentView.setText(mValues.get(position));
holder.itemView.setOnClickListener(v -> {
@@ -43,22 +47,22 @@ public class EditStringsRecyclerViewAdapter extends RecyclerView.Adapter {
- repository
- .deleteMonster(monster)
- .subscribeOn(Schedulers.io())
- .observeOn(AndroidSchedulers.mainThread())
- .subscribe(() -> {
- Logger.logDebug("deleted");
- }, Logger::logError);
- },
- mTwoPane);
+ (monster) -> navigateToMonsterDetail(monster.id),
+ (monster) -> repository
+ .deleteMonster(monster)
+ .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);
- recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
- ItemTouchHelper itemTouchHelper = new ItemTouchHelper(new SwipeToDeleteCallback(getContext(), (position) -> {
- adapter.deleteItem(position);
- }));
+
+ LinearLayoutManager layoutManager = new LinearLayoutManager(context);
+ recyclerView.setLayoutManager(layoutManager);
+
+ DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(context, layoutManager.getOrientation());
+ recyclerView.addItemDecoration(dividerItemDecoration);
+
+ ItemTouchHelper itemTouchHelper = new ItemTouchHelper(new SwipeToDeleteCallback(requireContext(), adapter::deleteItem));
itemTouchHelper.attachToRecyclerView(recyclerView);
}
private void setupAddMonsterButton(@NonNull FloatingActionButton fab) {
fab.setOnClickListener(view -> {
Monster monster = new Monster();
- monster.name = "Unnamed Monster";
+ monster.name = getString(R.string.default_monster_name);
MonsterRepository repository = this.getMonsterRepository();
repository.addMonster(monster)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
- .subscribe(() -> {
- Snackbar.make(
- getView(),
- String.format("%s created", monster.name),
- Snackbar.LENGTH_LONG)
- .setAction("Action", (_view) -> {
- navigateToMonsterDetail(monster.id);
- })
- .show();
- }, throwable -> {
- Logger.logError("Error creating monster", throwable);
- Snackbar.make(getView(), "Failed to create monster", Snackbar.LENGTH_LONG)
- .setAction("Action", null).show();
- });
- });
+ .subscribe(
+ new DisposableCompletableObserver() {
+ @Override
+ public void onComplete() {
+ View view = getView();
+ assert view != null;
+ Snackbar.make(
+ view,
+ getString(R.string.snackbar_monster_created, monster.name),
+ Snackbar.LENGTH_LONG)
+ .setAction("Action", (_view) -> navigateToMonsterDetail(monster.id))
+ .show();
+ }
+ @Override
+ public void onError(@io.reactivex.rxjava3.annotations.NonNull Throwable e) {
+ Logger.logError("Error creating monster", e);
+ View view = getView();
+ assert view != null;
+ Snackbar.make(view, getString(R.string.snackbar_failed_to_create_monster), Snackbar.LENGTH_LONG)
+ .setAction("Action", null).show();
+ }
+ });
+ });
}
protected void navigateToMonsterDetail(UUID monsterId) {
NavDirections action = LibraryFragmentDirections.actionNavigationLibraryToNavigationMonster(monsterId.toString());
- Navigation.findNavController(getView()).navigate(action);
+ View view = getView();
+ assert view != null;
+ Navigation.findNavController(view).navigate(action);
}
}
diff --git a/Android/app/src/main/java/com/majinnaibu/monstercards/ui/monster/MonsterDetailFragment.java b/Android/app/src/main/java/com/majinnaibu/monstercards/ui/monster/MonsterDetailFragment.java
index 32145c1..cf0031d 100644
--- a/Android/app/src/main/java/com/majinnaibu/monstercards/ui/monster/MonsterDetailFragment.java
+++ b/Android/app/src/main/java/com/majinnaibu/monstercards/ui/monster/MonsterDetailFragment.java
@@ -26,7 +26,7 @@ import com.majinnaibu.monstercards.data.MonsterRepository;
import com.majinnaibu.monstercards.helpers.CommonMarkHelper;
import com.majinnaibu.monstercards.helpers.StringHelper;
import com.majinnaibu.monstercards.models.Monster;
-import com.majinnaibu.monstercards.ui.MCFragment;
+import com.majinnaibu.monstercards.ui.shared.MCFragment;
import com.majinnaibu.monstercards.utils.Logger;
import java.util.UUID;
@@ -241,10 +241,15 @@ public class MonsterDetailFragment extends MCFragment {
@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
if (item.getItemId() == R.id.menu_action_edit_monster) {
- NavDirections action = MonsterDetailFragmentDirections.actionNavigationMonsterToEditMonsterFragment(monsterDetailViewModel.getId().toString());
- View view = getView();
- assert view != null;
- Navigation.findNavController(view).navigate(action);
+ UUID monsterId = monsterDetailViewModel.getId().getValue();
+ if (monsterId != null) {
+ NavDirections action = MonsterDetailFragmentDirections.actionNavigationMonsterToEditMonsterFragment(monsterId.toString());
+ View view = getView();
+ assert view != null;
+ Navigation.findNavController(view).navigate(action);
+ } else {
+ Logger.logWTF("monsterId cannot be null.");
+ }
return true;
}
return super.onOptionsItemSelected(item);
diff --git a/Android/app/src/main/java/com/majinnaibu/monstercards/ui/search/SearchFragment.java b/Android/app/src/main/java/com/majinnaibu/monstercards/ui/search/SearchFragment.java
index b25276c..12ab602 100644
--- a/Android/app/src/main/java/com/majinnaibu/monstercards/ui/search/SearchFragment.java
+++ b/Android/app/src/main/java/com/majinnaibu/monstercards/ui/search/SearchFragment.java
@@ -14,12 +14,10 @@ import androidx.recyclerview.widget.RecyclerView;
import com.majinnaibu.monstercards.R;
import com.majinnaibu.monstercards.data.MonsterRepository;
-import com.majinnaibu.monstercards.ui.MCFragment;
+import com.majinnaibu.monstercards.ui.shared.MCFragment;
public class SearchFragment extends MCFragment {
- private SearchViewModel searchViewModel;
-
public View onCreateView(@NonNull LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.fragment_search, container, false);
diff --git a/Android/app/src/main/java/com/majinnaibu/monstercards/ui/search/SearchResultsRecyclerViewAdapter.java b/Android/app/src/main/java/com/majinnaibu/monstercards/ui/search/SearchResultsRecyclerViewAdapter.java
index c437486..c9f62e2 100644
--- a/Android/app/src/main/java/com/majinnaibu/monstercards/ui/search/SearchResultsRecyclerViewAdapter.java
+++ b/Android/app/src/main/java/com/majinnaibu/monstercards/ui/search/SearchResultsRecyclerViewAdapter.java
@@ -13,6 +13,8 @@ import com.majinnaibu.monstercards.data.MonsterRepository;
import com.majinnaibu.monstercards.models.Monster;
import com.majinnaibu.monstercards.utils.Logger;
+import org.jetbrains.annotations.NotNull;
+
import java.util.ArrayList;
import java.util.List;
@@ -20,16 +22,11 @@ import io.reactivex.rxjava3.core.Flowable;
import io.reactivex.rxjava3.disposables.Disposable;
public class SearchResultsRecyclerViewAdapter extends RecyclerView.Adapter {
- public interface ItemCallback {
- void onItem(Monster monster);
- }
-
private final MonsterRepository mRepository;
+ private final ItemCallback mOnClickHandler;
private String mSearchText;
private List mValues;
private Disposable mSubscriptionHandler;
- private final ItemCallback mOnClickHandler;
-
public SearchResultsRecyclerViewAdapter(MonsterRepository repository,
ItemCallback onClick) {
mRepository = repository;
@@ -54,6 +51,7 @@ public class SearchResultsRecyclerViewAdapter extends RecyclerView.Adapter Logger.logError("Error performing search", throwable));
}
+ @NotNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
@@ -79,7 +77,11 @@ public class SearchResultsRecyclerViewAdapter extends RecyclerView.Adapter