diff --git a/Icons/cauldron-svgrepo-com.svg b/Icons/cauldron-svgrepo-com.svg
new file mode 100644
index 00000000..4e623770
--- /dev/null
+++ b/Icons/cauldron-svgrepo-com.svg
@@ -0,0 +1,36 @@
+
+
+
\ No newline at end of file
diff --git a/app/build.gradle b/app/build.gradle
index f4eb5b3b..d7ab3794 100755
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -1,5 +1,5 @@
apply plugin: 'com.android.application'
-apply plugin: 'placeholder-resolver'
+apply plugin: 'com.likethesalad.stem'
android {
signingConfigs {
@@ -21,8 +21,8 @@ android {
signingConfig signingConfigs.release
}
compileOptions {
- sourceCompatibility JavaVersion.VERSION_1_8
- targetCompatibility JavaVersion.VERSION_1_8
+ sourceCompatibility JavaVersion.VERSION_11
+ targetCompatibility JavaVersion.VERSION_11
}
buildTypes {
release {
@@ -39,29 +39,38 @@ android {
viewBinding true
dataBinding true
}
- stringXmlReference {
- keepResolvedFiles = true
- }
testOptions {
unitTests {
includeAndroidResources = true
}
}
- lintOptions {
+ lint {
abortOnError false
}
+ namespace 'dnd.jon.spellbook'
}
dependencies {
+ implementation 'androidx.navigation:navigation-runtime:2.5.2'
+ constraints {
+ implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.8.0") {
+ because 'align all versions of Kotlin transitive dependencies'
+ }
+ }
+ def nav_version = "2.6.0"
+
implementation fileTree(include: ['*.jar'], dir: 'libs')
- implementation 'androidx.core:core:1.6.0'
- implementation 'androidx.appcompat:appcompat:1.3.1'
- implementation 'androidx.fragment:fragment:1.4.0'
- implementation 'androidx.lifecycle:lifecycle-livedata:2.3.1'
+ implementation 'androidx.core:core:1.10.1'
+ implementation 'androidx.appcompat:appcompat:1.6.1'
+ implementation 'androidx.fragment:fragment:1.6.1'
+ implementation 'androidx.lifecycle:lifecycle-livedata:2.6.2'
+ implementation "androidx.navigation:navigation-fragment:$nav_version"
+ implementation "androidx.navigation:navigation-ui:$nav_version"
+
//implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
- implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
- implementation 'androidx.preference:preference:1.1.1'
- implementation 'com.google.android.material:material:1.4.0'
+ implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
+ implementation 'androidx.preference:preference:1.2.1'
+ implementation 'com.google.android.material:material:1.9.0'
implementation "androidx.gridlayout:gridlayout:1.0.0"
implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.1.0"
implementation 'com.github.deano2390:MaterialShowcaseView:1.3.4'
@@ -72,13 +81,17 @@ dependencies {
implementation 'com.github.kizitonwose.colorpreference:support:1.1.0'
implementation 'com.github.skydoves:colorpickerview:2.2.4'
implementation 'io.github.cdimascio:dotenv-java:2.2.4'
+ implementation "com.leinardi.android:speed-dial:3.3.0"
//implementation 'org.sufficientlysecure:html-textview:4.0'
+
testImplementation 'junit:junit:4.13.1'
- testImplementation 'androidx.test:core:1.4.0'
+ testImplementation 'androidx.test:core:1.5.0'
testImplementation 'com.google.truth:truth:1.1.2'
testImplementation 'org.robolectric:robolectric:4.4'
testImplementation 'org.json:json:20180813'
- androidTestImplementation 'androidx.test.ext:junit:1.1.3'
- androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
+ androidTestImplementation 'androidx.test.ext:junit:1.1.5'
+ androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
implementation files('libs/commons-lang3-3.8.jar')
}
+
+
diff --git a/app/release/app-release.aab b/app/release/app-release.aab
new file mode 100644
index 00000000..3ea3d45c
Binary files /dev/null and b/app/release/app-release.aab differ
diff --git a/app/src/debug/res/drawable-anydpi/ic_add_white.xml b/app/src/debug/res/drawable-anydpi/ic_add_white.xml
new file mode 100644
index 00000000..672478e3
--- /dev/null
+++ b/app/src/debug/res/drawable-anydpi/ic_add_white.xml
@@ -0,0 +1,11 @@
+
+
+
diff --git a/app/src/debug/res/drawable-anydpi/ic_close_white.xml b/app/src/debug/res/drawable-anydpi/ic_close_white.xml
new file mode 100644
index 00000000..6d8f2825
--- /dev/null
+++ b/app/src/debug/res/drawable-anydpi/ic_close_white.xml
@@ -0,0 +1,11 @@
+
+
+
diff --git a/app/src/debug/res/drawable-anydpi/ic_delete.xml b/app/src/debug/res/drawable-anydpi/ic_delete.xml
new file mode 100644
index 00000000..18b7e774
--- /dev/null
+++ b/app/src/debug/res/drawable-anydpi/ic_delete.xml
@@ -0,0 +1,11 @@
+
+
+
diff --git a/app/src/debug/res/drawable-hdpi/ic_add_white.png b/app/src/debug/res/drawable-hdpi/ic_add_white.png
new file mode 100644
index 00000000..9a20be84
Binary files /dev/null and b/app/src/debug/res/drawable-hdpi/ic_add_white.png differ
diff --git a/app/src/debug/res/drawable-hdpi/ic_close_white.png b/app/src/debug/res/drawable-hdpi/ic_close_white.png
new file mode 100644
index 00000000..8a4491ab
Binary files /dev/null and b/app/src/debug/res/drawable-hdpi/ic_close_white.png differ
diff --git a/app/src/debug/res/drawable-hdpi/ic_delete.png b/app/src/debug/res/drawable-hdpi/ic_delete.png
new file mode 100644
index 00000000..bde3d479
Binary files /dev/null and b/app/src/debug/res/drawable-hdpi/ic_delete.png differ
diff --git a/app/src/debug/res/drawable-mdpi/ic_add_white.png b/app/src/debug/res/drawable-mdpi/ic_add_white.png
new file mode 100644
index 00000000..be6d6259
Binary files /dev/null and b/app/src/debug/res/drawable-mdpi/ic_add_white.png differ
diff --git a/app/src/debug/res/drawable-mdpi/ic_close_white.png b/app/src/debug/res/drawable-mdpi/ic_close_white.png
new file mode 100644
index 00000000..81f85b02
Binary files /dev/null and b/app/src/debug/res/drawable-mdpi/ic_close_white.png differ
diff --git a/app/src/debug/res/drawable-mdpi/ic_delete.png b/app/src/debug/res/drawable-mdpi/ic_delete.png
new file mode 100644
index 00000000..f5f1e1eb
Binary files /dev/null and b/app/src/debug/res/drawable-mdpi/ic_delete.png differ
diff --git a/app/src/debug/res/drawable-xhdpi/ic_add_white.png b/app/src/debug/res/drawable-xhdpi/ic_add_white.png
new file mode 100644
index 00000000..6eedadfb
Binary files /dev/null and b/app/src/debug/res/drawable-xhdpi/ic_add_white.png differ
diff --git a/app/src/debug/res/drawable-xhdpi/ic_close_white.png b/app/src/debug/res/drawable-xhdpi/ic_close_white.png
new file mode 100644
index 00000000..538ddf1a
Binary files /dev/null and b/app/src/debug/res/drawable-xhdpi/ic_close_white.png differ
diff --git a/app/src/debug/res/drawable-xhdpi/ic_delete.png b/app/src/debug/res/drawable-xhdpi/ic_delete.png
new file mode 100644
index 00000000..13057cbf
Binary files /dev/null and b/app/src/debug/res/drawable-xhdpi/ic_delete.png differ
diff --git a/app/src/debug/res/drawable-xxhdpi/ic_add_white.png b/app/src/debug/res/drawable-xxhdpi/ic_add_white.png
new file mode 100644
index 00000000..7a27534d
Binary files /dev/null and b/app/src/debug/res/drawable-xxhdpi/ic_add_white.png differ
diff --git a/app/src/debug/res/drawable-xxhdpi/ic_close_white.png b/app/src/debug/res/drawable-xxhdpi/ic_close_white.png
new file mode 100644
index 00000000..f45eedf3
Binary files /dev/null and b/app/src/debug/res/drawable-xxhdpi/ic_close_white.png differ
diff --git a/app/src/debug/res/drawable-xxhdpi/ic_delete.png b/app/src/debug/res/drawable-xxhdpi/ic_delete.png
new file mode 100644
index 00000000..ee98d4cd
Binary files /dev/null and b/app/src/debug/res/drawable-xxhdpi/ic_delete.png differ
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index b2c8b0a0..6f8eee0b 100755
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -1,6 +1,5 @@
-
+
screenDimensions(Activity activity) {
+ final DisplayMetrics displayMetrics = new DisplayMetrics();
+ activity.getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
+ return new Pair<>(displayMetrics.widthPixels, displayMetrics.heightPixels);
+ }
+}
diff --git a/app/src/main/java/dnd/jon/spellbook/CastingTime.java b/app/src/main/java/dnd/jon/spellbook/CastingTime.java
index 18652569..aee125de 100755
--- a/app/src/main/java/dnd/jon/spellbook/CastingTime.java
+++ b/app/src/main/java/dnd/jon/spellbook/CastingTime.java
@@ -66,6 +66,9 @@ public static CastingTimeType fromInternalName(String name) {
// Convenience constructors
CastingTime(CastingTimeType type, float value, TimeUnit unit, String str) { super(type, value, unit, str); }
+ CastingTime(CastingTimeType type, float value, TimeUnit unit) { super(type, value, unit); }
+ CastingTime(CastingTimeType type, float value) { super(type, value, TimeUnit.SECOND); }
+ CastingTime(CastingTimeType type) { this(type, 1); }
CastingTime() { this(CastingTimeType.ACTION, 1, TimeUnit.SECOND, ""); }
// For Parcelable
@@ -83,17 +86,13 @@ private CastingTime(Parcel in) {
String makeString(boolean useStored, Function typeNameGetter, Function unitSingularNameGetter, Function unitPluralNameGetter) {
if (useStored && !str.isEmpty()) { return str; }
final String name = typeNameGetter.apply(type);
- final String valueString = DisplayUtils.DECIMAL_FORMAT.format(value);
if (type == CastingTimeType.TIME) {
+ final String valueString = DisplayUtils.DECIMAL_FORMAT.format(value);
final Function unitNameGetter = (value == 1) ? unitSingularNameGetter : unitPluralNameGetter;
final String unitStr = unitNameGetter.apply(unit);
return valueString + " " + unitStr;
} else {
- String typeStr = name;
- if (value != 1) {
- typeStr += "s";
- }
- return valueString + " " + typeStr;
+ return name;
}
}
@@ -108,22 +107,27 @@ String internalString() {
// Create a range from a string
static CastingTime fromString(String s, Function typeNameGetter, Function timeUnitMaker, boolean useForStr) {
try {
+
String[] sSplit = s.split(" ", 2);
- final float value = Float.parseFloat(sSplit[0]);
- final String typeStr = sSplit[1];
- //System.out.println("sSplit0: " + sSplit[0]);
- //System.out.println("sSplit1: " + sSplit[1]);
+ float value = 1;
+ String typeStr = "";
+ try {
+ value = Float.parseFloat(sSplit[0]);
+ typeStr = sSplit[1];
+ } catch (NumberFormatException e) {
+ e.printStackTrace();
+ }
// If the type is one of the action types
CastingTimeType type = null;
for (CastingTimeType ct : CastingTimeType.actionTypes) {
- if (typeStr.startsWith(typeNameGetter.apply(ct))) {
+ final String typeName = typeNameGetter.apply(ct);
+ if (s.startsWith(typeName) || typeStr.startsWith(typeName)) {
type = ct;
break;
}
}
if (type != null) {
- //final int inRounds = value * SECONDS_PER_ROUND;
final String str = useForStr ? s : "";
return new CastingTime(type, 1, TimeUnit.SECOND, str);
}
diff --git a/app/src/main/java/dnd/jon/spellbook/CenterReveal.java b/app/src/main/java/dnd/jon/spellbook/CenterReveal.java
index 0c2dfe65..89d903ac 100644
--- a/app/src/main/java/dnd/jon/spellbook/CenterReveal.java
+++ b/app/src/main/java/dnd/jon/spellbook/CenterReveal.java
@@ -12,17 +12,15 @@
public class CenterReveal {
private final View view;
- private final View container;
- private ObjectAnimator viewTranslation;
- private ObjectAnimator viewAlpha;
- private ObjectAnimator viewScale;
- private ObjectAnimator containerAlpha;
+ private final ObjectAnimator viewTranslation;
+ private final ObjectAnimator viewAlpha;
+ private final ObjectAnimator viewScale;
+ private final ObjectAnimator containerAlpha;
private static final long duration = 150L;
CenterReveal(View view, View container) {
this.view = view;
- this.container = container;
final ViewGroup parent = (ViewGroup) view.getParent();
final ViewGroup.MarginLayoutParams marginLayoutParams = (ViewGroup.MarginLayoutParams) view.getLayoutParams();
final float cX = marginLayoutParams.getMarginEnd() + view.getWidth() / 2f - parent.getWidth() / 2f;
diff --git a/app/src/main/java/dnd/jon/spellbook/CharacterAdapter.java b/app/src/main/java/dnd/jon/spellbook/CharacterAdapter.java
index bd5c1e8b..3be085e5 100644
--- a/app/src/main/java/dnd/jon/spellbook/CharacterAdapter.java
+++ b/app/src/main/java/dnd/jon/spellbook/CharacterAdapter.java
@@ -6,6 +6,7 @@
import android.content.Intent;
import android.os.Bundle;
import android.view.LayoutInflater;
+import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.PopupMenu;
@@ -20,6 +21,10 @@
public class CharacterAdapter extends NamedItemAdapter {
+ private static final String confirmDeleteTag = "confirmDeleteCharacter";
+ private static final String duplicateTag = "duplicateCharacter";
+ private static final String renameTag = "changeCharacterName";
+
CharacterAdapter(FragmentActivity fragmentActivity) {
super(fragmentActivity, SpellbookViewModel::currentCharacterNames);
}
@@ -47,26 +52,30 @@ public void bind(String name) {
binding.optionsButton.setOnClickListener((View v) -> {
final PopupMenu popupMenu = new PopupMenu(activity, binding.optionsButton);
popupMenu.inflate(R.menu.options_menu);
+ final MenuItem updateItem = popupMenu.getMenu().findItem(R.id.options_update);
+ if (updateItem != null) {
+ updateItem.setTitle(R.string.rename);
+ }
popupMenu.setOnMenuItemClickListener((menuItem) -> {
final int itemID = menuItem.getItemId();
- if (itemID == R.id.options_rename) {
+ if (itemID == R.id.options_update) {
final Bundle args = new Bundle();
args.putString(NameChangeDialog.nameKey, binding.getName());
final CharacterNameChangeDialog dialog = new CharacterNameChangeDialog();
dialog.setArguments(args);
- dialog.show(activity.getSupportFragmentManager(), "changeCharacterName");
+ dialog.show(activity.getSupportFragmentManager(), renameTag);
} else if (itemID == R.id.options_duplicate) {
final Bundle args = new Bundle();
args.putParcelable(CreateCharacterDialog.PROFILE_KEY, viewModel.getProfileByName(binding.getName()));
final CreateCharacterDialog dialog = new CreateCharacterDialog();
dialog.setArguments(args);
- dialog.show(activity.getSupportFragmentManager(), "duplicateCharacter");
+ dialog.show(activity.getSupportFragmentManager(), duplicateTag);
} else if (itemID == R.id.options_delete) {
final Bundle args = new Bundle();
args.putString(DeleteCharacterDialog.NAME_KEY, binding.getName());
final DeleteCharacterDialog dialog = new DeleteCharacterDialog();
dialog.setArguments(args);
- dialog.show(activity.getSupportFragmentManager(), "confirmDeleteCharacter");
+ dialog.show(activity.getSupportFragmentManager(), confirmDeleteTag);
} else if (itemID == R.id.options_export) {
// String permissionNeeded;
// if (GlobalInfo.ANDROID_VERSION >= Build.VERSION_CODES.R) {
diff --git a/app/src/main/java/dnd/jon/spellbook/CharacterProfile.java b/app/src/main/java/dnd/jon/spellbook/CharacterProfile.java
index adda28f5..3d1b6906 100755
--- a/app/src/main/java/dnd/jon/spellbook/CharacterProfile.java
+++ b/app/src/main/java/dnd/jon/spellbook/CharacterProfile.java
@@ -215,7 +215,6 @@ public JSONObject toJSON() throws JSONException {
// Construct a profile from a JSON object
// Basically the inverse to toJSON
static CharacterProfile fromJSON(JSONObject json) throws JSONException {
- //System.out.println(json.toString(4));
if (json.has(versionCodeKey)) {
final String versionCode = json.getString(versionCodeKey);
final Version version = SpellbookUtils.coalesce(Version.fromString(versionCode), GlobalInfo.VERSION);
@@ -356,7 +355,7 @@ private static CharacterProfile fromJSONNew(JSONObject json, Version version) th
final EnumSet visibleCasterClasses = visibleSetFromLegacyJSON(json, CasterClass.class);
final EnumSet visibleSchools = visibleSetFromLegacyJSON(json, School.class);
- final Set