ViewModel refactoring.
This commit is contained in:
		| @@ -1,6 +1,7 @@ | |||||||
| <component name="InspectionProjectProfileManager"> | <component name="InspectionProjectProfileManager"> | ||||||
|   <profile version="1.0"> |   <profile version="1.0"> | ||||||
|     <option name="myName" value="Project Default" /> |     <option name="myName" value="Project Default" /> | ||||||
|  |     <inspection_tool class="FieldCanBeLocal" enabled="false" level="WARNING" enabled_by_default="false" /> | ||||||
|     <inspection_tool class="TrivialIf" enabled="false" level="WARNING" enabled_by_default="false" /> |     <inspection_tool class="TrivialIf" enabled="false" level="WARNING" enabled_by_default="false" /> | ||||||
|   </profile> |   </profile> | ||||||
| </component> | </component> | ||||||
| @@ -1,35 +0,0 @@ | |||||||
| package com.majinnaibu.monstercards.ui; |  | ||||||
|  |  | ||||||
| import android.app.Activity; |  | ||||||
|  |  | ||||||
| import androidx.appcompat.app.ActionBar; |  | ||||||
| import androidx.appcompat.app.AppCompatActivity; |  | ||||||
| import androidx.fragment.app.Fragment; |  | ||||||
|  |  | ||||||
| import com.majinnaibu.monstercards.MonsterCardsApplication; |  | ||||||
| import com.majinnaibu.monstercards.data.MonsterRepository; |  | ||||||
|  |  | ||||||
| public class MCFragment extends Fragment { |  | ||||||
|     public MonsterCardsApplication getApplication() { |  | ||||||
|         return (MonsterCardsApplication) this.getActivity().getApplication(); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     protected MonsterRepository getMonsterRepository() { |  | ||||||
|         return this.getApplication().getMonsterRepository(); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     public AppCompatActivity requireAppCompatActivity() { |  | ||||||
|         return (AppCompatActivity) requireActivity(); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     public void setTitle(CharSequence title) { |  | ||||||
|         Activity activity = requireActivity(); |  | ||||||
|         if (activity instanceof AppCompatActivity) { |  | ||||||
|             AppCompatActivity appCompatActivity = (AppCompatActivity) activity; |  | ||||||
|             ActionBar supportActionBar = appCompatActivity.getSupportActionBar(); |  | ||||||
|             if (supportActionBar != null) { |  | ||||||
|                 supportActionBar.setTitle(title); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @@ -12,7 +12,7 @@ import androidx.lifecycle.Observer; | |||||||
| import androidx.lifecycle.ViewModelProvider; | import androidx.lifecycle.ViewModelProvider; | ||||||
|  |  | ||||||
| import com.majinnaibu.monstercards.R; | import com.majinnaibu.monstercards.R; | ||||||
| import com.majinnaibu.monstercards.ui.MCFragment; | import com.majinnaibu.monstercards.ui.shared.MCFragment; | ||||||
|  |  | ||||||
| public class CollectionsFragment extends MCFragment { | public class CollectionsFragment extends MCFragment { | ||||||
|  |  | ||||||
|   | |||||||
| @@ -7,12 +7,10 @@ import android.view.ViewGroup; | |||||||
| import android.widget.TextView; | import android.widget.TextView; | ||||||
|  |  | ||||||
| import androidx.annotation.NonNull; | import androidx.annotation.NonNull; | ||||||
| import androidx.annotation.Nullable; |  | ||||||
| import androidx.lifecycle.Observer; |  | ||||||
| import androidx.lifecycle.ViewModelProvider; | import androidx.lifecycle.ViewModelProvider; | ||||||
|  |  | ||||||
| import com.majinnaibu.monstercards.R; | import com.majinnaibu.monstercards.R; | ||||||
| import com.majinnaibu.monstercards.ui.MCFragment; | import com.majinnaibu.monstercards.ui.shared.MCFragment; | ||||||
|  |  | ||||||
| public class DashboardFragment extends MCFragment { | public class DashboardFragment extends MCFragment { | ||||||
|  |  | ||||||
| @@ -23,12 +21,7 @@ public class DashboardFragment extends MCFragment { | |||||||
|         dashboardViewModel = new ViewModelProvider(this).get(DashboardViewModel.class); |         dashboardViewModel = new ViewModelProvider(this).get(DashboardViewModel.class); | ||||||
|         View root = inflater.inflate(R.layout.fragment_dashboard, container, false); |         View root = inflater.inflate(R.layout.fragment_dashboard, container, false); | ||||||
|         final TextView textView = root.findViewById(R.id.text_dashboard); |         final TextView textView = root.findViewById(R.id.text_dashboard); | ||||||
|         dashboardViewModel.getText().observe(getViewLifecycleOwner(), new Observer<String>() { |         dashboardViewModel.getText().observe(getViewLifecycleOwner(), textView::setText); | ||||||
|             @Override |  | ||||||
|             public void onChanged(@Nullable String s) { |  | ||||||
|                 textView.setText(s); |  | ||||||
|             } |  | ||||||
|         }); |  | ||||||
|         return root; |         return root; | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -5,8 +5,7 @@ import androidx.lifecycle.MutableLiveData; | |||||||
| import androidx.lifecycle.ViewModel; | import androidx.lifecycle.ViewModel; | ||||||
|  |  | ||||||
| public class DashboardViewModel extends ViewModel { | public class DashboardViewModel extends ViewModel { | ||||||
|  |     private final MutableLiveData<String> mText; | ||||||
|     private MutableLiveData<String> mText; |  | ||||||
|  |  | ||||||
|     public DashboardViewModel() { |     public DashboardViewModel() { | ||||||
|         mText = new MutableLiveData<>(); |         mText = new MutableLiveData<>(); | ||||||
|   | |||||||
| @@ -11,8 +11,8 @@ import androidx.navigation.NavController; | |||||||
| import androidx.navigation.Navigation; | import androidx.navigation.Navigation; | ||||||
|  |  | ||||||
| import com.majinnaibu.monstercards.R; | import com.majinnaibu.monstercards.R; | ||||||
| import com.majinnaibu.monstercards.ui.MCFragment; |  | ||||||
| import com.majinnaibu.monstercards.ui.components.Stepper; | import com.majinnaibu.monstercards.ui.components.Stepper; | ||||||
|  | import com.majinnaibu.monstercards.ui.shared.MCFragment; | ||||||
|  |  | ||||||
| public class EditAbilityScoresFragment extends MCFragment { | public class EditAbilityScoresFragment extends MCFragment { | ||||||
|     private final String ABILITY_SCORE_FORMAT = "%d (%+d)"; |     private final String ABILITY_SCORE_FORMAT = "%d (%+d)"; | ||||||
|   | |||||||
| @@ -21,10 +21,9 @@ import androidx.navigation.Navigation; | |||||||
| import com.majinnaibu.monstercards.R; | import com.majinnaibu.monstercards.R; | ||||||
| import com.majinnaibu.monstercards.data.enums.ArmorType; | import com.majinnaibu.monstercards.data.enums.ArmorType; | ||||||
| import com.majinnaibu.monstercards.helpers.ArrayHelper; | import com.majinnaibu.monstercards.helpers.ArrayHelper; | ||||||
| import com.majinnaibu.monstercards.ui.MCFragment; | import com.majinnaibu.monstercards.ui.shared.MCFragment; | ||||||
| import com.majinnaibu.monstercards.utils.TextChangedListener; | import com.majinnaibu.monstercards.utils.TextChangedListener; | ||||||
|  |  | ||||||
| @SuppressWarnings("FieldCanBeLocal") |  | ||||||
| public class EditArmorFragment extends MCFragment { | public class EditArmorFragment extends MCFragment { | ||||||
|     private EditMonsterViewModel mViewModel; |     private EditMonsterViewModel mViewModel; | ||||||
|     private ViewHolder mHolder; |     private ViewHolder mHolder; | ||||||
|   | |||||||
| @@ -13,10 +13,9 @@ import androidx.navigation.Navigation; | |||||||
|  |  | ||||||
| import com.google.android.material.switchmaterial.SwitchMaterial; | import com.google.android.material.switchmaterial.SwitchMaterial; | ||||||
| import com.majinnaibu.monstercards.R; | import com.majinnaibu.monstercards.R; | ||||||
| import com.majinnaibu.monstercards.ui.MCFragment; | import com.majinnaibu.monstercards.ui.shared.MCFragment; | ||||||
| import com.majinnaibu.monstercards.utils.TextChangedListener; | import com.majinnaibu.monstercards.utils.TextChangedListener; | ||||||
|  |  | ||||||
| @SuppressWarnings("FieldCanBeLocal") |  | ||||||
| public class EditBasicInfoFragment extends MCFragment { | public class EditBasicInfoFragment extends MCFragment { | ||||||
|     private EditMonsterViewModel mViewModel; |     private EditMonsterViewModel mViewModel; | ||||||
|     private ViewHolder mHolder; |     private ViewHolder mHolder; | ||||||
|   | |||||||
| @@ -20,7 +20,7 @@ import androidx.navigation.Navigation; | |||||||
| import com.majinnaibu.monstercards.R; | import com.majinnaibu.monstercards.R; | ||||||
| import com.majinnaibu.monstercards.data.enums.ChallengeRating; | import com.majinnaibu.monstercards.data.enums.ChallengeRating; | ||||||
| import com.majinnaibu.monstercards.helpers.ArrayHelper; | import com.majinnaibu.monstercards.helpers.ArrayHelper; | ||||||
| import com.majinnaibu.monstercards.ui.MCFragment; | import com.majinnaibu.monstercards.ui.shared.MCFragment; | ||||||
| import com.majinnaibu.monstercards.utils.TextChangedListener; | import com.majinnaibu.monstercards.utils.TextChangedListener; | ||||||
|  |  | ||||||
| public class EditChallengeRatingFragment extends MCFragment { | public class EditChallengeRatingFragment extends MCFragment { | ||||||
|   | |||||||
| @@ -29,7 +29,6 @@ import org.jetbrains.annotations.NotNull; | |||||||
| /** | /** | ||||||
|  * A fragment representing a list of Items. |  * A fragment representing a list of Items. | ||||||
|  */ |  */ | ||||||
| @SuppressWarnings("FieldCanBeLocal") |  | ||||||
| public class EditConditionImmunitiesFragment extends Fragment { | public class EditConditionImmunitiesFragment extends Fragment { | ||||||
|     private EditMonsterViewModel mViewModel; |     private EditMonsterViewModel mViewModel; | ||||||
|     private ViewHolder mHolder; |     private ViewHolder mHolder; | ||||||
|   | |||||||
| @@ -26,7 +26,7 @@ public class EditConditionImmunitiesRecyclerViewAdapter extends RecyclerView.Ada | |||||||
|  |  | ||||||
|     @NotNull |     @NotNull | ||||||
|     @Override |     @Override | ||||||
|     public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { |     public ViewHolder onCreateViewHolder(@NotNull ViewGroup parent, int viewType) { | ||||||
|         return new ViewHolder(FragmentEditConditionImmunitiesListItemBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false)); |         return new ViewHolder(FragmentEditConditionImmunitiesListItemBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false)); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -19,22 +19,21 @@ import com.majinnaibu.monstercards.R; | |||||||
| import com.majinnaibu.monstercards.utils.Logger; | import com.majinnaibu.monstercards.utils.Logger; | ||||||
| import com.majinnaibu.monstercards.utils.TextChangedListener; | import com.majinnaibu.monstercards.utils.TextChangedListener; | ||||||
|  |  | ||||||
| @SuppressWarnings("FieldCanBeLocal") |  | ||||||
| public class EditConditionImmunityFragment extends Fragment { | public class EditConditionImmunityFragment extends Fragment { | ||||||
|     private EditMonsterViewModel mEditMonsterViewModel; |     private EditMonsterViewModel mEditMonsterViewModel; | ||||||
|     private EditConditionImmunityViewModel mViewModel; |     private EditStringViewModel mViewModel; | ||||||
|     private ViewHolder mHolder; |     private ViewHolder mHolder; | ||||||
|     private String mOldValue; |     private String mOldValue; | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     public void onCreate(@Nullable Bundle savedInstanceState) { |     public void onCreate(@Nullable Bundle savedInstanceState) { | ||||||
|         mViewModel = new ViewModelProvider(this).get(EditConditionImmunityViewModel.class); |         mViewModel = new ViewModelProvider(this).get(EditStringViewModel.class); | ||||||
|         if (getArguments() != null) { |         if (getArguments() != null) { | ||||||
|             EditConditionImmunityFragmentArgs args = EditConditionImmunityFragmentArgs.fromBundle(getArguments()); |             EditConditionImmunityFragmentArgs args = EditConditionImmunityFragmentArgs.fromBundle(getArguments()); | ||||||
|             mOldValue = args.getCondition(); |             mOldValue = args.getCondition(); | ||||||
|             mViewModel.reset(mOldValue); |             mViewModel.resetValue(mOldValue); | ||||||
|         } else { |         } else { | ||||||
|             Logger.logWTF("This should never happen. EditConditionImmunityFragment needs arguments"); |             Logger.logWTF("EditConditionImmunityFragment needs arguments"); | ||||||
|             mOldValue = null; |             mOldValue = null; | ||||||
|         } |         } | ||||||
|  |  | ||||||
| @@ -49,14 +48,14 @@ public class EditConditionImmunityFragment extends Fragment { | |||||||
|         mEditMonsterViewModel = new ViewModelProvider(backStackEntry).get(EditMonsterViewModel.class); |         mEditMonsterViewModel = new ViewModelProvider(backStackEntry).get(EditMonsterViewModel.class); | ||||||
|         View root = inflater.inflate(R.layout.fragment_edit_condition_immunity, container, false); |         View root = inflater.inflate(R.layout.fragment_edit_condition_immunity, container, false); | ||||||
|         mHolder = new ViewHolder(root); |         mHolder = new ViewHolder(root); | ||||||
|         mHolder.description.setText(mViewModel.getDescription().getValue()); |         mHolder.description.setText(mViewModel.getValueAsString()); | ||||||
|         mHolder.description.addTextChangedListener(new TextChangedListener((TextChangedListener.OnTextChangedCallback) (s, start, before, count) -> mViewModel.setDescription(s.toString()))); |         mHolder.description.addTextChangedListener(new TextChangedListener((TextChangedListener.OnTextChangedCallback) (s, start, before, count) -> mViewModel.setValue(s.toString()))); | ||||||
|  |  | ||||||
|         requireActivity().getOnBackPressedDispatcher().addCallback(getViewLifecycleOwner(), new OnBackPressedCallback(true) { |         requireActivity().getOnBackPressedDispatcher().addCallback(getViewLifecycleOwner(), new OnBackPressedCallback(true) { | ||||||
|             @Override |             @Override | ||||||
|             public void handleOnBackPressed() { |             public void handleOnBackPressed() { | ||||||
|                 if (mViewModel.hasChanges()) { |                 if (mViewModel.hasChanges()) { | ||||||
|                     mEditMonsterViewModel.replaceConditionImmunity(mOldValue, mViewModel.getDescription().getValue()); |                     mEditMonsterViewModel.replaceConditionImmunity(mOldValue, mViewModel.getValueAsString()); | ||||||
|                 } |                 } | ||||||
|                 Navigation.findNavController(requireView()).navigateUp(); |                 Navigation.findNavController(requireView()).navigateUp(); | ||||||
|             } |             } | ||||||
|   | |||||||
| @@ -1,36 +0,0 @@ | |||||||
| package com.majinnaibu.monstercards.ui.editmonster; |  | ||||||
|  |  | ||||||
| import androidx.lifecycle.LiveData; |  | ||||||
| import androidx.lifecycle.MutableLiveData; |  | ||||||
| import androidx.lifecycle.ViewModel; |  | ||||||
|  |  | ||||||
| import com.majinnaibu.monstercards.utils.ChangeTrackedLiveData; |  | ||||||
|  |  | ||||||
| public class EditConditionImmunityViewModel extends ViewModel { |  | ||||||
|     private final ChangeTrackedLiveData<String> mDescription; |  | ||||||
|     private final MutableLiveData<Boolean> mHasChanges; |  | ||||||
|  |  | ||||||
|     public EditConditionImmunityViewModel() { |  | ||||||
|         mHasChanges = new MutableLiveData<>(false); |  | ||||||
|         ChangeTrackedLiveData.OnValueDirtiedCallback onDirtied = () -> mHasChanges.setValue(true); |  | ||||||
|         mDescription = new ChangeTrackedLiveData<>("", onDirtied); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     public void reset(String description) { |  | ||||||
|         mHasChanges.setValue(false); |  | ||||||
|         mDescription.resetValue(description); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     public LiveData<String> getDescription() { |  | ||||||
|         return mDescription; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     public void setDescription(String description) { |  | ||||||
|         mDescription.setValue(description); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     public boolean hasChanges() { |  | ||||||
|         Boolean value = mHasChanges.getValue(); |  | ||||||
|         return value != null && value; |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @@ -20,8 +20,8 @@ import com.google.android.material.snackbar.Snackbar; | |||||||
| import com.majinnaibu.monstercards.R; | import com.majinnaibu.monstercards.R; | ||||||
| import com.majinnaibu.monstercards.data.MonsterRepository; | import com.majinnaibu.monstercards.data.MonsterRepository; | ||||||
| import com.majinnaibu.monstercards.models.Monster; | import com.majinnaibu.monstercards.models.Monster; | ||||||
| import com.majinnaibu.monstercards.ui.MCFragment; |  | ||||||
| import com.majinnaibu.monstercards.ui.monster.MonsterDetailFragmentArgs; | import com.majinnaibu.monstercards.ui.monster.MonsterDetailFragmentArgs; | ||||||
|  | import com.majinnaibu.monstercards.ui.shared.MCFragment; | ||||||
| import com.majinnaibu.monstercards.utils.Logger; | import com.majinnaibu.monstercards.utils.Logger; | ||||||
|  |  | ||||||
| import java.util.Objects; | import java.util.Objects; | ||||||
| @@ -32,7 +32,6 @@ import io.reactivex.rxjava3.observers.DisposableCompletableObserver; | |||||||
| import io.reactivex.rxjava3.observers.DisposableSingleObserver; | import io.reactivex.rxjava3.observers.DisposableSingleObserver; | ||||||
| import io.reactivex.rxjava3.schedulers.Schedulers; | import io.reactivex.rxjava3.schedulers.Schedulers; | ||||||
|  |  | ||||||
| @SuppressWarnings("FieldCanBeLocal") |  | ||||||
| public class EditMonsterFragment extends MCFragment { | public class EditMonsterFragment extends MCFragment { | ||||||
|  |  | ||||||
|     private EditMonsterViewModel mViewModel; |     private EditMonsterViewModel mViewModel; | ||||||
|   | |||||||
| @@ -3,7 +3,6 @@ package com.majinnaibu.monstercards.ui.editmonster; | |||||||
| import androidx.annotation.NonNull; | import androidx.annotation.NonNull; | ||||||
| import androidx.lifecycle.LiveData; | import androidx.lifecycle.LiveData; | ||||||
| import androidx.lifecycle.MutableLiveData; | import androidx.lifecycle.MutableLiveData; | ||||||
| import androidx.lifecycle.ViewModel; |  | ||||||
|  |  | ||||||
| import com.majinnaibu.monstercards.data.enums.AbilityScore; | import com.majinnaibu.monstercards.data.enums.AbilityScore; | ||||||
| import com.majinnaibu.monstercards.data.enums.AdvantageType; | import com.majinnaibu.monstercards.data.enums.AdvantageType; | ||||||
| @@ -15,6 +14,7 @@ import com.majinnaibu.monstercards.models.Language; | |||||||
| import com.majinnaibu.monstercards.models.Monster; | import com.majinnaibu.monstercards.models.Monster; | ||||||
| import com.majinnaibu.monstercards.models.Skill; | import com.majinnaibu.monstercards.models.Skill; | ||||||
| import com.majinnaibu.monstercards.models.Trait; | import com.majinnaibu.monstercards.models.Trait; | ||||||
|  | import com.majinnaibu.monstercards.ui.shared.ChangeTrackedViewModel; | ||||||
| import com.majinnaibu.monstercards.utils.ChangeTrackedLiveData; | import com.majinnaibu.monstercards.utils.ChangeTrackedLiveData; | ||||||
|  |  | ||||||
| import java.util.ArrayList; | import java.util.ArrayList; | ||||||
| @@ -26,11 +26,10 @@ import java.util.Objects; | |||||||
| import java.util.UUID; | import java.util.UUID; | ||||||
|  |  | ||||||
| @SuppressWarnings({"ConstantConditions", "unused"}) | @SuppressWarnings({"ConstantConditions", "unused"}) | ||||||
| public class EditMonsterViewModel extends ViewModel { | public class EditMonsterViewModel extends ChangeTrackedViewModel { | ||||||
|     private final ChangeTrackedLiveData<UUID> mMonsterId; |     private final ChangeTrackedLiveData<UUID> mMonsterId; | ||||||
|     private final MutableLiveData<Boolean> mHasError; |     private final MutableLiveData<Boolean> mHasError; | ||||||
|     private final MutableLiveData<Boolean> mHasLoaded; |     private final MutableLiveData<Boolean> mHasLoaded; | ||||||
|     private final MutableLiveData<Boolean> mHasChanges; |  | ||||||
|     private final ChangeTrackedLiveData<Boolean> mHasCustomHitPoints; |     private final ChangeTrackedLiveData<Boolean> mHasCustomHitPoints; | ||||||
|     private final ChangeTrackedLiveData<Boolean> mHasShield; |     private final ChangeTrackedLiveData<Boolean> mHasShield; | ||||||
|     private final ChangeTrackedLiveData<Boolean> mCanHover; |     private final ChangeTrackedLiveData<Boolean> mCanHover; | ||||||
| @@ -91,70 +90,69 @@ public class EditMonsterViewModel extends ViewModel { | |||||||
|     private final ChangeTrackedLiveData<List<Trait>> mRegionalActions; |     private final ChangeTrackedLiveData<List<Trait>> mRegionalActions; | ||||||
|  |  | ||||||
|     public EditMonsterViewModel() { |     public EditMonsterViewModel() { | ||||||
|  |         super(); | ||||||
|         mErrorMessage = new MutableLiveData<>(""); |         mErrorMessage = new MutableLiveData<>(""); | ||||||
|         mHasError = new MutableLiveData<>(false); |         mHasError = new MutableLiveData<>(false); | ||||||
|         mHasLoaded = new MutableLiveData<>(false); |         mHasLoaded = new MutableLiveData<>(false); | ||||||
|         mHasChanges = new MutableLiveData<>(false); |  | ||||||
|         ChangeTrackedLiveData.OnValueDirtiedCallback onDirtied = () -> mHasChanges.setValue(true); |  | ||||||
|  |  | ||||||
|         mName = new ChangeTrackedLiveData<>("", onDirtied); |         mName = new ChangeTrackedLiveData<>("", this::makeDirty); | ||||||
|         mMonsterId = new ChangeTrackedLiveData<>(UUID.randomUUID(), onDirtied); |         mMonsterId = new ChangeTrackedLiveData<>(UUID.randomUUID(), this::makeDirty); | ||||||
|         mSize = new ChangeTrackedLiveData<>("", onDirtied); |         mSize = new ChangeTrackedLiveData<>("", this::makeDirty); | ||||||
|         mType = new ChangeTrackedLiveData<>("", onDirtied); |         mType = new ChangeTrackedLiveData<>("", this::makeDirty); | ||||||
|         mSubtype = new ChangeTrackedLiveData<>("", onDirtied); |         mSubtype = new ChangeTrackedLiveData<>("", this::makeDirty); | ||||||
|         mAlignment = new ChangeTrackedLiveData<>("", onDirtied); |         mAlignment = new ChangeTrackedLiveData<>("", this::makeDirty); | ||||||
|         mCustomHitPoints = new ChangeTrackedLiveData<>("", onDirtied); |         mCustomHitPoints = new ChangeTrackedLiveData<>("", this::makeDirty); | ||||||
|         mHitDice = new ChangeTrackedLiveData<>(0, onDirtied); |         mHitDice = new ChangeTrackedLiveData<>(0, this::makeDirty); | ||||||
|         mNaturalArmorBonus = new ChangeTrackedLiveData<>(0, onDirtied); |         mNaturalArmorBonus = new ChangeTrackedLiveData<>(0, this::makeDirty); | ||||||
|         mHasCustomHitPoints = new ChangeTrackedLiveData<>(false, onDirtied); |         mHasCustomHitPoints = new ChangeTrackedLiveData<>(false, this::makeDirty); | ||||||
|         mArmorType = new ChangeTrackedLiveData<>(ArmorType.NONE, onDirtied); |         mArmorType = new ChangeTrackedLiveData<>(ArmorType.NONE, this::makeDirty); | ||||||
|         mHasShield = new ChangeTrackedLiveData<>(false, onDirtied); |         mHasShield = new ChangeTrackedLiveData<>(false, this::makeDirty); | ||||||
|         mShieldBonus = new ChangeTrackedLiveData<>(0, onDirtied); |         mShieldBonus = new ChangeTrackedLiveData<>(0, this::makeDirty); | ||||||
|         mCustomArmor = new ChangeTrackedLiveData<>("", onDirtied); |         mCustomArmor = new ChangeTrackedLiveData<>("", this::makeDirty); | ||||||
|         mWalkSpeed = new ChangeTrackedLiveData<>(0, onDirtied); |         mWalkSpeed = new ChangeTrackedLiveData<>(0, this::makeDirty); | ||||||
|         mBurrowSpeed = new ChangeTrackedLiveData<>(0, onDirtied); |         mBurrowSpeed = new ChangeTrackedLiveData<>(0, this::makeDirty); | ||||||
|         mClimbSpeed = new ChangeTrackedLiveData<>(0, onDirtied); |         mClimbSpeed = new ChangeTrackedLiveData<>(0, this::makeDirty); | ||||||
|         mFlySpeed = new ChangeTrackedLiveData<>(0, onDirtied); |         mFlySpeed = new ChangeTrackedLiveData<>(0, this::makeDirty); | ||||||
|         mSwimSpeed = new ChangeTrackedLiveData<>(0, onDirtied); |         mSwimSpeed = new ChangeTrackedLiveData<>(0, this::makeDirty); | ||||||
|         mCanHover = new ChangeTrackedLiveData<>(false, onDirtied); |         mCanHover = new ChangeTrackedLiveData<>(false, this::makeDirty); | ||||||
|         mHasCustomSpeed = new ChangeTrackedLiveData<>(false, onDirtied); |         mHasCustomSpeed = new ChangeTrackedLiveData<>(false, this::makeDirty); | ||||||
|         mCustomSpeed = new ChangeTrackedLiveData<>("", onDirtied); |         mCustomSpeed = new ChangeTrackedLiveData<>("", this::makeDirty); | ||||||
|         mStrength = new ChangeTrackedLiveData<>(10, onDirtied); |         mStrength = new ChangeTrackedLiveData<>(10, this::makeDirty); | ||||||
|         mDexterity = new ChangeTrackedLiveData<>(10, onDirtied); |         mDexterity = new ChangeTrackedLiveData<>(10, this::makeDirty); | ||||||
|         mConstitution = new ChangeTrackedLiveData<>(10, onDirtied); |         mConstitution = new ChangeTrackedLiveData<>(10, this::makeDirty); | ||||||
|         mIntelligence = new ChangeTrackedLiveData<>(10, onDirtied); |         mIntelligence = new ChangeTrackedLiveData<>(10, this::makeDirty); | ||||||
|         mWisdom = new ChangeTrackedLiveData<>(10, onDirtied); |         mWisdom = new ChangeTrackedLiveData<>(10, this::makeDirty); | ||||||
|         mCharisma = new ChangeTrackedLiveData<>(10, onDirtied); |         mCharisma = new ChangeTrackedLiveData<>(10, this::makeDirty); | ||||||
|         mStrengthProficiency = new ChangeTrackedLiveData<>(ProficiencyType.NONE, onDirtied); |         mStrengthProficiency = new ChangeTrackedLiveData<>(ProficiencyType.NONE, this::makeDirty); | ||||||
|         mStrengthAdvantage = new ChangeTrackedLiveData<>(AdvantageType.NONE, onDirtied); |         mStrengthAdvantage = new ChangeTrackedLiveData<>(AdvantageType.NONE, this::makeDirty); | ||||||
|         mDexterityProficiency = new ChangeTrackedLiveData<>(ProficiencyType.NONE, onDirtied); |         mDexterityProficiency = new ChangeTrackedLiveData<>(ProficiencyType.NONE, this::makeDirty); | ||||||
|         mDexterityAdvantage = new ChangeTrackedLiveData<>(AdvantageType.NONE, onDirtied); |         mDexterityAdvantage = new ChangeTrackedLiveData<>(AdvantageType.NONE, this::makeDirty); | ||||||
|         mConstitutionProficiency = new ChangeTrackedLiveData<>(ProficiencyType.NONE, onDirtied); |         mConstitutionProficiency = new ChangeTrackedLiveData<>(ProficiencyType.NONE, this::makeDirty); | ||||||
|         mConstitutionAdvantage = new ChangeTrackedLiveData<>(AdvantageType.NONE, onDirtied); |         mConstitutionAdvantage = new ChangeTrackedLiveData<>(AdvantageType.NONE, this::makeDirty); | ||||||
|         mIntelligenceProficiency = new ChangeTrackedLiveData<>(ProficiencyType.NONE, onDirtied); |         mIntelligenceProficiency = new ChangeTrackedLiveData<>(ProficiencyType.NONE, this::makeDirty); | ||||||
|         mIntelligenceAdvantage = new ChangeTrackedLiveData<>(AdvantageType.NONE, onDirtied); |         mIntelligenceAdvantage = new ChangeTrackedLiveData<>(AdvantageType.NONE, this::makeDirty); | ||||||
|         mWisdomProficiency = new ChangeTrackedLiveData<>(ProficiencyType.NONE, onDirtied); |         mWisdomProficiency = new ChangeTrackedLiveData<>(ProficiencyType.NONE, this::makeDirty); | ||||||
|         mWisdomAdvantage = new ChangeTrackedLiveData<>(AdvantageType.NONE, onDirtied); |         mWisdomAdvantage = new ChangeTrackedLiveData<>(AdvantageType.NONE, this::makeDirty); | ||||||
|         mCharismaProficiency = new ChangeTrackedLiveData<>(ProficiencyType.NONE, onDirtied); |         mCharismaProficiency = new ChangeTrackedLiveData<>(ProficiencyType.NONE, this::makeDirty); | ||||||
|         mCharismaAdvantage = new ChangeTrackedLiveData<>(AdvantageType.NONE, onDirtied); |         mCharismaAdvantage = new ChangeTrackedLiveData<>(AdvantageType.NONE, this::makeDirty); | ||||||
|         mChallengeRating = new ChangeTrackedLiveData<>(ChallengeRating.ONE_EIGHTH, onDirtied); |         mChallengeRating = new ChangeTrackedLiveData<>(ChallengeRating.ONE_EIGHTH, this::makeDirty); | ||||||
|         mCustomChallengeRatingDescription = new ChangeTrackedLiveData<>("", onDirtied); |         mCustomChallengeRatingDescription = new ChangeTrackedLiveData<>("", this::makeDirty); | ||||||
|         mCustomProficiencyBonus = new ChangeTrackedLiveData<>(0, onDirtied); |         mCustomProficiencyBonus = new ChangeTrackedLiveData<>(0, this::makeDirty); | ||||||
|         mTelepathyRange = new ChangeTrackedLiveData<>(0, onDirtied); |         mTelepathyRange = new ChangeTrackedLiveData<>(0, this::makeDirty); | ||||||
|         mUnderstandsButDescription = new ChangeTrackedLiveData<>("", onDirtied); |         mUnderstandsButDescription = new ChangeTrackedLiveData<>("", this::makeDirty); | ||||||
|         mSkills = new ChangeTrackedLiveData<>(new ArrayList<>(), onDirtied); |         mSkills = new ChangeTrackedLiveData<>(new ArrayList<>(), this::makeDirty); | ||||||
|         mSenses = new ChangeTrackedLiveData<>(new ArrayList<>(), onDirtied); |         mSenses = new ChangeTrackedLiveData<>(new ArrayList<>(), this::makeDirty); | ||||||
|         mDamageImmunities = new ChangeTrackedLiveData<>(new ArrayList<>(), onDirtied); |         mDamageImmunities = new ChangeTrackedLiveData<>(new ArrayList<>(), this::makeDirty); | ||||||
|         mDamageResistances = new ChangeTrackedLiveData<>(new ArrayList<>(), onDirtied); |         mDamageResistances = new ChangeTrackedLiveData<>(new ArrayList<>(), this::makeDirty); | ||||||
|         mDamageVulnerabilities = new ChangeTrackedLiveData<>(new ArrayList<>(), onDirtied); |         mDamageVulnerabilities = new ChangeTrackedLiveData<>(new ArrayList<>(), this::makeDirty); | ||||||
|         mConditionImmunities = new ChangeTrackedLiveData<>(new ArrayList<>(), onDirtied); |         mConditionImmunities = new ChangeTrackedLiveData<>(new ArrayList<>(), this::makeDirty); | ||||||
|         mLanguages = new ChangeTrackedLiveData<>(new ArrayList<>(), onDirtied); |         mLanguages = new ChangeTrackedLiveData<>(new ArrayList<>(), this::makeDirty); | ||||||
|         mAbilities = new ChangeTrackedLiveData<>(new ArrayList<>(), onDirtied); |         mAbilities = new ChangeTrackedLiveData<>(new ArrayList<>(), this::makeDirty); | ||||||
|         mActions = new ChangeTrackedLiveData<>(new ArrayList<>(), onDirtied); |         mActions = new ChangeTrackedLiveData<>(new ArrayList<>(), this::makeDirty); | ||||||
|         mReactions = new ChangeTrackedLiveData<>(new ArrayList<>(), onDirtied); |         mReactions = new ChangeTrackedLiveData<>(new ArrayList<>(), this::makeDirty); | ||||||
|         mLairActions = new ChangeTrackedLiveData<>(new ArrayList<>(), onDirtied); |         mLairActions = new ChangeTrackedLiveData<>(new ArrayList<>(), this::makeDirty); | ||||||
|         mLegendaryActions = new ChangeTrackedLiveData<>(new ArrayList<>(), onDirtied); |         mLegendaryActions = new ChangeTrackedLiveData<>(new ArrayList<>(), this::makeDirty); | ||||||
|         mRegionalActions = new ChangeTrackedLiveData<>(new ArrayList<>(), onDirtied); |         mRegionalActions = new ChangeTrackedLiveData<>(new ArrayList<>(), this::makeDirty); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public void copyFromMonster(Monster monster) { |     public void copyFromMonster(Monster monster) { | ||||||
| @@ -231,7 +229,7 @@ public class EditMonsterViewModel extends ViewModel { | |||||||
|         mLairActions.resetValue(new ArrayList<>(monster.lairActions)); |         mLairActions.resetValue(new ArrayList<>(monster.lairActions)); | ||||||
|         mLegendaryActions.resetValue(new ArrayList<>(monster.legendaryActions)); |         mLegendaryActions.resetValue(new ArrayList<>(monster.legendaryActions)); | ||||||
|         mRegionalActions.resetValue(new ArrayList<>(monster.regionalActions)); |         mRegionalActions.resetValue(new ArrayList<>(monster.regionalActions)); | ||||||
|         mHasChanges.setValue(false); |         makeClean(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public LiveData<String> getName() { |     public LiveData<String> getName() { | ||||||
| @@ -318,14 +316,6 @@ public class EditMonsterViewModel extends ViewModel { | |||||||
|         mCustomHitPoints.setValue(customHitPoints); |         mCustomHitPoints.setValue(customHitPoints); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public LiveData<Boolean> getHasChanges() { |  | ||||||
|         return mHasChanges; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     public boolean hasChanges() { |  | ||||||
|         return mHasChanges.getValue(); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     public LiveData<Integer> getHitDice() { |     public LiveData<Integer> getHitDice() { | ||||||
|         return mHitDice; |         return mHitDice; | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -11,9 +11,9 @@ import androidx.navigation.NavController; | |||||||
| import androidx.navigation.Navigation; | import androidx.navigation.Navigation; | ||||||
|  |  | ||||||
| import com.majinnaibu.monstercards.R; | import com.majinnaibu.monstercards.R; | ||||||
| import com.majinnaibu.monstercards.ui.MCFragment; |  | ||||||
| import com.majinnaibu.monstercards.ui.components.AdvantagePicker; | import com.majinnaibu.monstercards.ui.components.AdvantagePicker; | ||||||
| import com.majinnaibu.monstercards.ui.components.ProficiencyPicker; | import com.majinnaibu.monstercards.ui.components.ProficiencyPicker; | ||||||
|  | import com.majinnaibu.monstercards.ui.shared.MCFragment; | ||||||
|  |  | ||||||
| public class EditSavingThrowsFragment extends MCFragment { | public class EditSavingThrowsFragment extends MCFragment { | ||||||
|     private EditMonsterViewModel mViewModel; |     private EditMonsterViewModel mViewModel; | ||||||
|   | |||||||
| @@ -15,26 +15,25 @@ import androidx.navigation.NavController; | |||||||
| import androidx.navigation.Navigation; | import androidx.navigation.Navigation; | ||||||
|  |  | ||||||
| import com.majinnaibu.monstercards.R; | import com.majinnaibu.monstercards.R; | ||||||
| import com.majinnaibu.monstercards.ui.MCFragment; | import com.majinnaibu.monstercards.ui.shared.MCFragment; | ||||||
| import com.majinnaibu.monstercards.utils.Logger; | import com.majinnaibu.monstercards.utils.Logger; | ||||||
| import com.majinnaibu.monstercards.utils.TextChangedListener; | import com.majinnaibu.monstercards.utils.TextChangedListener; | ||||||
|  |  | ||||||
| @SuppressWarnings("FieldCanBeLocal") |  | ||||||
| public class EditSenseFragment extends MCFragment { | public class EditSenseFragment extends MCFragment { | ||||||
|     private EditMonsterViewModel mEditMonsterViewModel; |     private EditMonsterViewModel mEditMonsterViewModel; | ||||||
|     private EditSenseViewModel mViewModel; |     private EditStringViewModel mViewModel; | ||||||
|     private ViewHolder mHolder; |     private ViewHolder mHolder; | ||||||
|     private String mOldSense; |     private String mOldSense; | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     public void onCreate(@Nullable Bundle savedInstanceState) { |     public void onCreate(@Nullable Bundle savedInstanceState) { | ||||||
|         mViewModel = new ViewModelProvider(this).get(EditSenseViewModel.class); |         mViewModel = new ViewModelProvider(this).get(EditStringViewModel.class); | ||||||
|         if (getArguments() != null) { |         if (getArguments() != null) { | ||||||
|             EditSenseFragmentArgs args = EditSenseFragmentArgs.fromBundle(getArguments()); |             EditSenseFragmentArgs args = EditSenseFragmentArgs.fromBundle(getArguments()); | ||||||
|             mOldSense = args.getSense(); |             mOldSense = args.getSense(); | ||||||
|             mViewModel.reset(mOldSense); |             mViewModel.resetValue(mOldSense); | ||||||
|         } else { |         } else { | ||||||
|             Logger.logWTF("This should never happen. EditSenseFragment needs arguments"); |             Logger.logWTF("EditSenseFragment needs arguments"); | ||||||
|             mOldSense = null; |             mOldSense = null; | ||||||
|         } |         } | ||||||
|         super.onCreate(savedInstanceState); |         super.onCreate(savedInstanceState); | ||||||
| @@ -51,14 +50,14 @@ public class EditSenseFragment extends MCFragment { | |||||||
|  |  | ||||||
|         mHolder = new ViewHolder(root); |         mHolder = new ViewHolder(root); | ||||||
|  |  | ||||||
|         mHolder.description.setText(mViewModel.getDescription().getValue()); |         mHolder.description.setText(mViewModel.getValueAsString()); | ||||||
|         mHolder.description.addTextChangedListener(new TextChangedListener((TextChangedListener.OnTextChangedCallback) (s, start, before, count) -> mViewModel.setDescription(s.toString()))); |         mHolder.description.addTextChangedListener(new TextChangedListener((TextChangedListener.OnTextChangedCallback) (s, start, before, count) -> mViewModel.setValue(s.toString()))); | ||||||
|  |  | ||||||
|         requireActivity().getOnBackPressedDispatcher().addCallback(getViewLifecycleOwner(), new OnBackPressedCallback(true) { |         requireActivity().getOnBackPressedDispatcher().addCallback(getViewLifecycleOwner(), new OnBackPressedCallback(true) { | ||||||
|             @Override |             @Override | ||||||
|             public void handleOnBackPressed() { |             public void handleOnBackPressed() { | ||||||
|                 if (mViewModel.hasChanges()) { |                 if (mViewModel.hasChanges()) { | ||||||
|                     mEditMonsterViewModel.replaceSense(mOldSense, mViewModel.getDescription().getValue()); |                     mEditMonsterViewModel.replaceSense(mOldSense, mViewModel.getValueAsString()); | ||||||
|                 } |                 } | ||||||
|                 Navigation.findNavController(requireView()).navigateUp(); |                 Navigation.findNavController(requireView()).navigateUp(); | ||||||
|             } |             } | ||||||
|   | |||||||
| @@ -1,36 +0,0 @@ | |||||||
| package com.majinnaibu.monstercards.ui.editmonster; |  | ||||||
|  |  | ||||||
| import androidx.lifecycle.LiveData; |  | ||||||
| import androidx.lifecycle.MutableLiveData; |  | ||||||
| import androidx.lifecycle.ViewModel; |  | ||||||
|  |  | ||||||
| import com.majinnaibu.monstercards.utils.ChangeTrackedLiveData; |  | ||||||
|  |  | ||||||
| public class EditSenseViewModel extends ViewModel { |  | ||||||
|     private final ChangeTrackedLiveData<String> mDescription; |  | ||||||
|     private final MutableLiveData<Boolean> mHasChanges; |  | ||||||
|  |  | ||||||
|     public EditSenseViewModel() { |  | ||||||
|         mHasChanges = new MutableLiveData<>(false); |  | ||||||
|         ChangeTrackedLiveData.OnValueDirtiedCallback onDirtied = () -> mHasChanges.setValue(true); |  | ||||||
|         mDescription = new ChangeTrackedLiveData<>("", onDirtied); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     public void reset(String description) { |  | ||||||
|         mHasChanges.setValue(false); |  | ||||||
|         mDescription.resetValue(description); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     public LiveData<String> getDescription() { |  | ||||||
|         return mDescription; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     public void setDescription(String description) { |  | ||||||
|         mDescription.setValue(description); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     public boolean hasChanges() { |  | ||||||
|         Boolean value = mHasChanges.getValue(); |  | ||||||
|         return value != null && value; |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @@ -19,14 +19,13 @@ import androidx.recyclerview.widget.RecyclerView; | |||||||
|  |  | ||||||
| import com.google.android.material.floatingactionbutton.FloatingActionButton; | import com.google.android.material.floatingactionbutton.FloatingActionButton; | ||||||
| import com.majinnaibu.monstercards.R; | import com.majinnaibu.monstercards.R; | ||||||
| import com.majinnaibu.monstercards.ui.MCFragment; | import com.majinnaibu.monstercards.ui.shared.MCFragment; | ||||||
| import com.majinnaibu.monstercards.ui.shared.SwipeToDeleteCallback; | import com.majinnaibu.monstercards.ui.shared.SwipeToDeleteCallback; | ||||||
| import com.majinnaibu.monstercards.utils.Logger; | import com.majinnaibu.monstercards.utils.Logger; | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * A fragment representing a list of Items. |  * A fragment representing a list of Items. | ||||||
|  */ |  */ | ||||||
| @SuppressWarnings("FieldCanBeLocal") |  | ||||||
| public class EditSensesFragment extends MCFragment { | public class EditSensesFragment extends MCFragment { | ||||||
|     private EditMonsterViewModel mViewModel; |     private EditMonsterViewModel mViewModel; | ||||||
|     private ViewHolder mHolder; |     private ViewHolder mHolder; | ||||||
|   | |||||||
| @@ -16,10 +16,10 @@ import androidx.navigation.Navigation; | |||||||
|  |  | ||||||
| import com.majinnaibu.monstercards.R; | import com.majinnaibu.monstercards.R; | ||||||
| import com.majinnaibu.monstercards.models.Skill; | import com.majinnaibu.monstercards.models.Skill; | ||||||
| import com.majinnaibu.monstercards.ui.MCFragment; |  | ||||||
| import com.majinnaibu.monstercards.ui.components.AbilityScorePicker; | import com.majinnaibu.monstercards.ui.components.AbilityScorePicker; | ||||||
| import com.majinnaibu.monstercards.ui.components.AdvantagePicker; | import com.majinnaibu.monstercards.ui.components.AdvantagePicker; | ||||||
| import com.majinnaibu.monstercards.ui.components.ProficiencyPicker; | 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.Logger; | ||||||
| import com.majinnaibu.monstercards.utils.TextChangedListener; | import com.majinnaibu.monstercards.utils.TextChangedListener; | ||||||
|  |  | ||||||
| @@ -37,7 +37,7 @@ public class EditSkillFragment extends MCFragment { | |||||||
|             mOldSkill = new Skill(args.getName(), args.getAbilityScore(), args.getAdvantage(), args.getProficiency()); |             mOldSkill = new Skill(args.getName(), args.getAbilityScore(), args.getAdvantage(), args.getProficiency()); | ||||||
|             mViewModel.copyFromSkill(mOldSkill); |             mViewModel.copyFromSkill(mOldSkill); | ||||||
|         } else { |         } else { | ||||||
|             Logger.logWTF("This should never happen. EditSkillFragment needs arguments."); |             Logger.logWTF("EditSkillFragment needs arguments."); | ||||||
|             mOldSkill = null; |             mOldSkill = null; | ||||||
|         } |         } | ||||||
|         super.onCreate(savedInstanceState); |         super.onCreate(savedInstanceState); | ||||||
|   | |||||||
| @@ -1,32 +1,28 @@ | |||||||
| package com.majinnaibu.monstercards.ui.editmonster; | package com.majinnaibu.monstercards.ui.editmonster; | ||||||
|  |  | ||||||
| import androidx.lifecycle.LiveData; | 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.AbilityScore; | ||||||
| import com.majinnaibu.monstercards.data.enums.AdvantageType; | import com.majinnaibu.monstercards.data.enums.AdvantageType; | ||||||
| import com.majinnaibu.monstercards.data.enums.ProficiencyType; | import com.majinnaibu.monstercards.data.enums.ProficiencyType; | ||||||
| import com.majinnaibu.monstercards.models.Skill; | import com.majinnaibu.monstercards.models.Skill; | ||||||
|  | import com.majinnaibu.monstercards.ui.shared.ChangeTrackedViewModel; | ||||||
| import com.majinnaibu.monstercards.utils.ChangeTrackedLiveData; | import com.majinnaibu.monstercards.utils.ChangeTrackedLiveData; | ||||||
|  |  | ||||||
| public class EditSkillViewModel extends ViewModel { | public class EditSkillViewModel extends ChangeTrackedViewModel { | ||||||
|     private final ChangeTrackedLiveData<AbilityScore> mAbilityScore; |     private final ChangeTrackedLiveData<AbilityScore> mAbilityScore; | ||||||
|     private final ChangeTrackedLiveData<AdvantageType> mAdvantageType; |     private final ChangeTrackedLiveData<AdvantageType> mAdvantageType; | ||||||
|     private final MutableLiveData<Boolean> mHasChanges; |  | ||||||
|     private final ChangeTrackedLiveData<ProficiencyType> mProficiencyType; |     private final ChangeTrackedLiveData<ProficiencyType> mProficiencyType; | ||||||
|     private final ChangeTrackedLiveData<String> mName; |     private final ChangeTrackedLiveData<String> mName; | ||||||
|     private final ChangeTrackedLiveData<Skill> mSkill; |     private final ChangeTrackedLiveData<Skill> mSkill; | ||||||
|  |  | ||||||
|     public EditSkillViewModel() { |     public EditSkillViewModel() { | ||||||
|         mHasChanges = new MutableLiveData<>(false); |         super(); | ||||||
|         ChangeTrackedLiveData.OnValueDirtiedCallback onDirtied = () -> mHasChanges.setValue(true); |         mAbilityScore = new ChangeTrackedLiveData<>(AbilityScore.STRENGTH, this::makeDirty); | ||||||
|  |         mAdvantageType = new ChangeTrackedLiveData<>(AdvantageType.NONE, this::makeDirty); | ||||||
|         mAbilityScore = new ChangeTrackedLiveData<>(AbilityScore.STRENGTH, onDirtied); |         mProficiencyType = new ChangeTrackedLiveData<>(ProficiencyType.NONE, this::makeDirty); | ||||||
|         mAdvantageType = new ChangeTrackedLiveData<>(AdvantageType.NONE, onDirtied); |         mName = new ChangeTrackedLiveData<>("Unknown Skill", this::makeDirty); | ||||||
|         mProficiencyType = new ChangeTrackedLiveData<>(ProficiencyType.NONE, onDirtied); |         mSkill = new ChangeTrackedLiveData<>(makeSkill(), this::makeDirty); | ||||||
|         mName = new ChangeTrackedLiveData<>("Unknown Skill", onDirtied); |  | ||||||
|         mSkill = new ChangeTrackedLiveData<>(makeSkill(), onDirtied); |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public void copyFromSkill(Skill skill) { |     public void copyFromSkill(Skill skill) { | ||||||
| @@ -76,11 +72,6 @@ public class EditSkillViewModel extends ViewModel { | |||||||
|         mSkill.setValue(makeSkill()); |         mSkill.setValue(makeSkill()); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public boolean hasChanges() { |  | ||||||
|         Boolean value = mHasChanges.getValue(); |  | ||||||
|         return value != null && value; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     private Skill makeSkill() { |     private Skill makeSkill() { | ||||||
|         return new Skill(mName.getValue(), mAbilityScore.getValue(), mAdvantageType.getValue(), mProficiencyType.getValue()); |         return new Skill(mName.getValue(), mAbilityScore.getValue(), mAdvantageType.getValue(), mProficiencyType.getValue()); | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -20,14 +20,13 @@ import androidx.recyclerview.widget.RecyclerView; | |||||||
| import com.google.android.material.floatingactionbutton.FloatingActionButton; | import com.google.android.material.floatingactionbutton.FloatingActionButton; | ||||||
| import com.majinnaibu.monstercards.R; | import com.majinnaibu.monstercards.R; | ||||||
| import com.majinnaibu.monstercards.models.Skill; | import com.majinnaibu.monstercards.models.Skill; | ||||||
| import com.majinnaibu.monstercards.ui.MCFragment; | import com.majinnaibu.monstercards.ui.shared.MCFragment; | ||||||
| import com.majinnaibu.monstercards.ui.shared.SwipeToDeleteCallback; | import com.majinnaibu.monstercards.ui.shared.SwipeToDeleteCallback; | ||||||
| import com.majinnaibu.monstercards.utils.Logger; | import com.majinnaibu.monstercards.utils.Logger; | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * A fragment representing a list of Items. |  * A fragment representing a list of Items. | ||||||
|  */ |  */ | ||||||
| @SuppressWarnings("FieldCanBeLocal") |  | ||||||
| public class EditSkillsFragment extends MCFragment { | public class EditSkillsFragment extends MCFragment { | ||||||
|     private EditMonsterViewModel mViewModel; |     private EditMonsterViewModel mViewModel; | ||||||
|     private ViewHolder mHolder; |     private ViewHolder mHolder; | ||||||
|   | |||||||
| @@ -13,8 +13,8 @@ import androidx.navigation.NavController; | |||||||
| import androidx.navigation.Navigation; | import androidx.navigation.Navigation; | ||||||
|  |  | ||||||
| import com.majinnaibu.monstercards.R; | import com.majinnaibu.monstercards.R; | ||||||
| import com.majinnaibu.monstercards.ui.MCFragment; |  | ||||||
| import com.majinnaibu.monstercards.ui.components.Stepper; | import com.majinnaibu.monstercards.ui.components.Stepper; | ||||||
|  | import com.majinnaibu.monstercards.ui.shared.MCFragment; | ||||||
| import com.majinnaibu.monstercards.utils.TextChangedListener; | import com.majinnaibu.monstercards.utils.TextChangedListener; | ||||||
|  |  | ||||||
| public class EditSpeedFragment extends MCFragment { | public class EditSpeedFragment extends MCFragment { | ||||||
|   | |||||||
| @@ -1,72 +0,0 @@ | |||||||
| package com.majinnaibu.monstercards.ui.editmonster.placeholder; |  | ||||||
|  |  | ||||||
| import java.util.ArrayList; |  | ||||||
| import java.util.HashMap; |  | ||||||
| import java.util.List; |  | ||||||
| import java.util.Map; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Helper class for providing sample content for user interfaces created by |  | ||||||
|  * Android template wizards. |  | ||||||
|  * <p> |  | ||||||
|  * TODO: Replace all uses of this class before publishing your app. |  | ||||||
|  */ |  | ||||||
| public class PlaceholderContent { |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * An array of sample (placeholder) items. |  | ||||||
|      */ |  | ||||||
|     public static final List<PlaceholderItem> ITEMS = new ArrayList<PlaceholderItem>(); |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * A map of sample (placeholder) items, by ID. |  | ||||||
|      */ |  | ||||||
|     public static final Map<String, PlaceholderItem> ITEM_MAP = new HashMap<String, PlaceholderItem>(); |  | ||||||
|  |  | ||||||
|     private static final int COUNT = 25; |  | ||||||
|  |  | ||||||
|     static { |  | ||||||
|         // Add some sample items. |  | ||||||
|         for (int i = 1; i <= COUNT; i++) { |  | ||||||
|             addItem(createPlaceholderItem(i)); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     private static void addItem(PlaceholderItem item) { |  | ||||||
|         ITEMS.add(item); |  | ||||||
|         ITEM_MAP.put(item.id, item); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     private static PlaceholderItem createPlaceholderItem(int position) { |  | ||||||
|         return new PlaceholderItem(String.valueOf(position), "Item " + position, makeDetails(position)); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     private static String makeDetails(int position) { |  | ||||||
|         StringBuilder builder = new StringBuilder(); |  | ||||||
|         builder.append("Details about Item: ").append(position); |  | ||||||
|         for (int i = 0; i < position; i++) { |  | ||||||
|             builder.append("\nMore details information here."); |  | ||||||
|         } |  | ||||||
|         return builder.toString(); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * A placeholder item representing a piece of content. |  | ||||||
|      */ |  | ||||||
|     public static class PlaceholderItem { |  | ||||||
|         public final String id; |  | ||||||
|         public final String content; |  | ||||||
|         public final String details; |  | ||||||
|  |  | ||||||
|         public PlaceholderItem(String id, String content, String details) { |  | ||||||
|             this.id = id; |  | ||||||
|             this.content = content; |  | ||||||
|             this.details = details; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         @Override |  | ||||||
|         public String toString() { |  | ||||||
|             return content; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @@ -19,7 +19,7 @@ import com.google.android.material.snackbar.Snackbar; | |||||||
| import com.majinnaibu.monstercards.R; | import com.majinnaibu.monstercards.R; | ||||||
| import com.majinnaibu.monstercards.data.MonsterRepository; | import com.majinnaibu.monstercards.data.MonsterRepository; | ||||||
| import com.majinnaibu.monstercards.models.Monster; | import com.majinnaibu.monstercards.models.Monster; | ||||||
| import com.majinnaibu.monstercards.ui.MCFragment; | import com.majinnaibu.monstercards.ui.shared.MCFragment; | ||||||
| import com.majinnaibu.monstercards.ui.shared.SwipeToDeleteCallback; | import com.majinnaibu.monstercards.ui.shared.SwipeToDeleteCallback; | ||||||
| import com.majinnaibu.monstercards.utils.Logger; | import com.majinnaibu.monstercards.utils.Logger; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -26,7 +26,7 @@ import com.majinnaibu.monstercards.data.MonsterRepository; | |||||||
| import com.majinnaibu.monstercards.helpers.CommonMarkHelper; | import com.majinnaibu.monstercards.helpers.CommonMarkHelper; | ||||||
| import com.majinnaibu.monstercards.helpers.StringHelper; | import com.majinnaibu.monstercards.helpers.StringHelper; | ||||||
| import com.majinnaibu.monstercards.models.Monster; | 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 com.majinnaibu.monstercards.utils.Logger; | ||||||
|  |  | ||||||
| import java.util.UUID; | import java.util.UUID; | ||||||
| @@ -241,10 +241,15 @@ public class MonsterDetailFragment extends MCFragment { | |||||||
|     @Override |     @Override | ||||||
|     public boolean onOptionsItemSelected(@NonNull MenuItem item) { |     public boolean onOptionsItemSelected(@NonNull MenuItem item) { | ||||||
|         if (item.getItemId() == R.id.menu_action_edit_monster) { |         if (item.getItemId() == R.id.menu_action_edit_monster) { | ||||||
|             NavDirections action = MonsterDetailFragmentDirections.actionNavigationMonsterToEditMonsterFragment(monsterDetailViewModel.getId().getValue().toString()); |             UUID monsterId = monsterDetailViewModel.getId().getValue(); | ||||||
|             View view = getView(); |             if (monsterId != null) { | ||||||
|             assert view != null; |                 NavDirections action = MonsterDetailFragmentDirections.actionNavigationMonsterToEditMonsterFragment(monsterId.toString()); | ||||||
|             Navigation.findNavController(view).navigate(action); |                 View view = getView(); | ||||||
|  |                 assert view != null; | ||||||
|  |                 Navigation.findNavController(view).navigate(action); | ||||||
|  |             } else { | ||||||
|  |                 Logger.logWTF("monsterId cannot be null."); | ||||||
|  |             } | ||||||
|             return true; |             return true; | ||||||
|         } |         } | ||||||
|         return super.onOptionsItemSelected(item); |         return super.onOptionsItemSelected(item); | ||||||
|   | |||||||
| @@ -14,10 +14,10 @@ import androidx.recyclerview.widget.RecyclerView; | |||||||
|  |  | ||||||
| import com.majinnaibu.monstercards.R; | import com.majinnaibu.monstercards.R; | ||||||
| import com.majinnaibu.monstercards.data.MonsterRepository; | import com.majinnaibu.monstercards.data.MonsterRepository; | ||||||
| import com.majinnaibu.monstercards.ui.MCFragment; | import com.majinnaibu.monstercards.ui.shared.MCFragment; | ||||||
|  |  | ||||||
| public class SearchFragment extends MCFragment { | public class SearchFragment extends MCFragment { | ||||||
|      |  | ||||||
|     public View onCreateView(@NonNull LayoutInflater inflater, |     public View onCreateView(@NonNull LayoutInflater inflater, | ||||||
|                              ViewGroup container, Bundle savedInstanceState) { |                              ViewGroup container, Bundle savedInstanceState) { | ||||||
|         View root = inflater.inflate(R.layout.fragment_search, container, false); |         View root = inflater.inflate(R.layout.fragment_search, container, false); | ||||||
|   | |||||||
| @@ -13,6 +13,8 @@ import com.majinnaibu.monstercards.data.MonsterRepository; | |||||||
| import com.majinnaibu.monstercards.models.Monster; | import com.majinnaibu.monstercards.models.Monster; | ||||||
| import com.majinnaibu.monstercards.utils.Logger; | import com.majinnaibu.monstercards.utils.Logger; | ||||||
|  |  | ||||||
|  | import org.jetbrains.annotations.NotNull; | ||||||
|  |  | ||||||
| import java.util.ArrayList; | import java.util.ArrayList; | ||||||
| import java.util.List; | import java.util.List; | ||||||
|  |  | ||||||
| @@ -20,16 +22,11 @@ import io.reactivex.rxjava3.core.Flowable; | |||||||
| import io.reactivex.rxjava3.disposables.Disposable; | import io.reactivex.rxjava3.disposables.Disposable; | ||||||
|  |  | ||||||
| public class SearchResultsRecyclerViewAdapter extends RecyclerView.Adapter<SearchResultsRecyclerViewAdapter.ViewHolder> { | public class SearchResultsRecyclerViewAdapter extends RecyclerView.Adapter<SearchResultsRecyclerViewAdapter.ViewHolder> { | ||||||
|     public interface ItemCallback { |  | ||||||
|         void onItem(Monster monster); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     private final MonsterRepository mRepository; |     private final MonsterRepository mRepository; | ||||||
|  |     private final ItemCallback mOnClickHandler; | ||||||
|     private String mSearchText; |     private String mSearchText; | ||||||
|     private List<Monster> mValues; |     private List<Monster> mValues; | ||||||
|     private Disposable mSubscriptionHandler; |     private Disposable mSubscriptionHandler; | ||||||
|     private final ItemCallback mOnClickHandler; |  | ||||||
|  |  | ||||||
|     public SearchResultsRecyclerViewAdapter(MonsterRepository repository, |     public SearchResultsRecyclerViewAdapter(MonsterRepository repository, | ||||||
|                                             ItemCallback onClick) { |                                             ItemCallback onClick) { | ||||||
|         mRepository = repository; |         mRepository = repository; | ||||||
| @@ -54,6 +51,7 @@ public class SearchResultsRecyclerViewAdapter extends RecyclerView.Adapter<Searc | |||||||
|                 throwable -> Logger.logError("Error performing search", throwable)); |                 throwable -> Logger.logError("Error performing search", throwable)); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     @NotNull | ||||||
|     @Override |     @Override | ||||||
|     public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { |     public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { | ||||||
|         View view = LayoutInflater.from(parent.getContext()) |         View view = LayoutInflater.from(parent.getContext()) | ||||||
| @@ -79,7 +77,11 @@ public class SearchResultsRecyclerViewAdapter extends RecyclerView.Adapter<Searc | |||||||
|         return mValues.size(); |         return mValues.size(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     class ViewHolder extends RecyclerView.ViewHolder { |     public interface ItemCallback { | ||||||
|  |         void onItem(Monster monster); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public static class ViewHolder extends RecyclerView.ViewHolder { | ||||||
|         final TextView mIdView; |         final TextView mIdView; | ||||||
|         final TextView mContentView; |         final TextView mContentView; | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Tom Hicks
						Tom Hicks