diff --git a/Android/app/src/main/AndroidManifest.xml b/Android/app/src/main/AndroidManifest.xml
index c9d60dd..70129c6 100644
--- a/Android/app/src/main/AndroidManifest.xml
+++ b/Android/app/src/main/AndroidManifest.xml
@@ -12,6 +12,40 @@
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -22,4 +56,5 @@
-
\ No newline at end of file
+
+
diff --git a/Android/app/src/main/java/com/majinnaibu/monstercards/ImportMonsterActivity.java b/Android/app/src/main/java/com/majinnaibu/monstercards/ImportMonsterActivity.java
new file mode 100644
index 0000000..030f8cc
--- /dev/null
+++ b/Android/app/src/main/java/com/majinnaibu/monstercards/ImportMonsterActivity.java
@@ -0,0 +1,318 @@
+package com.majinnaibu.monstercards;
+
+import android.content.Intent;
+import android.content.res.Resources;
+import android.net.Uri;
+import android.os.Bundle;
+import android.text.Html;
+import android.text.Spanned;
+import android.util.DisplayMetrics;
+import android.util.TypedValue;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.lifecycle.ViewModelProvider;
+
+import com.google.android.material.snackbar.Snackbar;
+import com.majinnaibu.monstercards.data.MonsterRepository;
+import com.majinnaibu.monstercards.helpers.CommonMarkHelper;
+import com.majinnaibu.monstercards.helpers.MonsterImportHelper;
+import com.majinnaibu.monstercards.helpers.StringHelper;
+import com.majinnaibu.monstercards.models.Monster;
+import com.majinnaibu.monstercards.ui.monster.MonsterDetailViewModel;
+import com.majinnaibu.monstercards.utils.Logger;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.List;
+import java.util.Objects;
+import java.util.UUID;
+
+import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
+import io.reactivex.rxjava3.observers.DisposableCompletableObserver;
+import io.reactivex.rxjava3.schedulers.Schedulers;
+
+public class ImportMonsterActivity extends AppCompatActivity {
+
+ private ViewHolder mHolder;
+
+ private MonsterDetailViewModel mViewModel;
+
+ @Override
+ protected void onCreate(@Nullable @org.jetbrains.annotations.Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.fragment_monster);
+ mHolder = new ViewHolder(findViewById(android.R.id.content));
+ mViewModel = new ViewModelProvider(this).get(MonsterDetailViewModel.class);
+
+ mViewModel.getName().observe(this, mHolder.name::setText);
+ mViewModel.getMeta().observe(this, mHolder.meta::setText);
+ mViewModel.getArmorClass().observe(this, armorText -> setupLabeledTextView(mHolder.armorClass, armorText, R.string.label_armor_class));
+ mViewModel.getHitPoints().observe(this, hitPoints -> setupLabeledTextView(mHolder.hitPoints, hitPoints, R.string.label_hit_points));
+ mViewModel.getSpeed().observe(this, speed -> setupLabeledTextView(mHolder.speed, speed, R.string.label_speed));
+ mViewModel.getStrength().observe(this, mHolder.strength::setText);
+ mViewModel.getDexterity().observe(this, mHolder.dexterity::setText);
+ mViewModel.getConstitution().observe(this, mHolder.constitution::setText);
+ mViewModel.getIntelligence().observe(this, mHolder.intelligence::setText);
+ mViewModel.getWisdom().observe(this, mHolder.wisdom::setText);
+ mViewModel.getCharisma().observe(this, mHolder.charisma::setText);
+ mViewModel.getSavingThrows().observe(this, savingThrows -> setupOptionalTextView(mHolder.savingThrows, savingThrows, R.string.label_saving_throws));
+ mViewModel.getSkills().observe(this, skills -> setupOptionalTextView(mHolder.skills, skills, R.string.label_skills));
+ mViewModel.getDamageVulnerabilities().observe(this, damageTypes -> setupOptionalTextView(mHolder.damageVulnerabilities, damageTypes, R.string.label_damage_vulnerabilities));
+ mViewModel.getDamageResistances().observe(this, damageTypes -> setupOptionalTextView(mHolder.damageResistances, damageTypes, R.string.label_damage_resistances));
+ mViewModel.getDamageImmunities().observe(this, damageTypes -> setupOptionalTextView(mHolder.damageImmunities, damageTypes, R.string.label_damage_immunities));
+ mViewModel.getConditionImmunities().observe(this, conditionImmunities -> setupOptionalTextView(mHolder.conditionImmunities, conditionImmunities, R.string.label_condition_immunities));
+ mViewModel.getSenses().observe(this, senses -> setupOptionalTextView(mHolder.senses, senses, R.string.label_senses));
+ mViewModel.getLanguages().observe(this, languages -> setupOptionalTextView(mHolder.languages, languages, R.string.label_languages));
+ mViewModel.getChallenge().observe(this, challengeRating -> setupLabeledTextView(mHolder.challenge, challengeRating, R.string.label_challenge_rating));
+ mViewModel.getAbilities().observe(this, abilities -> setupTraitList(mHolder.abilities, abilities));
+ mViewModel.getActions().observe(this, actions -> setupTraitList(mHolder.actions, actions, mHolder.actions_label, mHolder.actions_divider));
+ mViewModel.getReactions().observe(this, reactions -> setupTraitList(mHolder.reactions, reactions, mHolder.reactions_label, mHolder.reactions_divider));
+ mViewModel.getRegionalEffects().observe(this, regionalEffects -> setupTraitList(mHolder.regionalEffects, regionalEffects, mHolder.regionalEffects_label, mHolder.regionalEffects_divider));
+ mViewModel.getLairActions().observe(this, lairActions -> setupTraitList(mHolder.lairActions, lairActions, mHolder.lairActions_label, mHolder.lairActions_divider));
+ mViewModel.getLegendaryActions().observe(this, legendaryActions -> setupTraitList(mHolder.legendaryActions, legendaryActions, mHolder.legendaryActions_label, mHolder.legendaryActions_divider));
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ Logger.logDebug("onCreateView");
+ Monster monster = readMonsterFromIntent(getIntent());
+ if (monster != null) {
+ mViewModel.setMonster(monster);
+ }
+ }
+
+ private Monster readMonsterFromIntent(Intent intent) {
+ String action = intent.getAction();
+ Bundle extras = intent.getExtras();
+ String type = intent.getType();
+ String json;
+ Uri uri = null;
+ if ("android.intent.action.SEND".equals(action) && "text/plain".equals(type)) {
+ uri = extras.getParcelable("android.intent.extra.STREAM");
+ } else if ("android.intent.action.VIEW".equals(action) && ("text/plain".equals(type) || "application/octet-stream".equals(type))) {
+ uri = intent.getData();
+ } else {
+ Logger.logError(String.format("unexpected launch configuration action: %s, type: %s, uri: %s", action, type, uri));
+ }
+ if (uri == null) {
+ return null;
+ }
+ json = readContentsOfUri(uri);
+ if (StringHelper.isNullOrEmpty(json)) {
+ return null;
+ }
+ return MonsterImportHelper.fromJSON(json);
+ }
+
+ private String readContentsOfUri(Uri uri) {
+ StringBuilder builder = new StringBuilder();
+ try (InputStream inputStream =
+ getContentResolver().openInputStream(uri);
+ BufferedReader reader = new BufferedReader(
+ new InputStreamReader(Objects.requireNonNull(inputStream)))) {
+ String line;
+ while ((line = reader.readLine()) != null) {
+ builder.append(line);
+ }
+ } catch (IOException e) {
+ Logger.logError("error reading file", e);
+ return null;
+ }
+ return builder.toString();
+ }
+
+ @Override
+ protected void onNewIntent(Intent intent) {
+ super.onNewIntent(intent);
+ setIntent(intent);
+ }
+
+ private void setupLabeledTextView(TextView view, String text, int titleId) {
+ String title = getString(titleId);
+ String fullText = String.format("%s %s", title, text);
+ view.setText(Html.fromHtml(fullText));
+ }
+
+ private void setupOptionalTextView(TextView root, String text, int titleId) {
+ String title = getString(titleId);
+ if (StringHelper.isNullOrEmpty(text)) {
+ root.setVisibility(View.GONE);
+ } else {
+ root.setVisibility(View.VISIBLE);
+ }
+ Spanned formatted;
+ if (StringHelper.isNullOrEmpty(title)) {
+ formatted = Html.fromHtml(text);
+ } else {
+ formatted = Html.fromHtml(String.format("%s %s", title, text));
+ }
+ root.setText(formatted);
+ }
+
+ private void setupTraitList(@NonNull LinearLayout root, @NonNull List traits) {
+ setupTraitList(root, traits, null, null);
+ }
+
+ private void setupTraitList(@NonNull LinearLayout root, @NonNull List traits, View label, View divider) {
+ int visibility = traits.size() > 0 ? View.VISIBLE : View.GONE;
+ DisplayMetrics displayMetrics = null;
+ Resources resources = getResources();
+ if (resources != null) {
+ displayMetrics = resources.getDisplayMetrics();
+ }
+ root.removeAllViews();
+ for (String action : traits) {
+ TextView tvAction = new TextView(this);
+ // TODO: Handle multiline block quotes specially so they stay multiline.
+ // TODO: Replace QuoteSpans in the result of fromHtml with something like this https://stackoverflow.com/questions/7717567/how-to-style-blockquotes-in-android-textviews to make them indent as expected
+ tvAction.setText(Html.fromHtml(CommonMarkHelper.toHtml(action)));
+ LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
+ layoutParams.topMargin = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 8, displayMetrics);
+ tvAction.setLayoutParams(layoutParams);
+ root.addView(tvAction);
+ }
+ root.setVisibility(visibility);
+ if (label != null) {
+ label.setVisibility(visibility);
+ }
+ if (divider != null) {
+ divider.setVisibility(visibility);
+ }
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(@NonNull Menu menu) {
+ getMenuInflater().inflate(R.menu.import_monster, menu);
+ return true;
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(@NonNull MenuItem item) {
+ if (item.getItemId() == R.id.menu_action_import_monster) {
+ Logger.logDebug("Menu Item Selected");
+ Monster monster = mViewModel.getMonster();
+ if (monster != null) {
+ monster.id = UUID.randomUUID();
+ MonsterCardsApplication application = (MonsterCardsApplication) getApplication();
+ MonsterRepository repository = application.getMonsterRepository();
+ repository.addMonster(monster).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(new DisposableCompletableObserver() {
+ @Override
+ public void onComplete() {
+ Snackbar.make(
+ mHolder.root,
+ getString(R.string.snackbar_monster_created, monster.name),
+ Snackbar.LENGTH_LONG)
+ .setAction("Action", (_view) -> navigateToEditMonster(monster.id))
+ .show();
+ }
+
+ @Override
+ public void onError(@io.reactivex.rxjava3.annotations.NonNull Throwable e) {
+ Logger.logError("Error creating monster", e);
+ Snackbar.make(mHolder.root, getString(R.string.snackbar_failed_to_create_monster), Snackbar.LENGTH_LONG).show();
+ }
+ });
+ } else {
+ Logger.logWTF("monsterId cannot be null.");
+ }
+ return true;
+ }
+ return super.onOptionsItemSelected(item);
+ }
+
+ private void navigateToEditMonster(UUID monsterId) {
+ Logger.logUnimplementedFeature(String.format("navigate to editing the monster %s", monsterId));
+ }
+
+ private static class ViewHolder {
+ final View root;
+ final TextView name;
+ final TextView meta;
+ final TextView armorClass;
+ final TextView hitPoints;
+ final TextView speed;
+ final TextView strength;
+ final TextView dexterity;
+ final TextView constitution;
+ final TextView intelligence;
+ final TextView wisdom;
+ final TextView charisma;
+ final TextView savingThrows;
+ final TextView skills;
+ final TextView damageVulnerabilities;
+ final TextView damageResistances;
+ final TextView damageImmunities;
+ final TextView conditionImmunities;
+ final TextView senses;
+ final TextView languages;
+ final TextView challenge;
+ final LinearLayout abilities;
+ final LinearLayout actions;
+ final TextView actions_label;
+ final ImageView actions_divider;
+ final LinearLayout reactions;
+ final TextView reactions_label;
+ final ImageView reactions_divider;
+ final LinearLayout legendaryActions;
+ final TextView legendaryActions_label;
+ final ImageView legendaryActions_divider;
+ final LinearLayout lairActions;
+ final TextView lairActions_label;
+ final ImageView lairActions_divider;
+ final LinearLayout regionalEffects;
+ final TextView regionalEffects_label;
+ final ImageView regionalEffects_divider;
+
+ ViewHolder(View root) {
+ this.root = root;
+ name = root.findViewById(R.id.name);
+ meta = root.findViewById(R.id.meta);
+ armorClass = root.findViewById(R.id.armorClass);
+ hitPoints = root.findViewById(R.id.hitPoints);
+ speed = root.findViewById(R.id.speed);
+ strength = root.findViewById(R.id.strength);
+ dexterity = root.findViewById(R.id.dexterity);
+ constitution = root.findViewById(R.id.constitution);
+ intelligence = root.findViewById(R.id.intelligence);
+ wisdom = root.findViewById(R.id.wisdom);
+ charisma = root.findViewById(R.id.charisma);
+ savingThrows = root.findViewById(R.id.savingThrows);
+ skills = root.findViewById(R.id.skills);
+ damageVulnerabilities = root.findViewById(R.id.damageVulnerabilities);
+ damageResistances = root.findViewById(R.id.damageResistances);
+ damageImmunities = root.findViewById(R.id.damageImmunities);
+ conditionImmunities = root.findViewById(R.id.conditionImmunities);
+ senses = root.findViewById(R.id.senses);
+ languages = root.findViewById(R.id.languages);
+ challenge = root.findViewById(R.id.challenge);
+ abilities = root.findViewById(R.id.abilities);
+ actions = root.findViewById(R.id.actions);
+ actions_divider = root.findViewById(R.id.actions_divider);
+ actions_label = root.findViewById(R.id.actions_label);
+ reactions = root.findViewById(R.id.reactions);
+ reactions_divider = root.findViewById(R.id.reactions_divider);
+ reactions_label = root.findViewById(R.id.reactions_label);
+ legendaryActions = root.findViewById(R.id.legendaryActions);
+ legendaryActions_divider = root.findViewById(R.id.legendaryActions_divider);
+ legendaryActions_label = root.findViewById(R.id.legendaryActions_label);
+ lairActions = root.findViewById(R.id.lairActions);
+ lairActions_divider = root.findViewById(R.id.lairActions_divider);
+ lairActions_label = root.findViewById(R.id.lairActions_label);
+ regionalEffects = root.findViewById(R.id.regionalEffects);
+ regionalEffects_divider = root.findViewById(R.id.regionalEffects_divider);
+ regionalEffects_label = root.findViewById(R.id.regionalEffects_label);
+ }
+ }
+}
diff --git a/Android/app/src/main/java/com/majinnaibu/monstercards/helpers/MonsterImportHelper.java b/Android/app/src/main/java/com/majinnaibu/monstercards/helpers/MonsterImportHelper.java
index de7e0e8..a25f0dd 100644
--- a/Android/app/src/main/java/com/majinnaibu/monstercards/helpers/MonsterImportHelper.java
+++ b/Android/app/src/main/java/com/majinnaibu/monstercards/helpers/MonsterImportHelper.java
@@ -1,7 +1,5 @@
package com.majinnaibu.monstercards.helpers;
-import androidx.annotation.NonNull;
-
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
@@ -17,16 +15,17 @@ import com.majinnaibu.monstercards.models.Monster;
import com.majinnaibu.monstercards.models.Skill;
import com.majinnaibu.monstercards.models.Trait;
+import org.jetbrains.annotations.NotNull;
+
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
-import java.util.Locale;
import java.util.Set;
public class MonsterImportHelper {
- @NonNull
public static Monster fromJSON(String json) {
- JsonObject rootDict = JsonParser.parseString(json).getAsJsonObject();
+ JsonParser parser = new JsonParser();
+ JsonObject rootDict = parser.parse(json).getAsJsonObject();
Monster monster = new Monster();
monster.name = Helpers.getString(rootDict, "name");
@@ -111,7 +110,7 @@ public class MonsterImportHelper {
return getString(dict, name, "");
}
- public static String getString(@NonNull JsonObject dict, String name, String defaultValue) {
+ public static String getString(@NotNull JsonObject dict, String name, String defaultValue) {
if (dict.has(name)) {
return dict.get(name).getAsString();
}
@@ -123,19 +122,13 @@ public class MonsterImportHelper {
return getInt(dict, name, 0);
}
- public static int getInt(@NonNull JsonObject dict, String name, int defaultValue) {
+ public static int getInt(@NotNull JsonObject dict, String name, int defaultValue) {
if (dict.has(name)) {
JsonElement element = dict.get(name);
if (element.isJsonPrimitive()) {
- JsonPrimitive rawValue = element.getAsJsonPrimitive();
+ JsonPrimitive rawValue = element.getAsJsonPrimitive();//dict.getAsJsonPrimitive(name);
if (rawValue.isNumber()) {
return rawValue.getAsInt();
- } else {
- try {
- return rawValue.getAsInt();
- } catch (Exception ex) {
- return defaultValue;
- }
}
}
}
@@ -146,29 +139,22 @@ public class MonsterImportHelper {
return getBool(dict, name, false);
}
- public static boolean getBool(@NonNull JsonObject dict, String name, boolean defaultValue) {
+ public static boolean getBool(@NotNull JsonObject dict, String name, boolean defaultValue) {
if (dict.has(name)) {
JsonElement element = dict.get(name);
if (element.isJsonPrimitive()) {
JsonPrimitive rawValue = element.getAsJsonPrimitive();
if (rawValue.isBoolean()) {
return rawValue.getAsBoolean();
- } else {
- try {
- return rawValue.getAsBoolean();
- } catch (Exception ex) {
- return defaultValue;
- }
}
}
}
return defaultValue;
}
- @NonNull
+ @NotNull
public static String formatDistance(String name, int distance) {
- // TODO: consider moving this to a string resource so it can be localized
- return String.format(Locale.getDefault(), "%s %d ft.", name, distance);
+ return String.format("%s %d ft.", name, distance);
}
public static void addSense(Monster monster, JsonObject root, String name) {
@@ -178,8 +164,8 @@ public class MonsterImportHelper {
}
}
- @NonNull
- public static List getListOfTraits(@NonNull JsonObject dict, String name) {
+ @NotNull
+ public static List getListOfTraits(@NotNull JsonObject dict, String name) {
ArrayList traits = new ArrayList<>();
if (dict.has(name)) {
JsonElement arrayElement = dict.get(name);
@@ -191,7 +177,7 @@ public class MonsterImportHelper {
if (jsonElement.isJsonObject()) {
JsonObject jsonObject = jsonElement.getAsJsonObject();
String traitName = Helpers.getString(jsonObject, "name");
- String description = Helpers.getString(jsonObject, "desc");
+ String description = Helpers.getString(jsonObject, "description");
Trait trait = new Trait(traitName, description);
traits.add(trait);
}
@@ -201,7 +187,7 @@ public class MonsterImportHelper {
return traits;
}
- public static void addSavingThrows(Monster monster, @NonNull JsonObject root) {
+ public static void addSavingThrows(Monster monster, JsonObject root) {
if (root.has("sthrows")) {
JsonElement arrayElement = root.get("sthrows");
if (arrayElement.isJsonArray()) {
@@ -231,8 +217,7 @@ public class MonsterImportHelper {
}
}
- @NonNull
- public static Set getSetOfSkills(@NonNull JsonObject root) {
+ public static Set getSetOfSkills(JsonObject root) {
HashSet skills = new HashSet<>();
if (root.has("skills")) {
JsonElement arrayElement = root.get("skills");
@@ -256,13 +241,11 @@ public class MonsterImportHelper {
return skills;
}
- @NonNull
public static Set getSetOfDamageTypes(JsonObject rootDict, String name) {
return getSetOfDamageTypes(rootDict, name, null);
}
- @NonNull
- public static Set getSetOfDamageTypes(@NonNull JsonObject root, String name, String type) {
+ public static Set getSetOfDamageTypes(JsonObject root, String name, String type) {
HashSet damageTypes = new HashSet<>();
if (root.has(name)) {
JsonElement arrayElement = root.get(name);
@@ -285,8 +268,7 @@ public class MonsterImportHelper {
return damageTypes;
}
- @NonNull
- public static Set getSetOfLanguages(@NonNull JsonObject root, String name) {
+ public static Set getSetOfLanguages(JsonObject root, String name) {
HashSet languages = new HashSet<>();
if (root.has(name)) {
JsonElement arrayElement = root.get(name);
diff --git a/Android/app/src/main/java/com/majinnaibu/monstercards/ui/monster/MonsterDetailViewModel.java b/Android/app/src/main/java/com/majinnaibu/monstercards/ui/monster/MonsterDetailViewModel.java
index 95fbb3d..a0b0bed 100644
--- a/Android/app/src/main/java/com/majinnaibu/monstercards/ui/monster/MonsterDetailViewModel.java
+++ b/Android/app/src/main/java/com/majinnaibu/monstercards/ui/monster/MonsterDetailViewModel.java
@@ -12,155 +12,180 @@ import java.util.UUID;
public class MonsterDetailViewModel extends ViewModel {
+ private final MutableLiveData> mAbilities;
+ private final MutableLiveData> mActions;
+ private final MutableLiveData mArmorClass;
+ private final MutableLiveData mChallenge;
+ private final MutableLiveData mCharisma;
+ private final MutableLiveData mConditionImmunities;
+ private final MutableLiveData mConstitution;
+ private final MutableLiveData mDamageResistances;
+ private final MutableLiveData mDamageImmunities;
+ private final MutableLiveData mDamageVulnerabilities;
+ private final MutableLiveData mDexterity;
+ private final MutableLiveData mHitPoints;
+ private final MutableLiveData mIntelligence;
+ private final MutableLiveData> mLairActions;
+ private final MutableLiveData mLanguages;
+ private final MutableLiveData> mLegendaryActions;
+ private final MutableLiveData mMeta;
+ private final MutableLiveData mName;
+ private final MutableLiveData> mReactions;
+ private final MutableLiveData> mRegionalEffects;
+ private final MutableLiveData mSavingThrows;
+ private final MutableLiveData mSenses;
+ private final MutableLiveData mSkills;
+ private final MutableLiveData mSpeed;
+ private final MutableLiveData mStrength;
+ private final MutableLiveData mWisdom;
+ private final MutableLiveData mMonsterId;
+ private Monster mMonster;
+
public MonsterDetailViewModel() {
mMonster = null;
- mAbilities = new MutableLiveData<>();
- mAbilities.setValue(new ArrayList());
- mActions = new MutableLiveData<>();
- mActions.setValue(new ArrayList());
- mArmorClass = new MutableLiveData<>();
- mArmorClass.setValue("");
- mChallenge = new MutableLiveData<>();
- mChallenge.setValue("");
- mCharisma = new MutableLiveData<>();
- mCharisma.setValue("");
- mConditionImmunities = new MutableLiveData<>();
- mConditionImmunities.setValue("");
- mConstitution = new MutableLiveData<>();
- mConstitution.setValue("");
- mDamageImmunities = new MutableLiveData<>();
- mDamageImmunities.setValue("");
- mDamageResistances = new MutableLiveData<>();
- mDamageResistances.setValue("");
- mDamageVulnerabilities = new MutableLiveData<>();
- mDamageVulnerabilities.setValue("");
- mDexterity = new MutableLiveData<>();
- mDexterity.setValue("");
- mHitPoints = new MutableLiveData<>();
- mHitPoints.setValue("");
- mIntelligence = new MutableLiveData<>();
- mIntelligence.setValue("");
- mLanguages = new MutableLiveData<>();
- mLanguages.setValue("");
- mMeta = new MutableLiveData<>();
- mMeta.setValue("");
- mName = new MutableLiveData<>();
- mName.setValue("");
- mSavingThrows = new MutableLiveData<>();
- mSavingThrows.setValue("");
- mSenses = new MutableLiveData<>();
- mSenses.setValue("");
- mSkills = new MutableLiveData<>();
- mSkills.setValue("");
- mSpeed = new MutableLiveData<>();
- mSpeed.setValue("");
- mStrength = new MutableLiveData<>();
- mStrength.setValue("");
- mWisdom = new MutableLiveData<>();
- mWisdom.setValue("");
- mMonsterId = new MutableLiveData<>();
- mMonsterId.setValue(UUID.fromString("00000000-0000-0000-0000-000000000000"));
+ mAbilities = new MutableLiveData<>(new ArrayList<>());
+ mActions = new MutableLiveData<>(new ArrayList<>());
+ mArmorClass = new MutableLiveData<>("");
+ mChallenge = new MutableLiveData<>("");
+ mCharisma = new MutableLiveData<>("");
+ mConditionImmunities = new MutableLiveData<>("");
+ mConstitution = new MutableLiveData<>("");
+ mDamageImmunities = new MutableLiveData<>("");
+ mDamageResistances = new MutableLiveData<>("");
+ mDamageVulnerabilities = new MutableLiveData<>("");
+ mDexterity = new MutableLiveData<>("");
+ mHitPoints = new MutableLiveData<>("");
+ mIntelligence = new MutableLiveData<>("");
+ mLairActions = new MutableLiveData<>(new ArrayList<>());
+ mLanguages = new MutableLiveData<>("");
+ mLegendaryActions = new MutableLiveData<>(new ArrayList<>());
+ mMeta = new MutableLiveData<>("");
+ mName = new MutableLiveData<>("");
+ mReactions = new MutableLiveData<>(new ArrayList<>());
+ mRegionalEffects = new MutableLiveData<>(new ArrayList<>());
+ mSavingThrows = new MutableLiveData<>("");
+ mSenses = new MutableLiveData<>("");
+ mSkills = new MutableLiveData<>("");
+ mSpeed = new MutableLiveData<>("");
+ mStrength = new MutableLiveData<>("");
+ mWisdom = new MutableLiveData<>("");
+ mMonsterId = new MutableLiveData<>(UUID.fromString("00000000-0000-0000-0000-000000000000"));
}
- private MutableLiveData> mAbilities;
public LiveData> getAbilities() {
return mAbilities;
}
- private MutableLiveData> mActions;
+
public LiveData> getActions() {
return mActions;
}
- private MutableLiveData mArmorClass;
+
+ public LiveData> getReactions() {
+ return mReactions;
+ }
+
+ public LiveData> getLegendaryActions() {
+ return mLegendaryActions;
+ }
+
+ public LiveData> getLairActions() {
+ return mLairActions;
+ }
+
+ public LiveData> getRegionalEffects() {
+ return mRegionalEffects;
+ }
+
public LiveData getArmorClass() {
return mArmorClass;
}
- private MutableLiveData mChallenge;
+
public LiveData getChallenge() {
return mChallenge;
}
- private MutableLiveData mCharisma;
+
public LiveData getCharisma() {
return mCharisma;
}
- private MutableLiveData mConditionImmunities;
+
public LiveData getConditionImmunities() {
return mConditionImmunities;
}
- private MutableLiveData mConstitution;
+
public LiveData getConstitution() {
return mConstitution;
}
- private MutableLiveData mDamageResistances;
+
public LiveData getDamageResistances() {
return mDamageResistances;
}
- private MutableLiveData mDamageImmunities;
+
public LiveData getDamageImmunities() {
return mDamageImmunities;
}
- private MutableLiveData mDamageVulnerabilities;
+
public LiveData getDamageVulnerabilities() {
return mDamageVulnerabilities;
}
- private MutableLiveData mDexterity;
+
public LiveData getDexterity() {
return mDexterity;
}
- private MutableLiveData mHitPoints;
+
public LiveData getHitPoints() {
return mHitPoints;
}
- private MutableLiveData mIntelligence;
+
public LiveData getIntelligence() {
return mIntelligence;
}
- private MutableLiveData mLanguages;
+
public LiveData getLanguages() {
return mLanguages;
}
- private MutableLiveData mMeta;
+
public LiveData getMeta() {
return mMeta;
}
- private MutableLiveData mName;
+
public LiveData getName() {
return mName;
}
- private MutableLiveData mSavingThrows;
+
public LiveData getSavingThrows() {
return mSavingThrows;
}
- private MutableLiveData mSenses;
+
public LiveData getSenses() {
return mSenses;
}
- private MutableLiveData mSkills;
+
public LiveData getSkills() {
return mSkills;
}
- private MutableLiveData mSpeed;
+
public LiveData getSpeed() {
return mSpeed;
}
- private MutableLiveData mStrength;
+
public LiveData getStrength() {
return mStrength;
}
- private MutableLiveData mWisdom;
+
public LiveData getWisdom() {
return mWisdom;
}
- private final MutableLiveData mMonsterId;
-
public LiveData getId() {
return mMonsterId;
}
- private Monster mMonster;
+ public Monster getMonster() {
+ return mMonster;
+ }
+
public void setMonster(Monster monster) {
mMonster = monster;
-
mAbilities.setValue(mMonster.getAbilityDescriptions());
mActions.setValue(mMonster.getActionDescriptions());
mArmorClass.setValue(mMonster.getArmorClass());
@@ -174,9 +199,14 @@ public class MonsterDetailViewModel extends ViewModel {
mDexterity.setValue(monster.getDexterityDescription());
mHitPoints.setValue(mMonster.getHitPoints());
mIntelligence.setValue(monster.getIntelligenceDescription());
+ mLairActions.setValue(mMonster.getLairActionDescriptions());
mLanguages.setValue(mMonster.getLanguagesDescription());
+ mLegendaryActions.setValue(mMonster.getLegendaryActionDescriptions());
mMeta.setValue(mMonster.getMeta());
+ mMonsterId.setValue(mMonster.id);
mName.setValue(mMonster.name);
+ mReactions.setValue(monster.getReactionDescriptions());
+ mRegionalEffects.setValue(monster.getRegionalActionDescriptions());
mSavingThrows.setValue(monster.getSavingThrowsDescription());
mSenses.setValue(monster.getSensesDescription());
mSkills.setValue(monster.getSkillsDescription());
@@ -184,4 +214,4 @@ public class MonsterDetailViewModel extends ViewModel {
mStrength.setValue(monster.getStrengthDescription());
mWisdom.setValue(monster.getWisdomDescription());
}
-}
\ No newline at end of file
+}
diff --git a/Android/app/src/main/res/values/strings.xml b/Android/app/src/main/res/values/strings.xml
index aae151f..e0e919e 100644
--- a/Android/app/src/main/res/values/strings.xml
+++ b/Android/app/src/main/res/values/strings.xml
@@ -9,7 +9,7 @@
Add Skill
Add Trait
Edit
- Actions
+ Import Monster
MonsterCards
CHA
CON
@@ -26,6 +26,7 @@
None
Alignment
Armor
+ Armor Class
Base Speed
Basic Info
Burrow Speed
@@ -53,6 +54,7 @@
Has Custom Speed
Has a Shield
Hit Dice
+ Hit Points
+
Intelligence
Lair Actions
@@ -66,7 +68,7 @@
None
Proficient
Reactions
- Regional Actions
+ Regional Effects
Saving Throws
Query
Senses