64 Commits

Author SHA1 Message Date
3dc39ad6a4 cleanup 2025-07-06 20:12:41 -07:00
92ea5b6a0d Moves AppDatabase initialization into the AppDatabase class. 2025-07-06 20:12:40 -07:00
a5eec5c4c8 Moves DiffCallback methods into Monster class. 2025-07-06 20:12:40 -07:00
e598b2984a Adds proguard config. 2025-07-06 20:12:39 -07:00
Tom Hicks
32ae8461b7 Adds functional dashboard based on recycler view that picks the number of columns based on screen width. 2025-07-06 20:12:39 -07:00
Tom Hicks
8686dbdaea Adds dashboard mockup. 2025-07-06 20:12:38 -07:00
Tom Hicks
a8df37325f Adds views for dashboard. 2025-07-06 20:12:38 -07:00
Tom Hicks
2743a8337b Makes radio buttons suck less.
Styles the advantage picker and proficiency picker.
Makes the saving throws screen nicer.
2025-07-06 20:12:37 -07:00
Tom Hicks
b4767676d2 Fixes lists to use similar sized items. 2025-07-06 20:12:37 -07:00
Tom Hicks
7c9037af84 Makes monster importing a fragment in the main activity.
Makes the edit action work when editing an imported monster.
2025-07-06 20:12:36 -07:00
Tom Hicks
c582ba5eaa Adds import monster activity. 2025-07-06 20:12:35 -07:00
Tom Hicks
8b2ab8f48f Adds OnMoveCallback to the SwipeToDeleteCallback class.
Makes traits orderable.
2025-07-06 20:12:34 -07:00
Tom Hicks
2de07c54cc View cleanup.
Makes more numeric fields Steppers.
Sets titles for fragments.
Sets focus on the first EditText on most edit pages.
Makes Checkbox be a SwitchCompat
Fixes monster list item view.
2025-07-06 20:12:33 -07:00
Tom Hicks
c50f79c273 Renames EditTraitListFragment to EditTraitsFragment to match the other list fragments. 2025-07-06 20:12:32 -07:00
Tom Hicks
921a02f953 Replaces condition immunities, damage immunities, damage resistances, damage vulnerabilities, and senses with a unified list of strings editor. 2025-07-06 20:12:30 -07:00
Tom Hicks
ec712842ca Adds editing support for other traits using some shared fragments. 2025-07-06 20:11:56 -07:00
Tom Hicks
2f9dec4d02 Adds ability editor. 2025-07-06 20:11:55 -07:00
Tom Hicks
cb1e3343c9 Adds ability to edit languages. 2025-07-06 20:11:54 -07:00
5bded410d2 ViewModel refactoring. 2025-07-06 20:11:53 -07:00
f6a032844c Fixes default values for array/set properties of monsters in db.
Removes individual senses properties and replaces with a Set<String>.
2025-07-06 20:11:52 -07:00
d214d615e5 Adds edit skill fragment to edit individual skills. 2025-07-06 20:11:51 -07:00
54f863ee5f Adds ability score picker. 2025-07-06 20:11:51 -07:00
d4d298fcc3 Disables annoying lint rule. 2025-07-06 20:11:50 -07:00
7f31d98d7e Adds "New Skill" button. 2025-07-06 20:11:49 -07:00
68348b18c2 Adds edit skills view. 2025-07-06 20:11:49 -07:00
42a2994f2c Adds edit challenge rating screen. 2025-07-06 20:11:49 -07:00
218f39f6c2 Adds better change tracking to know if a monster needs to be saved. 2025-07-06 20:11:48 -07:00
2512bd8d75 Adds saving throws editor. 2025-07-06 20:11:47 -07:00
370d416a23 Adds AdvantagePicker and ProficiencyPicker components. 2025-07-06 20:11:47 -07:00
60d139078b Adds a Stepper control and uses it for the steppers in the editor. 2025-07-06 20:11:46 -07:00
611fa6c323 Adds screen to edit ability scores. 2025-07-06 20:11:45 -07:00
ab5a3c7c67 Adds Edit Speed screen to the monster editor. 2025-07-06 20:11:44 -07:00
b889857e80 Adds Edit Armor screen to edit a monster's armor stats. 2025-07-06 20:11:44 -07:00
da0e072a45 Adds confirmation when going up from the edit monster screen to save, cancel, or discard changes. 2025-07-06 20:11:43 -07:00
e075fc4369 Adds edit basic info screen with most string fields.
Cleans up fonts/margins on edit screens.
Makes the EditMonsterViewModel shared between edit monster fragments.
2025-07-06 20:11:43 -07:00
0db46ebb51 Adds TextChangedListener helper class to make working with text inputs less verbose. 2025-07-06 20:11:42 -07:00
20318b0ad5 Adds top level items to the edit monster view. 2025-07-06 20:11:41 -07:00
6debb1eb27 Replaces EditMonsterFragment with a basic ConstraintLayout. 2025-07-06 20:11:41 -07:00
87c845bd0d Adds Edit Monster placeholder fragment. 2025-07-06 20:11:40 -07:00
f507f9d7cd Adds edit button to monster detail view. 2025-07-06 20:11:40 -07:00
8bb1f64e9f Makes the swipe to delete callback more generic. 2025-07-06 20:11:39 -07:00
f2d0e93911 Fixes a bunch of lint errors and enables Flipper navigation logging. 2025-07-06 20:11:38 -07:00
c9a7e028ae Renames MonsterFragment to MonsterDetailFragment to better explain its use. 2025-07-06 20:11:38 -07:00
807871fe5c Make AppCenter only included in debug builds.
Moves Flipper initialization to the same place as AppCenter.
2025-07-06 20:11:37 -07:00
acadf2170c Adds functional search using sqlite full text search syntax. 2025-07-06 20:11:36 -07:00
8215d2021c Adds DevContent class with dev resources. Specifically an example monster.
Adds a task.
2025-07-06 20:11:35 -07:00
0cbf6022c4 Adds swipe to delete monsters on the library screen. 2025-07-06 20:11:35 -07:00
eec695bfc8 Adds MonsterRepository to manage access to the RoomDB store. 2025-07-06 20:11:34 -07:00
8363912e53 Adds logger. 2025-07-06 20:11:33 -07:00
67db8d79d0 Adds application class. 2025-07-06 20:11:32 -07:00
b5834f3db2 Migrates Monster class to be storable in roomdb. 2025-07-06 20:11:25 -07:00
ca6a319bd9 Creates initial app database class and adds minimal DTO support for monsters. 2025-07-06 20:08:58 -07:00
95ba20b5c6 Adds RoomDB and rxjava3 dependencies. 2025-07-06 20:08:57 -07:00
ea65692b38 Adds abilities to monster cards.
Adds CommonMark dependency and CommonMarkHelper to render it to html.
2025-07-06 20:08:56 -07:00
d7cf01e30d Adds languages to monster cards. 2025-07-06 20:08:56 -07:00
30c6dc7ee5 Adds skills to monster cards. 2025-07-06 20:08:55 -07:00
f13be2c1ac Adds armor class and section divider to monster cards. 2025-07-06 20:08:54 -07:00
920344b5fd Adds monster meta (size, type, subtype/tag, and alignment) to monster cards. 2025-07-06 20:08:54 -07:00
7b3d6003d4 Adds monster name to monster cards. 2025-07-06 20:08:54 -07:00
c837c19b87 Adds Monster fragment to view a monster's card.
Adds query box and search button to search fragment.
Makes the search button show a monster card.
2025-07-06 20:08:53 -07:00
b9759f6364 Adds top level navigation and placeholder fragments. 2025-07-06 20:08:52 -07:00
f24f1d978c Adds debug and release directories to git ignore list. 2025-07-06 20:08:51 -07:00
2defd1fca1 Adds INTERNET permission to manifest. 2025-07-06 20:08:51 -07:00
07f81a5f6d Initial 2025-07-06 20:08:51 -07:00
101 changed files with 1437 additions and 1452 deletions

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project version="4"> <project version="4">
<component name="CompilerConfiguration"> <component name="CompilerConfiguration">
<bytecodeTargetLevel target="16" /> <bytecodeTargetLevel target="1.8" />
</component> </component>
</project> </project>

View File

@@ -1,13 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project version="4"> <project version="4">
<component name="GradleMigrationSettings" migrationVersion="1" />
<component name="GradleSettings"> <component name="GradleSettings">
<option name="linkedExternalProjectsSettings"> <option name="linkedExternalProjectsSettings">
<GradleProjectSettings> <GradleProjectSettings>
<option name="testRunner" value="GRADLE" /> <option name="testRunner" value="PLATFORM" />
<option name="distributionType" value="DEFAULT_WRAPPED" /> <option name="distributionType" value="DEFAULT_WRAPPED" />
<option name="externalProjectPath" value="$PROJECT_DIR$" /> <option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="gradleJvm" value="Android Studio java home" /> <option name="gradleJvm" value="1.8" />
<option name="modules"> <option name="modules">
<set> <set>
<option value="$PROJECT_DIR$" /> <option value="$PROJECT_DIR$" />

View File

@@ -21,10 +21,5 @@
<option name="name" value="Google" /> <option name="name" value="Google" />
<option name="url" value="https://dl.google.com/dl/android/maven2/" /> <option name="url" value="https://dl.google.com/dl/android/maven2/" />
</remote-repository> </remote-repository>
<remote-repository>
<option name="id" value="MavenRepo" />
<option name="name" value="MavenRepo" />
<option name="url" value="https://repo.maven.apache.org/maven2/" />
</remote-repository>
</component> </component>
</project> </project>

46
Android/.idea/misc.xml generated
View File

@@ -1,50 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project version="4"> <project version="4">
<component name="NullableNotNullManager"> <component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<option name="myDefaultNullable" value="androidx.annotation.Nullable" />
<option name="myDefaultNotNull" value="androidx.annotation.NonNull" />
<option name="myNullables">
<value>
<list size="14">
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.Nullable" />
<item index="1" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.Nullable" />
<item index="2" class="java.lang.String" itemvalue="android.support.annotation.Nullable" />
<item index="3" class="java.lang.String" itemvalue="androidx.annotation.Nullable" />
<item index="4" class="java.lang.String" itemvalue="androidx.annotation.RecentlyNullable" />
<item index="5" class="java.lang.String" itemvalue="com.android.annotations.Nullable" />
<item index="6" class="java.lang.String" itemvalue="javax.annotation.Nullable" />
<item index="7" class="java.lang.String" itemvalue="javax.annotation.CheckForNull" />
<item index="8" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.qual.Nullable" />
<item index="9" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NullableDecl" />
<item index="10" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NullableType" />
<item index="11" class="java.lang.String" itemvalue="org.eclipse.jdt.annotation.Nullable" />
<item index="12" class="java.lang.String" itemvalue="io.reactivex.annotations.Nullable" />
<item index="13" class="java.lang.String" itemvalue="io.reactivex.rxjava3.annotations.Nullable" />
</list>
</value>
</option>
<option name="myNotNulls">
<value>
<list size="14">
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.NotNull" />
<item index="1" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.NonNull" />
<item index="2" class="java.lang.String" itemvalue="android.support.annotation.NonNull" />
<item index="3" class="java.lang.String" itemvalue="androidx.annotation.NonNull" />
<item index="4" class="java.lang.String" itemvalue="androidx.annotation.RecentlyNonNull" />
<item index="5" class="java.lang.String" itemvalue="com.android.annotations.NonNull" />
<item index="6" class="java.lang.String" itemvalue="javax.annotation.Nonnull" />
<item index="7" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.qual.NonNull" />
<item index="8" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NonNullDecl" />
<item index="9" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NonNullType" />
<item index="10" class="java.lang.String" itemvalue="org.eclipse.jdt.annotation.NonNull" />
<item index="11" class="java.lang.String" itemvalue="io.reactivex.annotations.NonNull" />
<item index="12" class="java.lang.String" itemvalue="io.reactivex.rxjava3.annotations.NonNull" />
<item index="13" class="java.lang.String" itemvalue="lombok.NonNull" />
</list>
</value>
</option>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_X" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" /> <output url="file://$PROJECT_DIR$/build/classes" />
</component> </component>
<component name="ProjectType"> <component name="ProjectType">

12
Android/.idea/runConfigurations.xml generated Normal file
View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RunConfigurationProducerService">
<option name="ignoredProducers">
<set>
<option value="org.jetbrains.plugins.gradle.execution.test.runner.AllInPackageGradleConfigurationProducer" />
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestClassGradleConfigurationProducer" />
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestMethodGradleConfigurationProducer" />
</set>
</option>
</component>
</project>

View File

@@ -9,7 +9,6 @@
<option value="noActionIfCompileErrors" /> <option value="noActionIfCompileErrors" />
<option value="organizeImports" /> <option value="organizeImports" />
<option value="reformat" /> <option value="reformat" />
<option value="rearrange" />
</set> </set>
</option> </option>
<option name="configurationPath" value="" /> <option name="configurationPath" value="" />

View File

@@ -11,15 +11,22 @@ if (propertiesFile.exists()) {
def appCenterLocalSecret = properties.getProperty('appCenter.localSecret') def appCenterLocalSecret = properties.getProperty('appCenter.localSecret')
def appCenterEnvSecret = System.getenv('APPCENTER_SECRET') def appCenterEnvSecret = System.getenv('APPCENTER_SECRET')
def appCenterSecret = appCenterLocalSecret != null ? appCenterLocalSecret : appCenterEnvSecret != null ? appCenterEnvSecret : "" def appCenterSecret = appCenterLocalSecret != null ? appCenterLocalSecret : appCenterEnvSecret != null ? appCenterEnvSecret : ""
def appCenterSdkVersion = '3.3.0'
def nav_version = '2.3.5'
def room_version = '2.3.0'
def rxjava_version = '3.0.0'
def flipper_version = '0.87.0'
def soloader_version = '0.10.1'
def gson_version = '2.8.6'
android { android {
compileSdkVersion 31 compileSdkVersion 30
buildToolsVersion '30.0.3' buildToolsVersion '30.0.2'
defaultConfig { defaultConfig {
applicationId "com.majinnaibu.monstercards" applicationId "com.majinnaibu.monstercards"
minSdkVersion 22 minSdkVersion 22
targetSdkVersion 31 targetSdkVersion 30
versionCode 1 versionCode 1
versionName "1.0" versionName "1.0"
buildConfigField "String", "APPCENTER_SECRET", "\"${appCenterSecret}\"" buildConfigField "String", "APPCENTER_SECRET", "\"${appCenterSecret}\""
@@ -56,9 +63,6 @@ android {
buildFeatures { buildFeatures {
viewBinding true viewBinding true
} }
lintOptions {
checkDependencies true
}
} }
dependencies { dependencies {
@@ -66,40 +70,40 @@ dependencies {
implementation fileTree(dir: "libs", include: ["*.jar"]) implementation fileTree(dir: "libs", include: ["*.jar"])
// Google // Google
implementation 'androidx.appcompat:appcompat:1.3.1' implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'com.google.android.material:material:1.4.0' implementation 'com.google.android.material:material:1.3.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.0' implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
implementation "androidx.navigation:navigation-fragment:2.3.5" implementation "androidx.navigation:navigation-fragment:$nav_version"
implementation "androidx.navigation:navigation-ui:2.3.5" implementation "androidx.navigation:navigation-ui:$nav_version"
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0' implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
implementation 'androidx.legacy:legacy-support-v4:1.0.0' implementation 'androidx.legacy:legacy-support-v4:1.0.0'
implementation 'androidx.recyclerview:recyclerview:1.2.1' implementation 'androidx.recyclerview:recyclerview:1.1.0'
implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.3.1' implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.3.1'
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1' implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1'
// Testing // Testing
testImplementation 'junit:junit:4.13.2' testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.3' androidTestImplementation 'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
// Room DB // Room DB
implementation 'io.reactivex.rxjava3:rxjava:3.1.0' implementation "io.reactivex.rxjava3:rxjava:$rxjava_version"
implementation "io.reactivex.rxjava3:rxandroid:3.0.0" implementation "io.reactivex.rxjava3:rxandroid:$rxjava_version"
implementation "androidx.room:room-runtime:2.3.0" implementation "androidx.room:room-runtime:$room_version"
annotationProcessor "androidx.room:room-compiler:2.3.0" annotationProcessor "androidx.room:room-compiler:$room_version"
implementation "androidx.room:room-rxjava3:2.3.0" implementation "androidx.room:room-rxjava3:$room_version"
//testImplementation "androidx.room:room-testing:2.3.0" //testImplementation "androidx.room:room-testing:$room_version"
// AppCenter // AppCenter
debugImplementation 'com.microsoft.appcenter:appcenter-analytics:4.2.0' debugImplementation "com.microsoft.appcenter:appcenter-analytics:${appCenterSdkVersion}"
debugImplementation 'com.microsoft.appcenter:appcenter-crashes:4.2.0' debugImplementation "com.microsoft.appcenter:appcenter-crashes:${appCenterSdkVersion}"
// Flipper // Flipper
debugImplementation 'com.facebook.flipper:flipper:0.102.0' debugImplementation "com.facebook.flipper:flipper:$flipper_version"
debugImplementation "com.facebook.soloader:soloader:0.10.1" debugImplementation "com.facebook.soloader:soloader:$soloader_version"
releaseImplementation 'com.facebook.flipper:flipper-noop:0.102.0' releaseImplementation "com.facebook.flipper:flipper-noop:$flipper_version"
// Other 3rd Party // Other 3rd Party
implementation 'com.atlassian.commonmark:commonmark:0.17.0' implementation 'com.atlassian.commonmark:commonmark:0.15.2'
implementation 'com.google.code.gson:gson:2.8.7' implementation "com.google.code.gson:gson:$gson_version"
} }

View File

@@ -7,7 +7,6 @@
<application <application
android:name=".MonsterCardsApplication" android:name=".MonsterCardsApplication"
android:allowBackup="true" android:allowBackup="true"
android:fullBackupOnly="true"
android:icon="@mipmap/ic_launcher" android:icon="@mipmap/ic_launcher"
android:label="@string/app_name" android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round" android:roundIcon="@mipmap/ic_launcher_round"
@@ -15,7 +14,6 @@
android:theme="@style/AppTheme"> android:theme="@style/AppTheme">
<activity <activity
android:name=".MainActivity" android:name=".MainActivity"
android:exported="true"
android:label="@string/app_name" android:label="@string/app_name"
android:launchMode="singleTask"> android:launchMode="singleTask">
<intent-filter> <intent-filter>
@@ -53,9 +51,6 @@
<nav-graph android:value="@navigation/mobile_navigation" /> <nav-graph android:value="@navigation/mobile_navigation" />
</activity> </activity>
<activity
android:name="com.facebook.flipper.android.diagnostics.FlipperDiagnosticActivity"
android:exported="true" />
</application> </application>
</manifest> </manifest>

View File

@@ -1,14 +1,21 @@
package com.majinnaibu.monstercards; package com.majinnaibu.monstercards;
import android.content.Context;
import androidx.annotation.NonNull;
import androidx.room.Database; import androidx.room.Database;
import androidx.room.Room;
import androidx.room.RoomDatabase; import androidx.room.RoomDatabase;
import androidx.room.TypeConverters; import androidx.room.TypeConverters;
import androidx.room.migration.Migration;
import androidx.sqlite.db.SupportSQLiteDatabase;
import com.majinnaibu.monstercards.data.MonsterDAO; import com.majinnaibu.monstercards.data.MonsterDAO;
import com.majinnaibu.monstercards.data.converters.ArmorTypeConverter; import com.majinnaibu.monstercards.data.converters.ArmorTypeConverter;
import com.majinnaibu.monstercards.data.converters.ChallengeRatingConverter; import com.majinnaibu.monstercards.data.converters.ChallengeRatingConverter;
import com.majinnaibu.monstercards.data.converters.ListOfTraitsConverter; import com.majinnaibu.monstercards.data.converters.ListOfTraitsConverter;
import com.majinnaibu.monstercards.data.converters.SetOfLanguageConverter; import com.majinnaibu.monstercards.data.converters.SetOfLanguageConverter;
import com.majinnaibu.monstercards.data.converters.SetOfSavingThrowConverter;
import com.majinnaibu.monstercards.data.converters.SetOfSkillConverter; import com.majinnaibu.monstercards.data.converters.SetOfSkillConverter;
import com.majinnaibu.monstercards.data.converters.SetOfStringConverter; import com.majinnaibu.monstercards.data.converters.SetOfStringConverter;
import com.majinnaibu.monstercards.data.converters.UUIDConverter; import com.majinnaibu.monstercards.data.converters.UUIDConverter;
@@ -21,10 +28,53 @@ import com.majinnaibu.monstercards.models.MonsterFTS;
ChallengeRatingConverter.class, ChallengeRatingConverter.class,
ListOfTraitsConverter.class, ListOfTraitsConverter.class,
SetOfLanguageConverter.class, SetOfLanguageConverter.class,
SetOfSavingThrowConverter.class,
SetOfSkillConverter.class, SetOfSkillConverter.class,
SetOfStringConverter.class, SetOfStringConverter.class,
UUIDConverter.class, UUIDConverter.class,
}) })
public abstract class AppDatabase extends RoomDatabase { public abstract class AppDatabase extends RoomDatabase {
private static final Migration MIGRATION_1_2 = new Migration(1, 2) {
@Override
public void migrate(@NonNull SupportSQLiteDatabase database) {
// rename table monster to monsters
database.execSQL("ALTER TABLE monster RENAME TO monsters");
// create the fts view
database.execSQL("CREATE VIRTUAL TABLE IF NOT EXISTS `monsters_fts` USING FTS4(`name` TEXT, `size` TEXT, `type` TEXT, `subtype` TEXT, `alignment` TEXT, content=`monsters`)");
// build the initial full text search index
database.execSQL("INSERT INTO monsters_fts(monsters_fts) VALUES('rebuild')");
}
};
private static final Migration MIGRATION_2_3 = new Migration(2, 3) {
@Override
public void migrate(@NonNull SupportSQLiteDatabase database) {
// Add the senses column
database.execSQL("ALTER TABLE monsters ADD COLUMN 'senses' TEXT DEFAULT '[]'");
database.execSQL("CREATE TABLE new_monsters (`id` TEXT NOT NULL, `name` TEXT NOT NULL DEFAULT '', `size` TEXT NOT NULL DEFAULT '', `type` TEXT NOT NULL DEFAULT '', `subtype` TEXT NOT NULL DEFAULT '', `alignment` TEXT NOT NULL DEFAULT '', `strength_score` INTEGER NOT NULL DEFAULT 10, `strength_saving_throw_advantage` TEXT DEFAULT 'none', `strength_saving_throw_proficiency` TEXT DEFAULT 'none', `dexterity_score` INTEGER NOT NULL DEFAULT 10, `dexterity_saving_throw_advantage` TEXT DEFAULT 'none', `dexterity_saving_throw_proficiency` TEXT DEFAULT 'none', `constitution_score` INTEGER NOT NULL DEFAULT 10, `constitution_saving_throw_advantage` TEXT DEFAULT 'none', `constitution_saving_throw_proficiency` TEXT DEFAULT 'none', `intelligence_score` INTEGER NOT NULL DEFAULT 10, `intelligence_saving_throw_advantage` TEXT DEFAULT 'none', `intelligence_saving_throw_proficiency` TEXT DEFAULT 'none', `wisdom_score` INTEGER NOT NULL DEFAULT 10, `wisdom_saving_throw_advantage` TEXT DEFAULT 'none', `wisdom_saving_throw_proficiency` TEXT DEFAULT 'none', `charisma_score` INTEGER NOT NULL DEFAULT 10, `charisma_saving_throw_advantage` TEXT DEFAULT 'none', `charisma_saving_throw_proficiency` TEXT DEFAULT 'none', `armor_type` TEXT DEFAULT 'none', `shield_bonus` INTEGER NOT NULL DEFAULT 0, `natural_armor_bonus` INTEGER NOT NULL DEFAULT 0, `other_armor_description` TEXT DEFAULT '', `hit_dice` INTEGER NOT NULL DEFAULT 1, `has_custom_hit_points` INTEGER NOT NULL, `custom_hit_points_description` TEXT DEFAULT '', `walk_speed` INTEGER NOT NULL DEFAULT 0, `burrow_speed` INTEGER NOT NULL DEFAULT 0, `climb_speed` INTEGER NOT NULL DEFAULT 0, `fly_speed` INTEGER NOT NULL DEFAULT 0, `can_hover` INTEGER NOT NULL DEFAULT false, `swim_speed` INTEGER NOT NULL DEFAULT 0, `has_custom_speed` INTEGER NOT NULL DEFAULT false, `custom_speed_description` TEXT, `challenge_rating` TEXT DEFAULT '1', `custom_challenge_rating_description` TEXT DEFAULT '', `custom_proficiency_bonus` INTEGER NOT NULL DEFAULT 0, `telepathy_range` INTEGER NOT NULL DEFAULT 0, `understands_but_description` TEXT DEFAULT '', `senses` TEXT DEFAULT '[]', `skills` TEXT DEFAULT '[]', `damage_immunities` TEXT DEFAULT '[]', `damage_resistances` TEXT DEFAULT '[]', `damage_vulnerabilities` TEXT DEFAULT '[]', `condition_immunities` TEXT DEFAULT '[]', `languages` TEXT DEFAULT '[]', `abilities` TEXT DEFAULT '[]', `actions` TEXT DEFAULT '[]', `reactions` TEXT DEFAULT '[]', `lair_actions` TEXT DEFAULT '[]', `legendary_actions` TEXT DEFAULT '[]', `regional_actions` TEXT DEFAULT '[]', PRIMARY KEY(`id`))");
database.execSQL("INSERT INTO new_monsters(id, name, size, type, subtype, alignment, strength_score, strength_saving_throw_advantage, strength_saving_throw_proficiency, dexterity_score, dexterity_saving_throw_advantage, dexterity_saving_throw_proficiency, constitution_score, constitution_saving_throw_advantage, constitution_saving_throw_proficiency, intelligence_score, intelligence_saving_throw_advantage, intelligence_saving_throw_proficiency, wisdom_score, wisdom_saving_throw_advantage, wisdom_saving_throw_proficiency, charisma_score, charisma_saving_throw_advantage, charisma_saving_throw_proficiency, armor_type, shield_bonus, natural_armor_bonus, other_armor_description, hit_dice, has_custom_hit_points, custom_hit_points_description, walk_speed, burrow_speed, climb_speed, fly_speed, can_hover, swim_speed, has_custom_speed, custom_speed_description, challenge_rating, custom_challenge_rating_description, custom_proficiency_bonus, telepathy_range, understands_but_description, senses, skills, damage_immunities, damage_resistances, damage_vulnerabilities, condition_immunities, languages, abilities, actions, reactions, lair_actions, legendary_actions, regional_actions) SELECT id, name, size, type, subtype, alignment, strength_score, strength_saving_throw_advantage, strength_saving_throw_proficiency, dexterity_score, dexterity_saving_throw_advantage, dexterity_saving_throw_proficiency, constitution_score, constitution_saving_throw_advantage, constitution_saving_throw_proficiency, intelligence_score, intelligence_saving_throw_advantage, intelligence_saving_throw_proficiency, wisdom_score, wisdom_saving_throw_advantage, wisdom_saving_throw_proficiency, charisma_score, charisma_saving_throw_advantage, charisma_saving_throw_proficiency, armor_type, shield_bonus, natural_armor_bonus, other_armor_description, hit_dice, has_custom_hit_points, custom_hit_points_description, walk_speed, burrow_speed, climb_speed, fly_speed, can_hover, swim_speed, has_custom_speed, custom_speed_description, challenge_rating, custom_challenge_rating_description, custom_proficiency_bonus, telepathy_range, understands_but_description, senses, skills, damage_immunities, damage_resistances, damage_vulnerabilities, condition_immunities, languages, abilities, actions, reactions, lair_actions, legendary_actions, regional_actions FROM monsters");
database.execSQL("DROP TABLE monsters");
database.execSQL("ALTER TABLE new_monsters RENAME TO monsters");
}
};
private static AppDatabase mDB = null;
public static AppDatabase getInstance(Context context) {
if (mDB == null) {
synchronized (AppDatabase.class) {
if (mDB == null) {
// .fallbackToDestructiveMigration()
mDB = Room.databaseBuilder(context.getApplicationContext(), AppDatabase.class, "monsters")
.addMigrations(MIGRATION_1_2)
.addMigrations(MIGRATION_2_3)
.fallbackToDestructiveMigrationOnDowngrade()
// .fallbackToDestructiveMigration()
.build();
}
}
}
return mDB;
}
public abstract MonsterDAO monsterDAO(); public abstract MonsterDAO monsterDAO();
} }

View File

@@ -1,15 +1,11 @@
package com.majinnaibu.monstercards; package com.majinnaibu.monstercards;
import android.content.ContentResolver;
import android.content.Intent; import android.content.Intent;
import android.database.Cursor;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.provider.DocumentsContract;
import android.view.MenuItem; import android.view.MenuItem;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.app.AppCompatActivity;
import androidx.navigation.NavController; import androidx.navigation.NavController;
import androidx.navigation.NavDirections; import androidx.navigation.NavDirections;
@@ -24,7 +20,6 @@ import com.majinnaibu.monstercards.init.FlipperInitializer;
import com.majinnaibu.monstercards.utils.Logger; import com.majinnaibu.monstercards.utils.Logger;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.InputStreamReader; import java.io.InputStreamReader;
@@ -59,7 +54,9 @@ public class MainActivity extends AppCompatActivity {
.build(); .build();
NavHostFragment navHostFragment = (NavHostFragment) getSupportFragmentManager().findFragmentById(R.id.nav_host_fragment); NavHostFragment navHostFragment = (NavHostFragment) getSupportFragmentManager().findFragmentById(R.id.nav_host_fragment);
NavController navController = navHostFragment.getNavController(); NavController navController = navHostFragment.getNavController();
navController.addOnDestinationChangedListener(FlipperInitializer::sendNavigationEvent); navController.addOnDestinationChangedListener((controller, destination, arguments) -> {
FlipperInitializer.sendNavigationEvent(controller, destination, arguments);
});
NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration); NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration);
NavigationUI.setupWithNavController(navView, navController); NavigationUI.setupWithNavController(navView, navController);
onNewIntent(getIntent()); onNewIntent(getIntent());
@@ -71,28 +68,25 @@ public class MainActivity extends AppCompatActivity {
String json = readMonsterJSONFromIntent(intent); String json = readMonsterJSONFromIntent(intent);
if (!StringHelper.isNullOrEmpty(json)) { if (!StringHelper.isNullOrEmpty(json)) {
NavHostFragment navHostFragment = Objects.requireNonNull((NavHostFragment) getSupportFragmentManager().findFragmentById(R.id.nav_host_fragment)); NavHostFragment navHostFragment = (NavHostFragment) getSupportFragmentManager().findFragmentById(R.id.nav_host_fragment);
NavController navController = navHostFragment.getNavController(); NavController navController = navHostFragment.getNavController();
NavDirections action = MobileNavigationDirections.actionGlobalMonsterImportFragment(json); NavDirections action = MobileNavigationDirections.actionGlobalMonsterImportFragment(json);
navController.navigate(action); navController.navigate(action);
} }
} }
@Nullable private String readMonsterJSONFromIntent(Intent intent) {
private String readMonsterJSONFromIntent(@NonNull Intent intent) {
String action = intent.getAction(); String action = intent.getAction();
Bundle extras = intent.getExtras(); Bundle extras = intent.getExtras();
String type = intent.getType(); String type = intent.getType();
String json; String json;
Uri uri = null; Uri uri = null;
if ("android.intent.action.MAIN".equals(action)) { if ("android.intent.action.SEND".equals(action) && "text/plain".equals(type)) {
return null;
} else if ("android.intent.action.SEND".equals(action) && "text/plain".equals(type)) {
uri = extras.getParcelable("android.intent.extra.STREAM"); uri = extras.getParcelable("android.intent.extra.STREAM");
} else if ("android.intent.action.VIEW".equals(action) && ("text/plain".equals(type) || "application/octet-stream".equals(type))) { } else if ("android.intent.action.VIEW".equals(action) && ("text/plain".equals(type) || "application/octet-stream".equals(type))) {
uri = intent.getData(); uri = intent.getData();
} else { } else {
Logger.logError(String.format("unexpected launch configuration action: %s, type: %s", action, type)); Logger.logError(String.format("unexpected launch configuration action: %s, type: %s, uri: %s", action, type, uri));
} }
if (uri == null) { if (uri == null) {
return null; return null;
@@ -104,13 +98,12 @@ public class MainActivity extends AppCompatActivity {
return json; return json;
} }
@Nullable
private String readContentsOfUri(Uri uri) { private String readContentsOfUri(Uri uri) {
StringBuilder builder = new StringBuilder(); StringBuilder builder = new StringBuilder();
try ( try (InputStream inputStream =
InputStream inputStream = openInputStream(uri); getContentResolver().openInputStream(uri);
BufferedReader reader = new BufferedReader(new InputStreamReader(Objects.requireNonNull(inputStream))) BufferedReader reader = new BufferedReader(
) { new InputStreamReader(Objects.requireNonNull(inputStream)))) {
String line; String line;
while ((line = reader.readLine()) != null) { while ((line = reader.readLine()) != null) {
builder.append(line); builder.append(line);
@@ -121,36 +114,4 @@ public class MainActivity extends AppCompatActivity {
} }
return builder.toString(); return builder.toString();
} }
private boolean isVirtualFile(Uri uri) {
if (!DocumentsContract.isDocumentUri(this, uri)) {
return false;
}
Cursor cursor = getContentResolver().query(
uri,
new String[]{DocumentsContract.Document.COLUMN_FLAGS},
null, null, null);
int flags = 0;
if (cursor.moveToFirst()) {
flags = cursor.getInt(0);
}
cursor.close();
return (flags & DocumentsContract.Document.FLAG_VIRTUAL_DOCUMENT) != 0;
}
private InputStream openInputStream(Uri uri) throws IOException {
ContentResolver resolver = getContentResolver();
if (isVirtualFile(uri)) {
String[] openableMimeTypes = resolver.getStreamTypes(uri, "*/*");
if (openableMimeTypes == null || openableMimeTypes.length <= 0) {
throw new FileNotFoundException();
}
return resolver.openTypedAssetFileDescriptor(uri, openableMimeTypes[0], null).createInputStream();
} else {
return resolver.openInputStream(uri);
}
}
} }

View File

@@ -3,39 +3,12 @@ package com.majinnaibu.monstercards;
import android.app.Application; import android.app.Application;
import android.content.res.Configuration; import android.content.res.Configuration;
import androidx.annotation.NonNull;
import androidx.room.Room;
import androidx.room.migration.Migration;
import androidx.sqlite.db.SupportSQLiteDatabase;
import com.majinnaibu.monstercards.data.MonsterRepository; import com.majinnaibu.monstercards.data.MonsterRepository;
import com.majinnaibu.monstercards.init.FlipperInitializer; import com.majinnaibu.monstercards.init.FlipperInitializer;
public class MonsterCardsApplication extends Application { public class MonsterCardsApplication extends Application {
private static final Migration MIGRATION_1_2 = new Migration(1, 2) {
@Override
public void migrate(@NonNull SupportSQLiteDatabase database) {
// rename table monster to monsters
database.execSQL("ALTER TABLE monster RENAME TO monsters");
// create the fts view
database.execSQL("CREATE VIRTUAL TABLE IF NOT EXISTS `monsters_fts` USING FTS4(`name` TEXT, `size` TEXT, `type` TEXT, `subtype` TEXT, `alignment` TEXT, content=`monsters`)");
// build the initial full text search index
database.execSQL("INSERT INTO monsters_fts(monsters_fts) VALUES('rebuild')");
}
};
private static final Migration MIGRATION_2_3 = new Migration(2, 3) {
@Override
public void migrate(@NonNull SupportSQLiteDatabase database) {
// Add the senses column
database.execSQL("ALTER TABLE monsters ADD COLUMN 'senses' TEXT DEFAULT '[]'");
database.execSQL("CREATE TABLE new_monsters (`id` TEXT NOT NULL, `name` TEXT NOT NULL DEFAULT '', `size` TEXT NOT NULL DEFAULT '', `type` TEXT NOT NULL DEFAULT '', `subtype` TEXT NOT NULL DEFAULT '', `alignment` TEXT NOT NULL DEFAULT '', `strength_score` INTEGER NOT NULL DEFAULT 10, `strength_saving_throw_advantage` TEXT DEFAULT 'none', `strength_saving_throw_proficiency` TEXT DEFAULT 'none', `dexterity_score` INTEGER NOT NULL DEFAULT 10, `dexterity_saving_throw_advantage` TEXT DEFAULT 'none', `dexterity_saving_throw_proficiency` TEXT DEFAULT 'none', `constitution_score` INTEGER NOT NULL DEFAULT 10, `constitution_saving_throw_advantage` TEXT DEFAULT 'none', `constitution_saving_throw_proficiency` TEXT DEFAULT 'none', `intelligence_score` INTEGER NOT NULL DEFAULT 10, `intelligence_saving_throw_advantage` TEXT DEFAULT 'none', `intelligence_saving_throw_proficiency` TEXT DEFAULT 'none', `wisdom_score` INTEGER NOT NULL DEFAULT 10, `wisdom_saving_throw_advantage` TEXT DEFAULT 'none', `wisdom_saving_throw_proficiency` TEXT DEFAULT 'none', `charisma_score` INTEGER NOT NULL DEFAULT 10, `charisma_saving_throw_advantage` TEXT DEFAULT 'none', `charisma_saving_throw_proficiency` TEXT DEFAULT 'none', `armor_type` TEXT DEFAULT 'none', `shield_bonus` INTEGER NOT NULL DEFAULT 0, `natural_armor_bonus` INTEGER NOT NULL DEFAULT 0, `other_armor_description` TEXT DEFAULT '', `hit_dice` INTEGER NOT NULL DEFAULT 1, `has_custom_hit_points` INTEGER NOT NULL, `custom_hit_points_description` TEXT DEFAULT '', `walk_speed` INTEGER NOT NULL DEFAULT 0, `burrow_speed` INTEGER NOT NULL DEFAULT 0, `climb_speed` INTEGER NOT NULL DEFAULT 0, `fly_speed` INTEGER NOT NULL DEFAULT 0, `can_hover` INTEGER NOT NULL DEFAULT false, `swim_speed` INTEGER NOT NULL DEFAULT 0, `has_custom_speed` INTEGER NOT NULL DEFAULT false, `custom_speed_description` TEXT, `challenge_rating` TEXT DEFAULT '1', `custom_challenge_rating_description` TEXT DEFAULT '', `custom_proficiency_bonus` INTEGER NOT NULL DEFAULT 0, `telepathy_range` INTEGER NOT NULL DEFAULT 0, `understands_but_description` TEXT DEFAULT '', `senses` TEXT DEFAULT '[]', `skills` TEXT DEFAULT '[]', `damage_immunities` TEXT DEFAULT '[]', `damage_resistances` TEXT DEFAULT '[]', `damage_vulnerabilities` TEXT DEFAULT '[]', `condition_immunities` TEXT DEFAULT '[]', `languages` TEXT DEFAULT '[]', `abilities` TEXT DEFAULT '[]', `actions` TEXT DEFAULT '[]', `reactions` TEXT DEFAULT '[]', `lair_actions` TEXT DEFAULT '[]', `legendary_actions` TEXT DEFAULT '[]', `regional_actions` TEXT DEFAULT '[]', PRIMARY KEY(`id`))");
database.execSQL("INSERT INTO new_monsters(id, name, size, type, subtype, alignment, strength_score, strength_saving_throw_advantage, strength_saving_throw_proficiency, dexterity_score, dexterity_saving_throw_advantage, dexterity_saving_throw_proficiency, constitution_score, constitution_saving_throw_advantage, constitution_saving_throw_proficiency, intelligence_score, intelligence_saving_throw_advantage, intelligence_saving_throw_proficiency, wisdom_score, wisdom_saving_throw_advantage, wisdom_saving_throw_proficiency, charisma_score, charisma_saving_throw_advantage, charisma_saving_throw_proficiency, armor_type, shield_bonus, natural_armor_bonus, other_armor_description, hit_dice, has_custom_hit_points, custom_hit_points_description, walk_speed, burrow_speed, climb_speed, fly_speed, can_hover, swim_speed, has_custom_speed, custom_speed_description, challenge_rating, custom_challenge_rating_description, custom_proficiency_bonus, telepathy_range, understands_but_description, senses, skills, damage_immunities, damage_resistances, damage_vulnerabilities, condition_immunities, languages, abilities, actions, reactions, lair_actions, legendary_actions, regional_actions) SELECT id, name, size, type, subtype, alignment, strength_score, strength_saving_throw_advantage, strength_saving_throw_proficiency, dexterity_score, dexterity_saving_throw_advantage, dexterity_saving_throw_proficiency, constitution_score, constitution_saving_throw_advantage, constitution_saving_throw_proficiency, intelligence_score, intelligence_saving_throw_advantage, intelligence_saving_throw_proficiency, wisdom_score, wisdom_saving_throw_advantage, wisdom_saving_throw_proficiency, charisma_score, charisma_saving_throw_advantage, charisma_saving_throw_proficiency, armor_type, shield_bonus, natural_armor_bonus, other_armor_description, hit_dice, has_custom_hit_points, custom_hit_points_description, walk_speed, burrow_speed, climb_speed, fly_speed, can_hover, swim_speed, has_custom_speed, custom_speed_description, challenge_rating, custom_challenge_rating_description, custom_proficiency_bonus, telepathy_range, understands_but_description, senses, skills, damage_immunities, damage_resistances, damage_vulnerabilities, condition_immunities, languages, abilities, actions, reactions, lair_actions, legendary_actions, regional_actions FROM monsters");
database.execSQL("DROP TABLE monsters");
database.execSQL("ALTER TABLE new_monsters RENAME TO monsters");
}
};
private MonsterRepository m_monsterLibraryRepository; private MonsterRepository m_monsterLibraryRepository;
@@ -54,15 +27,8 @@ public class MonsterCardsApplication extends Application {
// Required initialization logic here! // Required initialization logic here!
FlipperInitializer.init(this); FlipperInitializer.init(this);
AppDatabase mDB = AppDatabase.getInstance(this);
// .fallbackToDestructiveMigration() m_monsterLibraryRepository = new MonsterRepository(mDB);
AppDatabase m_db = Room.databaseBuilder(getApplicationContext(), AppDatabase.class, "monsters")
.addMigrations(MIGRATION_1_2)
.addMigrations(MIGRATION_2_3)
.fallbackToDestructiveMigrationOnDowngrade()
// .fallbackToDestructiveMigration()
.build();
m_monsterLibraryRepository = new MonsterRepository(m_db);
} }
// Called by the system when the device configuration changes while your component is running. // Called by the system when the device configuration changes while your component is running.

View File

@@ -1,7 +1,5 @@
package com.majinnaibu.monstercards.data; package com.majinnaibu.monstercards.data;
import androidx.annotation.NonNull;
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.ArmorType; import com.majinnaibu.monstercards.data.enums.ArmorType;
@@ -14,7 +12,6 @@ import com.majinnaibu.monstercards.models.Trait;
@SuppressWarnings("unused") @SuppressWarnings("unused")
public final class DevContent { public final class DevContent {
@NonNull
public static Monster createSampleMonster() { public static Monster createSampleMonster() {
Monster monster = new Monster(); Monster monster = new Monster();
// Name // Name

View File

@@ -3,10 +3,8 @@ package com.majinnaibu.monstercards.data;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import com.majinnaibu.monstercards.AppDatabase; import com.majinnaibu.monstercards.AppDatabase;
import com.majinnaibu.monstercards.helpers.StringHelper;
import com.majinnaibu.monstercards.models.Monster; import com.majinnaibu.monstercards.models.Monster;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
@@ -15,16 +13,16 @@ import io.reactivex.rxjava3.core.Completable;
import io.reactivex.rxjava3.core.Flowable; import io.reactivex.rxjava3.core.Flowable;
import io.reactivex.rxjava3.schedulers.Schedulers; import io.reactivex.rxjava3.schedulers.Schedulers;
@SuppressWarnings("ResultOfMethodCallIgnored")
public class MonsterRepository { public class MonsterRepository {
private final AppDatabase m_db; private AppDatabase m_db;
public MonsterRepository(@NonNull AppDatabase db) { public MonsterRepository(@NonNull AppDatabase db) {
m_db = db; m_db = db;
} }
public Flowable<List<Monster>> getMonsters() { public Flowable<List<Monster>> getMonsters() {
return m_db.monsterDAO() return m_db.monsterDAO()
.getAll() .getAll()
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
@@ -33,21 +31,12 @@ public class MonsterRepository {
public Flowable<List<Monster>> searchMonsters(String searchText) { public Flowable<List<Monster>> searchMonsters(String searchText) {
return m_db.monsterDAO() return m_db.monsterDAO()
.getAll() .search(searchText)
.map(monsters -> {
ArrayList<Monster> filteredMonsters = new ArrayList<>();
for (Monster monster : monsters) {
if (Helpers.monsterMatchesSearch(monster, searchText)) {
filteredMonsters.add(monster);
}
}
return (List<Monster>) filteredMonsters;
})
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()); .observeOn(AndroidSchedulers.mainThread());
} }
public Flowable<Monster> getMonster(@NonNull UUID monsterId) { public Flowable<Monster> getMonster(UUID monsterId) {
return m_db.monsterDAO() return m_db.monsterDAO()
.loadAllByIds(new String[]{monsterId.toString()}) .loadAllByIds(new String[]{monsterId.toString()})
.map( .map(
@@ -79,34 +68,4 @@ public class MonsterRepository {
result.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()); result.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread());
return result; return result;
} }
private static class Helpers {
static boolean monsterMatchesSearch(Monster monster, String searchText) {
if (StringHelper.isNullOrEmpty(searchText)) {
return true;
}
if (StringHelper.containsCaseInsensitive(monster.name, searchText)) {
return true;
}
if (StringHelper.containsCaseInsensitive(monster.size, searchText)) {
return true;
}
if (StringHelper.containsCaseInsensitive(monster.type, searchText)) {
return true;
}
if (StringHelper.containsCaseInsensitive(monster.subtype, searchText)) {
return true;
}
if (StringHelper.containsCaseInsensitive(monster.alignment, searchText)) {
return true;
}
return false;
}
}
} }

View File

@@ -1,6 +1,5 @@
package com.majinnaibu.monstercards.data.converters; package com.majinnaibu.monstercards.data.converters;
import androidx.annotation.NonNull;
import androidx.room.TypeConverter; import androidx.room.TypeConverter;
import com.majinnaibu.monstercards.data.enums.ArmorType; import com.majinnaibu.monstercards.data.enums.ArmorType;
@@ -8,7 +7,7 @@ import com.majinnaibu.monstercards.data.enums.ArmorType;
public class ArmorTypeConverter { public class ArmorTypeConverter {
@TypeConverter @TypeConverter
public static String fromArmorType(@NonNull ArmorType armorType) { public static String fromArmorType(ArmorType armorType) {
return armorType.stringValue; return armorType.stringValue;
} }

View File

@@ -1,6 +1,5 @@
package com.majinnaibu.monstercards.data.converters; package com.majinnaibu.monstercards.data.converters;
import androidx.annotation.NonNull;
import androidx.room.TypeConverter; import androidx.room.TypeConverter;
import com.majinnaibu.monstercards.data.enums.ChallengeRating; import com.majinnaibu.monstercards.data.enums.ChallengeRating;
@@ -8,7 +7,7 @@ import com.majinnaibu.monstercards.data.enums.ChallengeRating;
public class ChallengeRatingConverter { public class ChallengeRatingConverter {
@TypeConverter @TypeConverter
public static String fromChallengeRating(@NonNull ChallengeRating challengeRating) { public static String fromChallengeRating(ChallengeRating challengeRating) {
return challengeRating.stringValue; return challengeRating.stringValue;
} }

View File

@@ -0,0 +1,31 @@
package com.majinnaibu.monstercards.data.converters;
import androidx.room.TypeConverter;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.majinnaibu.monstercards.models.SavingThrow;
import java.lang.reflect.Type;
import java.util.HashSet;
import java.util.Set;
public class SetOfSavingThrowConverter {
@TypeConverter
public static String fromSetOfSavingThrow(Set<SavingThrow> savingThrows) {
Gson gson = new Gson();
SavingThrow[] saves = new SavingThrow[savingThrows.size()];
savingThrows.toArray(saves);
return gson.toJson(saves);
}
@TypeConverter
public static Set<SavingThrow> setOfSavingThrowFromString(String string) {
Gson gson = new Gson();
Type setType = new TypeToken<HashSet<SavingThrow>>() {
}.getType();
return gson.fromJson(string, setType);
}
}

View File

@@ -1,15 +1,13 @@
package com.majinnaibu.monstercards.data.converters; package com.majinnaibu.monstercards.data.converters;
import androidx.annotation.NonNull;
import androidx.room.TypeConverter; import androidx.room.TypeConverter;
import java.util.UUID; import java.util.UUID;
public class UUIDConverter { public class UUIDConverter {
@NonNull
@TypeConverter @TypeConverter
public static String fromUUID(@NonNull UUID uuid) { public static String fromUUID(UUID uuid) {
return uuid.toString(); return uuid.toString();
} }

View File

@@ -5,7 +5,7 @@ public enum AbilityScore {
STRENGTH("strength", "Strength", "STR"), STRENGTH("strength", "Strength", "STR"),
DEXTERITY("dexterity", "Dexterity", "DEX"), DEXTERITY("dexterity", "Dexterity", "DEX"),
CONSTITUTION("constitution", "Constitution", "CON"), CONSTITUTION("constitution", "Constitution", "CON"),
INTELLIGENCE("intelligence", "Intelligence", "INT"), INTELLIGENCE("intellligence", "Intelligence", "INT"),
WISDOM("wisdom", "Wisdom", "WIS"), WISDOM("wisdom", "Wisdom", "WIS"),
CHARISMA("charisma", "Charisma", "CHA"), CHARISMA("charisma", "Charisma", "CHA"),
; ;

View File

@@ -3,7 +3,7 @@ package com.majinnaibu.monstercards.data.enums;
public enum ProficiencyType { public enum ProficiencyType {
NONE("none", "None", ""), NONE("none", "None", ""),
PROFICIENT("proficient", "Proficient", "P"), PROFICIENT("proficient", "Proficient", "P"),
EXPERTISE("expertise", "Expertise", "Ex"), EXPERTISE("experties", "Expertise", "Ex"),
; ;
public final String displayName; public final String displayName;

View File

@@ -1,11 +1,9 @@
package com.majinnaibu.monstercards.helpers; package com.majinnaibu.monstercards.helpers;
import androidx.annotation.NonNull;
import java.util.Objects; import java.util.Objects;
public final class ArrayHelper { public final class ArrayHelper {
public static int indexOf(@NonNull Object[] array, Object target) { public static int indexOf(Object[] array, Object target) {
for (int index = 0; index < array.length; index++) { for (int index = 0; index < array.length; index++) {
if (Objects.equals(array[index], target)) { if (Objects.equals(array[index], target)) {
return index; return index;

View File

@@ -4,9 +4,20 @@ import org.commonmark.node.Document;
import org.commonmark.node.Node; import org.commonmark.node.Node;
import org.commonmark.node.Paragraph; import org.commonmark.node.Paragraph;
import org.commonmark.parser.Parser; import org.commonmark.parser.Parser;
import org.commonmark.renderer.NodeRenderer;
import org.commonmark.renderer.html.HtmlNodeRendererContext;
import org.commonmark.renderer.html.HtmlNodeRendererFactory;
import org.commonmark.renderer.html.HtmlRenderer; import org.commonmark.renderer.html.HtmlRenderer;
public final class CommonMarkHelper { public final class CommonMarkHelper {
private static final class MyNodeRendererFactory implements HtmlNodeRendererFactory {
@Override
public NodeRenderer create(HtmlNodeRendererContext context) {
return null;
}
}
public static String toHtml(String rawCommonMark) { public static String toHtml(String rawCommonMark) {
Parser parser = Parser.builder().build(); Parser parser = Parser.builder().build();
Node document = parser.parse(rawCommonMark); Node document = parser.parse(rawCommonMark);

View File

@@ -1,7 +1,5 @@
package com.majinnaibu.monstercards.helpers; package com.majinnaibu.monstercards.helpers;
import androidx.annotation.NonNull;
import com.google.gson.JsonArray; import com.google.gson.JsonArray;
import com.google.gson.JsonElement; import com.google.gson.JsonElement;
import com.google.gson.JsonObject; 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.Skill;
import com.majinnaibu.monstercards.models.Trait; import com.majinnaibu.monstercards.models.Trait;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Locale;
import java.util.Set; import java.util.Set;
public class MonsterImportHelper { public class MonsterImportHelper {
@NonNull
public static Monster fromJSON(String json) { 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 monster = new Monster();
monster.name = Helpers.getString(rootDict, "name"); monster.name = Helpers.getString(rootDict, "name");
@@ -111,7 +110,7 @@ public class MonsterImportHelper {
return getString(dict, name, ""); 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)) { if (dict.has(name)) {
return dict.get(name).getAsString(); return dict.get(name).getAsString();
} }
@@ -123,19 +122,13 @@ public class MonsterImportHelper {
return getInt(dict, name, 0); 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)) { if (dict.has(name)) {
JsonElement element = dict.get(name); JsonElement element = dict.get(name);
if (element.isJsonPrimitive()) { if (element.isJsonPrimitive()) {
JsonPrimitive rawValue = element.getAsJsonPrimitive(); JsonPrimitive rawValue = element.getAsJsonPrimitive();//dict.getAsJsonPrimitive(name);
if (rawValue.isNumber()) { if (rawValue.isNumber()) {
return rawValue.getAsInt(); 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); 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)) { if (dict.has(name)) {
JsonElement element = dict.get(name); JsonElement element = dict.get(name);
if (element.isJsonPrimitive()) { if (element.isJsonPrimitive()) {
JsonPrimitive rawValue = element.getAsJsonPrimitive(); JsonPrimitive rawValue = element.getAsJsonPrimitive();
if (rawValue.isBoolean()) { if (rawValue.isBoolean()) {
return rawValue.getAsBoolean(); return rawValue.getAsBoolean();
} else {
try {
return rawValue.getAsBoolean();
} catch (Exception ex) {
return defaultValue;
}
} }
} }
} }
return defaultValue; return defaultValue;
} }
@NonNull @NotNull
public static String formatDistance(String name, int distance) { public static String formatDistance(String name, int distance) {
// TODO: consider moving this to a string resource so it can be localized return String.format("%s %d ft.", name, distance);
return String.format(Locale.getDefault(), "%s %d ft.", name, distance);
} }
public static void addSense(Monster monster, JsonObject root, String name) { public static void addSense(Monster monster, JsonObject root, String name) {
@@ -178,8 +164,8 @@ public class MonsterImportHelper {
} }
} }
@NonNull @NotNull
public static List<Trait> getListOfTraits(@NonNull JsonObject dict, String name) { public static List<Trait> getListOfTraits(@NotNull JsonObject dict, String name) {
ArrayList<Trait> traits = new ArrayList<>(); ArrayList<Trait> traits = new ArrayList<>();
if (dict.has(name)) { if (dict.has(name)) {
JsonElement arrayElement = dict.get(name); JsonElement arrayElement = dict.get(name);
@@ -191,7 +177,7 @@ public class MonsterImportHelper {
if (jsonElement.isJsonObject()) { if (jsonElement.isJsonObject()) {
JsonObject jsonObject = jsonElement.getAsJsonObject(); JsonObject jsonObject = jsonElement.getAsJsonObject();
String traitName = Helpers.getString(jsonObject, "name"); String traitName = Helpers.getString(jsonObject, "name");
String description = Helpers.getString(jsonObject, "desc"); String description = Helpers.getString(jsonObject, "description");
Trait trait = new Trait(traitName, description); Trait trait = new Trait(traitName, description);
traits.add(trait); traits.add(trait);
} }
@@ -201,7 +187,7 @@ public class MonsterImportHelper {
return traits; return traits;
} }
public static void addSavingThrows(Monster monster, @NonNull JsonObject root) { public static void addSavingThrows(Monster monster, JsonObject root) {
if (root.has("sthrows")) { if (root.has("sthrows")) {
JsonElement arrayElement = root.get("sthrows"); JsonElement arrayElement = root.get("sthrows");
if (arrayElement.isJsonArray()) { if (arrayElement.isJsonArray()) {
@@ -231,8 +217,7 @@ public class MonsterImportHelper {
} }
} }
@NonNull public static Set<Skill> getSetOfSkills(JsonObject root) {
public static Set<Skill> getSetOfSkills(@NonNull JsonObject root) {
HashSet<Skill> skills = new HashSet<>(); HashSet<Skill> skills = new HashSet<>();
if (root.has("skills")) { if (root.has("skills")) {
JsonElement arrayElement = root.get("skills"); JsonElement arrayElement = root.get("skills");
@@ -256,13 +241,11 @@ public class MonsterImportHelper {
return skills; return skills;
} }
@NonNull
public static Set<String> getSetOfDamageTypes(JsonObject rootDict, String name) { public static Set<String> getSetOfDamageTypes(JsonObject rootDict, String name) {
return getSetOfDamageTypes(rootDict, name, null); return getSetOfDamageTypes(rootDict, name, null);
} }
@NonNull public static Set<String> getSetOfDamageTypes(JsonObject root, String name, String type) {
public static Set<String> getSetOfDamageTypes(@NonNull JsonObject root, String name, String type) {
HashSet<String> damageTypes = new HashSet<>(); HashSet<String> damageTypes = new HashSet<>();
if (root.has(name)) { if (root.has(name)) {
JsonElement arrayElement = root.get(name); JsonElement arrayElement = root.get(name);
@@ -285,8 +268,7 @@ public class MonsterImportHelper {
return damageTypes; return damageTypes;
} }
@NonNull public static Set<Language> getSetOfLanguages(JsonObject root, String name) {
public static Set<Language> getSetOfLanguages(@NonNull JsonObject root, String name) {
HashSet<Language> languages = new HashSet<>(); HashSet<Language> languages = new HashSet<>();
if (root.has(name)) { if (root.has(name)) {
JsonElement arrayElement = root.get(name); JsonElement arrayElement = root.get(name);

View File

@@ -1,11 +1,6 @@
package com.majinnaibu.monstercards.helpers; package com.majinnaibu.monstercards.helpers;
import androidx.annotation.NonNull; @SuppressWarnings({"BooleanMethodIsAlwaysInverted", "RedundantIfStatement"})
import androidx.annotation.Nullable;
import java.util.Collection;
@SuppressWarnings({"RedundantIfStatement"})
public final class StringHelper { public final class StringHelper {
public static boolean isNullOrEmpty(CharSequence value) { public static boolean isNullOrEmpty(CharSequence value) {
if (value == null) { if (value == null) {
@@ -18,62 +13,4 @@ public final class StringHelper {
return false; return false;
} }
@NonNull
public static String join(String delimiter, @NonNull Collection<String> strings) {
int length = strings.size();
if (length < 1) {
return "";
} else {
StringBuilder sb = new StringBuilder();
boolean isFirst = true;
for (String element : strings) {
if (!isFirst) {
sb.append(delimiter);
}
sb.append(element);
isFirst = false;
}
return sb.toString();
}
}
public static String oxfordJoin(String delimiter, String lastDelimiter, String onlyDelimiter, @NonNull Collection<String> strings) {
int length = strings.size();
if (length < 1) {
return "";
} else if (length == 2) {
return join(onlyDelimiter, strings);
} else {
StringBuilder sb = new StringBuilder();
int index = 0;
int lastIndex = length - 1;
for (String element : strings) {
if (index > 0 && index < lastIndex) {
sb.append(delimiter);
} else if (index > 0 && index >= lastIndex) {
sb.append(lastDelimiter);
}
sb.append(element);
index++;
}
return sb.toString();
}
}
@Nullable
public static Integer parseInt(String s) {
try {
return Integer.parseInt(s);
} catch (NumberFormatException _ex) {
return null;
}
}
public static boolean containsCaseInsensitive(@NonNull String text, @NonNull String search) {
// TODO: find a locale independent way to do this
return text.toLowerCase().contains(search.toLowerCase());
}
} }

View File

@@ -1,74 +1,37 @@
package com.majinnaibu.monstercards.models; package com.majinnaibu.monstercards.models;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import java.util.Comparator; import java.util.Comparator;
import java.util.Objects;
public class Language implements Comparator<Language>, Comparable<Language> { public class Language implements Comparator<Language>, Comparable<Language> {
private String mName;
private boolean mSpeaks;
public Language(String name, boolean speaks) { public Language(String name, boolean speaks) {
mName = name; mName = name;
mSpeaks = speaks; mSpeaks = speaks;
} }
private String mName;
public String getName() { public String getName() {
return mName; return mName;
} }
public void setName(String value) { public void setName(String value) {
mName = value; mName = value;
} }
private boolean mSpeaks;
public boolean getSpeaks() { public boolean getSpeaks() {
return mSpeaks; return mSpeaks;
} }
public void setSpeaks(boolean value) { public void setSpeaks(boolean value) {
mSpeaks = value; mSpeaks = value;
} }
@Override @Override
public int compareTo(Language o) { public int compareTo(Language o) {
if (this.mSpeaks && !o.mSpeaks) { return this.getName().compareToIgnoreCase(o.getName());
return -1;
}
if (!this.mSpeaks && o.mSpeaks) {
return 1;
}
return this.mName.compareToIgnoreCase(o.mName);
} }
@Override @Override
public int compare(@NonNull Language o1, Language o2) { public int compare(Language o1, Language o2) {
if (o1.mSpeaks && !o2.mSpeaks) { return o1.getName().compareToIgnoreCase(o2.getName());
return -1;
}
if (!o1.mSpeaks && o2.mSpeaks) {
return 1;
}
return o1.mName.compareToIgnoreCase(o2.mName);
}
@Override
public boolean equals(@Nullable Object obj) {
if (obj == null) {
return false;
}
if (!(obj instanceof Language)) {
return false;
}
Language otherLanguage = (Language) obj;
if (!Objects.equals(this.mName, otherLanguage.mName)) {
return false;
}
if (this.mSpeaks != otherLanguage.mSpeaks) {
return false;
}
return true;
} }
} }

View File

@@ -16,11 +16,14 @@ import com.majinnaibu.monstercards.data.enums.ProficiencyType;
import com.majinnaibu.monstercards.helpers.StringHelper; import com.majinnaibu.monstercards.helpers.StringHelper;
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.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Objects;
import java.util.Set; import java.util.Set;
import java.util.UUID; import java.util.UUID;
@@ -268,6 +271,69 @@ public class Monster {
regionalActions = new ArrayList<>(); regionalActions = new ArrayList<>();
} }
public static boolean areItemsTheSame(@NonNull Monster oldItem, @NonNull Monster newItem) {
return Objects.equals(oldItem.id, newItem.id);
}
public static boolean areContentsTheSame(@NonNull Monster oldItem, @NonNull Monster newItem) {
return Objects.equals(oldItem.abilities, newItem.abilities) &&
Objects.equals(oldItem.actions, newItem.actions) &&
Objects.equals(oldItem.alignment, newItem.alignment) &&
Objects.equals(oldItem.armorType, newItem.armorType) &&
Objects.equals(oldItem.burrowSpeed, newItem.burrowSpeed) &&
Objects.equals(oldItem.canHover, newItem.canHover) &&
Objects.equals(oldItem.challengeRating, newItem.challengeRating) &&
Objects.equals(oldItem.charismaSavingThrowAdvantage, newItem.charismaSavingThrowAdvantage) &&
Objects.equals(oldItem.charismaSavingThrowProficiency, newItem.charismaSavingThrowProficiency) &&
Objects.equals(oldItem.charismaScore, newItem.charismaScore) &&
Objects.equals(oldItem.climbSpeed, newItem.climbSpeed) &&
Objects.equals(oldItem.conditionImmunities, newItem.conditionImmunities) &&
Objects.equals(oldItem.constitutionSavingThrowAdvantage, newItem.constitutionSavingThrowAdvantage) &&
Objects.equals(oldItem.constitutionSavingThrowProficiency, newItem.constitutionSavingThrowProficiency) &&
Objects.equals(oldItem.constitutionScore, newItem.constitutionScore) &&
Objects.equals(oldItem.customChallengeRatingDescription, newItem.customChallengeRatingDescription) &&
Objects.equals(oldItem.customHPDescription, newItem.customHPDescription) &&
Objects.equals(oldItem.customProficiencyBonus, newItem.customProficiencyBonus) &&
Objects.equals(oldItem.customSpeedDescription, newItem.customSpeedDescription) &&
Objects.equals(oldItem.damageImmunities, newItem.damageImmunities) &&
Objects.equals(oldItem.damageResistances, newItem.damageResistances) &&
Objects.equals(oldItem.damageVulnerabilities, newItem.damageVulnerabilities) &&
Objects.equals(oldItem.dexteritySavingThrowAdvantage, newItem.dexteritySavingThrowAdvantage) &&
Objects.equals(oldItem.dexteritySavingThrowProficiency, newItem.dexteritySavingThrowProficiency) &&
Objects.equals(oldItem.dexterityScore, newItem.dexterityScore) &&
Objects.equals(oldItem.flySpeed, newItem.flySpeed) &&
Objects.equals(oldItem.hasCustomHP, newItem.hasCustomHP) &&
Objects.equals(oldItem.hasCustomSpeed, newItem.hasCustomSpeed) &&
Objects.equals(oldItem.hitDice, newItem.hitDice) &&
Objects.equals(oldItem.intelligenceSavingThrowAdvantage, newItem.intelligenceSavingThrowAdvantage) &&
Objects.equals(oldItem.intelligenceSavingThrowProficiency, newItem.intelligenceSavingThrowProficiency) &&
Objects.equals(oldItem.intelligenceScore, newItem.intelligenceScore) &&
Objects.equals(oldItem.lairActions, newItem.lairActions) &&
Objects.equals(oldItem.languages, newItem.languages) &&
Objects.equals(oldItem.legendaryActions, newItem.legendaryActions) &&
Objects.equals(oldItem.name, newItem.name) &&
Objects.equals(oldItem.naturalArmorBonus, newItem.naturalArmorBonus) &&
Objects.equals(oldItem.otherArmorDescription, newItem.otherArmorDescription) &&
Objects.equals(oldItem.reactions, newItem.reactions) &&
Objects.equals(oldItem.regionalActions, newItem.regionalActions) &&
Objects.equals(oldItem.senses, newItem.senses) &&
Objects.equals(oldItem.shieldBonus, newItem.shieldBonus) &&
Objects.equals(oldItem.size, newItem.size) &&
Objects.equals(oldItem.skills, newItem.skills) &&
Objects.equals(oldItem.strengthSavingThrowAdvantage, newItem.strengthSavingThrowAdvantage) &&
Objects.equals(oldItem.strengthSavingThrowProficiency, newItem.strengthSavingThrowProficiency) &&
Objects.equals(oldItem.strengthScore, newItem.strengthScore) &&
Objects.equals(oldItem.subtype, newItem.subtype) &&
Objects.equals(oldItem.swimSpeed, newItem.swimSpeed) &&
Objects.equals(oldItem.telepathyRange, newItem.telepathyRange) &&
Objects.equals(oldItem.type, newItem.type) &&
Objects.equals(oldItem.understandsButDescription, newItem.understandsButDescription) &&
Objects.equals(oldItem.wisdomSavingThrowAdvantage, newItem.wisdomSavingThrowAdvantage) &&
Objects.equals(oldItem.wisdomSavingThrowProficiency, newItem.wisdomSavingThrowProficiency) &&
Objects.equals(oldItem.wisdomScore, newItem.wisdomScore) &&
Objects.equals(oldItem.walkSpeed, newItem.walkSpeed);
}
public String getMeta() { public String getMeta() {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
boolean isFirstOutput = true; boolean isFirstOutput = true;
@@ -304,7 +370,7 @@ public class Monster {
return sb.toString(); return sb.toString();
} }
public int getAbilityScore(@NonNull AbilityScore abilityScore) { public int getAbilityScore(@NotNull AbilityScore abilityScore) {
switch (abilityScore) { switch (abilityScore) {
case STRENGTH: case STRENGTH:
return strengthScore; return strengthScore;
@@ -323,7 +389,7 @@ public class Monster {
} }
} }
public int getAbilityModifier(@NonNull AbilityScore abilityScore) { public int getAbilityModifier(@NotNull AbilityScore abilityScore) {
switch (abilityScore) { switch (abilityScore) {
case STRENGTH: case STRENGTH:
return getStrengthModifier(); return getStrengthModifier();
@@ -342,7 +408,7 @@ public class Monster {
} }
} }
public AdvantageType getSavingThrowAdvantageType(@NonNull AbilityScore abilityScore) { public AdvantageType getSavingThrowAdvantageType(@NotNull AbilityScore abilityScore) {
switch (abilityScore) { switch (abilityScore) {
case STRENGTH: case STRENGTH:
return strengthSavingThrowAdvantage; return strengthSavingThrowAdvantage;
@@ -361,7 +427,7 @@ public class Monster {
} }
} }
public ProficiencyType getSavingThrowProficiencyType(@NonNull AbilityScore abilityScore) { public ProficiencyType getSavingThrowProficiencyType(@NotNull AbilityScore abilityScore) {
switch (abilityScore) { switch (abilityScore) {
case STRENGTH: case STRENGTH:
return strengthSavingThrowProficiency; return strengthSavingThrowProficiency;
@@ -607,7 +673,7 @@ public class Monster {
} }
} }
public int getProficiencyBonus(@NonNull ProficiencyType proficiencyType) { public int getProficiencyBonus(@NotNull ProficiencyType proficiencyType) {
switch (proficiencyType) { switch (proficiencyType) {
case PROFICIENT: case PROFICIENT:
return getProficiencyBonus(); return getProficiencyBonus();
@@ -751,7 +817,7 @@ public class Monster {
return abilityDescriptions; return abilityDescriptions;
} }
public String getPlaceholderReplacedText(@NonNull String rawText) { public String getPlaceholderReplacedText(@NotNull String rawText) {
return rawText return rawText
.replaceAll("\\[STR SAVE]", String.format("%+d", getSpellSaveDC(AbilityScore.STRENGTH))) .replaceAll("\\[STR SAVE]", String.format("%+d", getSpellSaveDC(AbilityScore.STRENGTH)))
.replaceAll("\\[STR ATK]", String.format("%+d", getAttackBonus(AbilityScore.STRENGTH))) .replaceAll("\\[STR ATK]", String.format("%+d", getAttackBonus(AbilityScore.STRENGTH)))
@@ -816,7 +882,7 @@ public class Monster {
} }
@Override @Override
public boolean equals(@Nullable Object obj) { public boolean equals(@Nullable @org.jetbrains.annotations.Nullable Object obj) {
if (obj == null) { if (obj == null) {
return false; return false;
} }

View File

@@ -2,14 +2,11 @@ package com.majinnaibu.monstercards.models;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import androidx.annotation.Nullable;
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 java.util.Comparator; import java.util.Comparator;
import java.util.Objects;
@SuppressLint("DefaultLocale") @SuppressLint("DefaultLocale")
public class Skill implements Comparator<Skill>, Comparable<Skill> { public class Skill implements Comparator<Skill>, Comparable<Skill> {
@@ -52,7 +49,7 @@ public class Skill implements Comparator<Skill>, Comparable<Skill> {
return String.format( return String.format(
"%s%s %+d%s", "%s%s %+d%s",
name.charAt(0), name.substring(0, 1),
name.substring(1), name.substring(1),
bonus, bonus,
advantageType == AdvantageType.ADVANTAGE ? " A" : advantageType == AdvantageType.DISADVANTAGE ? " D" : "" advantageType == AdvantageType.ADVANTAGE ? " A" : advantageType == AdvantageType.DISADVANTAGE ? " D" : ""
@@ -69,27 +66,4 @@ public class Skill implements Comparator<Skill>, Comparable<Skill> {
return o1.name.compareToIgnoreCase(o2.name); return o1.name.compareToIgnoreCase(o2.name);
} }
@Override
public boolean equals(@Nullable Object obj) {
if (obj == null) {
return false;
}
if (!(obj instanceof Skill)) {
return false;
}
Skill otherSkill = (Skill) obj;
if (!Objects.equals(this.name, otherSkill.name)) {
return false;
}
if (this.abilityScore != otherSkill.abilityScore) {
return false;
}
if (this.advantageType != otherSkill.advantageType) {
return false;
}
if (this.proficiencyType != otherSkill.proficiencyType) {
return false;
}
return true;
}
} }

View File

@@ -1,11 +1,6 @@
package com.majinnaibu.monstercards.models; package com.majinnaibu.monstercards.models;
import androidx.annotation.Nullable; public class Trait {
import java.util.Comparator;
import java.util.Objects;
public class Trait implements Comparator<Trait>, Comparable<Trait> {
public String name; public String name;
public String description; public String description;
@@ -14,36 +9,4 @@ public class Trait implements Comparator<Trait>, Comparable<Trait> {
this.name = name; this.name = name;
this.description = description; this.description = description;
} }
@Override
public int compareTo(Trait o) {
return compare(this, o);
}
@Override
public int compare(Trait o1, Trait o2) {
int result = o1.name.compareToIgnoreCase(o2.name);
if (result != 0) {
return result;
}
return o1.description.compareToIgnoreCase(o2.description);
}
@Override
public boolean equals(@Nullable Object obj) {
if (obj == null) {
return false;
}
if (!(obj instanceof Trait)) {
return false;
}
Trait otherTrait = (Trait) obj;
if (!Objects.equals(this.name, otherTrait.name)) {
return false;
}
if (!Objects.equals(this.description, otherTrait.description)) {
return false;
}
return true;
}
} }

View File

@@ -0,0 +1,72 @@
package com.majinnaibu.monstercards.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;
}
}
}

View File

@@ -0,0 +1,119 @@
package com.majinnaibu.monstercards.ui;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.navigation.NavDirections;
import androidx.navigation.Navigation;
import androidx.recyclerview.widget.RecyclerView;
import com.majinnaibu.monstercards.R;
import com.majinnaibu.monstercards.models.Monster;
import com.majinnaibu.monstercards.ui.library.LibraryFragment;
import com.majinnaibu.monstercards.ui.library.LibraryFragmentDirections;
import java.util.ArrayList;
import java.util.List;
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
import io.reactivex.rxjava3.core.Flowable;
import io.reactivex.rxjava3.schedulers.Schedulers;
public class MonsterListRecyclerViewAdapter extends RecyclerView.Adapter<MonsterListRecyclerViewAdapter.ViewHolder> {
public interface ItemCallback {
void onItem(Monster monster);
}
// TODO: Replace SimpleItemRecyclerViewAdapter with something better like MonsterListRecyclerViewAdapter that can be reused in search
private final LibraryFragment mParentActivity;
private List<Monster> mValues;
private final boolean mTwoPane;
private final Context mContext;
private final ItemCallback mOnDelete;
private final View.OnClickListener mOnClickListener = new View.OnClickListener() {
@Override
public void onClick(View view) {
Monster monster = (Monster) view.getTag();
// TODO: I would like to call navigateToMonsterDetail(item.id) here
if (mTwoPane) {
// TODO: Figure out how to navigate to a MonsterDetailFragment when in two pane view.
// Bundle arguments = new Bundle();
// arguments.putString(ItemDetailFragment.ARG_ITEM_ID, monster.id.toString());
// ItemDetailFragment fragment = new ItemDetailFragment();
// fragment.setArguments(arguments);
// mParentActivity.getSupportFragmentManager().beginTransaction()
// .replace(R.id.item_detail_container, fragment)
// .commit();
} else {
NavDirections action = LibraryFragmentDirections.actionNavigationLibraryToNavigationMonster(monster.id.toString());
Navigation.findNavController(view).navigate(action);
}
}
};
public MonsterListRecyclerViewAdapter(LibraryFragment parent,
Flowable<List<Monster>> itemsObservable,
ItemCallback onDelete,
boolean twoPane) {
mValues = new ArrayList<>();
mParentActivity = parent;
mTwoPane = twoPane;
mContext = parent.getContext();
mOnDelete = onDelete;
itemsObservable
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(monsters -> {
mValues = monsters;
notifyDataSetChanged();
});
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.monster_list_content, parent, false);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(final ViewHolder holder, int position) {
holder.mIdView.setText(mValues.get(position).id.toString().substring(0, 6));
holder.mContentView.setText(mValues.get(position).name);
holder.itemView.setTag(mValues.get(position));
holder.itemView.setOnClickListener(mOnClickListener);
}
@Override
public int getItemCount() {
return mValues.size();
}
public Context getContext() {
return mContext;
}
class ViewHolder extends RecyclerView.ViewHolder {
final TextView mIdView;
final TextView mContentView;
ViewHolder(View view) {
super(view);
mIdView = view.findViewById(R.id.id_text);
mContentView = view.findViewById(R.id.content);
}
}
public void deleteItem(int position) {
if (mOnDelete != null) {
Monster monster = mValues.get(position);
mOnDelete.onItem(monster);
}
}
}

View File

@@ -7,6 +7,8 @@ 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;
@@ -21,7 +23,12 @@ public class CollectionsFragment extends MCFragment {
collectionsViewModel = new ViewModelProvider(this).get(CollectionsViewModel.class); collectionsViewModel = new ViewModelProvider(this).get(CollectionsViewModel.class);
View root = inflater.inflate(R.layout.fragment_collections, container, false); View root = inflater.inflate(R.layout.fragment_collections, container, false);
final TextView textView = root.findViewById(R.id.text_collections); final TextView textView = root.findViewById(R.id.text_collections);
collectionsViewModel.getText().observe(getViewLifecycleOwner(), textView::setText); collectionsViewModel.getText().observe(getViewLifecycleOwner(), new Observer<String>() {
@Override
public void onChanged(@Nullable String s) {
textView.setText(s);
}
});
return root; return root;
} }
} }

View File

@@ -6,7 +6,7 @@ import androidx.lifecycle.ViewModel;
public class CollectionsViewModel extends ViewModel { public class CollectionsViewModel extends ViewModel {
private final MutableLiveData<String> mText; private MutableLiveData<String> mText;
public CollectionsViewModel() { public CollectionsViewModel() {
mText = new MutableLiveData<>(); mText = new MutableLiveData<>();

View File

@@ -35,12 +35,11 @@ public class AbilityScorePicker extends LinearLayout {
// TODO: use this as default but allow setting via attribute // TODO: use this as default but allow setting via attribute
mLabel = "Ability Score"; mLabel = "Ability Score";
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.AbilityScorePicker, 0, 0); TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.Stepper, 0, 0);
String label = a.getString(R.styleable.AbilityScorePicker_label); String label = a.getString(R.styleable.Stepper_label);
if (label != null) { if (label != null) {
mLabel = label; mLabel = label;
} }
a.recycle();
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View root = inflater.inflate(R.layout.component_ability_score_picker, this, true); View root = inflater.inflate(R.layout.component_ability_score_picker, this, true);
@@ -70,17 +69,18 @@ public class AbilityScorePicker extends LinearLayout {
mHolder.spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { mHolder.spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override @Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
setValue((AbilityScore) parent.getItemAtPosition(position)); mSelectedValue = (AbilityScore) parent.getItemAtPosition(position);
} }
@Override @Override
public void onNothingSelected(AdapterView<?> parent) { public void onNothingSelected(AdapterView<?> parent) {
setValue(mSelectedValue = AbilityScore.STRENGTH); mSelectedValue = AbilityScore.STRENGTH;
} }
}); });
mHolder.spinner.setSelection(ArrayHelper.indexOf(AbilityScore.values(), mSelectedValue)); mHolder.spinner.setSelection(ArrayHelper.indexOf(AbilityScore.values(), mSelectedValue));
setValue(AbilityScore.STRENGTH); setValue(AbilityScore.STRENGTH);
// TODO: listen for changes on the component to update mSelectedValue;
} }
public AbilityScorePicker(@NonNull Context context) { public AbilityScorePicker(@NonNull Context context) {
@@ -93,8 +93,7 @@ public class AbilityScorePicker extends LinearLayout {
public void setValue(AbilityScore value) { public void setValue(AbilityScore value) {
if (value != mSelectedValue) { if (value != mSelectedValue) {
mSelectedValue = value; mHolder.spinner.setSelection(ArrayHelper.indexOf(AbilityScore.values(), mSelectedValue));
mHolder.spinner.setSelection(ArrayHelper.indexOf(AbilityScore.values(), value));
if (mOnValueChangedListener != null) { if (mOnValueChangedListener != null) {
mOnValueChangedListener.onValueChanged(value); mOnValueChangedListener.onValueChanged(value);
} }
@@ -125,7 +124,7 @@ public class AbilityScorePicker extends LinearLayout {
private final Spinner spinner; private final Spinner spinner;
private final TextView label; private final TextView label;
ViewHolder(@NonNull View root) { ViewHolder(View root) {
spinner = root.findViewById(R.id.spinner); spinner = root.findViewById(R.id.spinner);
label = root.findViewById(R.id.label); label = root.findViewById(R.id.label);
} }

View File

@@ -33,9 +33,9 @@ public class AdvantagePicker extends ConstraintLayout {
setValue(AdvantageType.NONE); setValue(AdvantageType.NONE);
mHolder.group.setOnCheckedChangeListener((group, checkedId) -> { mHolder.group.setOnCheckedChangeListener((group, checkedId) -> {
if (R.id.hasAdvantage == checkedId) { if (R.id.advantage == checkedId) {
setValue(AdvantageType.ADVANTAGE); setValue(AdvantageType.ADVANTAGE);
} else if (R.id.hasDisadvantage == checkedId) { } else if (R.id.disadvantage == checkedId) {
setValue(AdvantageType.DISADVANTAGE); setValue(AdvantageType.DISADVANTAGE);
} else { } else {
setValue(AdvantageType.NONE); setValue(AdvantageType.NONE);
@@ -60,11 +60,11 @@ public class AdvantagePicker extends ConstraintLayout {
} }
final int checkedId = mHolder.group.getCheckedRadioButtonId(); final int checkedId = mHolder.group.getCheckedRadioButtonId();
if (mSelectedValue == AdvantageType.ADVANTAGE) { if (mSelectedValue == AdvantageType.ADVANTAGE) {
if (checkedId != R.id.hasAdvantage) { if (checkedId != R.id.advantage) {
mHolder.advantage.setChecked(true); mHolder.advantage.setChecked(true);
} }
} else if (mSelectedValue == AdvantageType.DISADVANTAGE) { } else if (mSelectedValue == AdvantageType.DISADVANTAGE) {
if (checkedId != R.id.hasDisadvantage) { if (checkedId != R.id.disadvantage) {
mHolder.disadvantage.setChecked(true); mHolder.disadvantage.setChecked(true);
} }
} else { } else {
@@ -88,11 +88,11 @@ public class AdvantagePicker extends ConstraintLayout {
final MaterialRadioButton advantage; final MaterialRadioButton advantage;
final MaterialRadioButton disadvantage; final MaterialRadioButton disadvantage;
ViewHolder(@NonNull View root) { ViewHolder(View root) {
group = root.findViewById(R.id.group); group = root.findViewById(R.id.group);
none = root.findViewById(R.id.hasNoAdvantage); none = root.findViewById(R.id.none);
advantage = root.findViewById(R.id.hasAdvantage); advantage = root.findViewById(R.id.advantage);
disadvantage = root.findViewById(R.id.hasDisadvantage); disadvantage = root.findViewById(R.id.disadvantage);
} }
} }
} }

View File

@@ -88,7 +88,7 @@ public class ProficiencyPicker extends ConstraintLayout {
final MaterialRadioButton proficient; final MaterialRadioButton proficient;
final MaterialRadioButton expertise; final MaterialRadioButton expertise;
ViewHolder(@NonNull View root) { ViewHolder(View root) {
group = root.findViewById(R.id.group); group = root.findViewById(R.id.group);
none = root.findViewById(R.id.none); none = root.findViewById(R.id.none);
proficient = root.findViewById(R.id.proficient); proficient = root.findViewById(R.id.proficient);

View File

@@ -13,11 +13,11 @@ import androidx.annotation.Nullable;
import androidx.constraintlayout.widget.ConstraintLayout; import androidx.constraintlayout.widget.ConstraintLayout;
import com.majinnaibu.monstercards.R; import com.majinnaibu.monstercards.R;
import com.majinnaibu.monstercards.utils.Logger;
import java.util.Objects; import java.util.Objects;
@SuppressWarnings("unused")
public class Stepper extends ConstraintLayout { public class Stepper extends ConstraintLayout {
private final ViewHolder mHolder; private final ViewHolder mHolder;
private int mCurrentValue; private int mCurrentValue;
@@ -46,7 +46,6 @@ public class Stepper extends ConstraintLayout {
mHolder = new ViewHolder(root); mHolder = new ViewHolder(root);
setValue(mCurrentValue); setValue(mCurrentValue);
updateDisplayedValue();
mHolder.increment.setOnClickListener(v -> setValue(mCurrentValue + mStep)); mHolder.increment.setOnClickListener(v -> setValue(mCurrentValue + mStep));
mHolder.decrement.setOnClickListener(v -> setValue(mCurrentValue - mStep)); mHolder.decrement.setOnClickListener(v -> setValue(mCurrentValue - mStep));
@@ -75,22 +74,19 @@ public class Stepper extends ConstraintLayout {
public void setValue(int value) { public void setValue(int value) {
int oldValue = this.mCurrentValue; int oldValue = this.mCurrentValue;
int newValue = Math.min(mMaxValue, Math.max(mMinValue, value)); int newValue = Math.min(mMaxValue, Math.max(mMinValue, value));
Logger.logDebug(String.format("Setting stepper value value: %d, oldValue: %d, newValue: %d", value, oldValue, newValue));
if (newValue != oldValue) { if (newValue != oldValue) {
this.mCurrentValue = newValue; this.mCurrentValue = newValue;
if (mOnValueChangeListener != null) { if (mOnValueChangeListener != null) {
mOnValueChangeListener.onChange(newValue, oldValue); mOnValueChangeListener.onChange(newValue, oldValue);
} }
updateDisplayedValue();
}
}
private void updateDisplayedValue() {
if (mOnFormatValueCallback != null) { if (mOnFormatValueCallback != null) {
mHolder.text.setText(mOnFormatValueCallback.onFormatValue(this.mCurrentValue)); mHolder.text.setText(mOnFormatValueCallback.onFormatValue(this.mCurrentValue));
} else { } else {
mHolder.text.setText(String.valueOf(this.mCurrentValue)); mHolder.text.setText(String.valueOf(this.mCurrentValue));
} }
} }
}
public void setOnValueChangeListener(OnValueChangeListener listener) { public void setOnValueChangeListener(OnValueChangeListener listener) {
mOnValueChangeListener = listener; mOnValueChangeListener = listener;
@@ -98,7 +94,6 @@ public class Stepper extends ConstraintLayout {
public void setOnFormatValueCallback(OnFormatValueCallback callback) { public void setOnFormatValueCallback(OnFormatValueCallback callback) {
mOnFormatValueCallback = callback; mOnFormatValueCallback = callback;
updateDisplayedValue();
} }
public int getStep() { public int getStep() {
@@ -139,7 +134,7 @@ public class Stepper extends ConstraintLayout {
final Button increment; final Button increment;
final Button decrement; final Button decrement;
ViewHolder(@NonNull View root) { ViewHolder(View root) {
text = root.findViewById(R.id.text); text = root.findViewById(R.id.text);
label = root.findViewById(R.id.label); label = root.findViewById(R.id.label);
increment = root.findViewById(R.id.increment); increment = root.findViewById(R.id.increment);

View File

@@ -25,6 +25,7 @@ import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
import io.reactivex.rxjava3.schedulers.Schedulers; import io.reactivex.rxjava3.schedulers.Schedulers;
public class DashboardFragment extends MCFragment { public class DashboardFragment extends MCFragment {
private static final String MODIFIER_FORMAT = "%+d";
private DashboardViewModel mViewModel; private DashboardViewModel mViewModel;
private ViewHolder mHolder; private ViewHolder mHolder;
private DashboardRecyclerViewAdapter mAdapter; private DashboardRecyclerViewAdapter mAdapter;
@@ -37,18 +38,20 @@ public class DashboardFragment extends MCFragment {
setupRecyclerView(mHolder.list); setupRecyclerView(mHolder.list);
// TODO: subscribe better
getMonsterRepository() getMonsterRepository()
.getMonsters() .getMonsters()
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.subscribe(monsters -> mViewModel.setMonsters(monsters)); .subscribe(monsters -> {
mViewModel.setMonsters(monsters);
});
return root; return root;
} }
private void setupRecyclerView(@NonNull RecyclerView recyclerView) { private void setupRecyclerView(@NonNull RecyclerView recyclerView) {
int columnCount = Math.max(1, getResources().getConfiguration().screenWidthDp / 396); int columnCount = Math.max(1, (int) Math.floor(getResources().getConfiguration().screenWidthDp / 396));
Logger.logWTF(String.format("Setting column count to %d", columnCount));
Context context = requireContext(); Context context = requireContext();
GridLayoutManager layoutManager = new GridLayoutManager(context, columnCount); GridLayoutManager layoutManager = new GridLayoutManager(context, columnCount);
recyclerView.setLayoutManager(layoutManager); recyclerView.setLayoutManager(layoutManager);

View File

@@ -28,12 +28,12 @@ public class DashboardRecyclerViewAdapter extends ListAdapter<Monster, Dashboard
private static final DiffUtil.ItemCallback<Monster> DIFF_CALLBACK = new DiffUtil.ItemCallback<Monster>() { private static final DiffUtil.ItemCallback<Monster> DIFF_CALLBACK = new DiffUtil.ItemCallback<Monster>() {
@Override @Override
public boolean areItemsTheSame(@NonNull Monster oldItem, @NonNull Monster newItem) { public boolean areItemsTheSame(@NonNull Monster oldItem, @NonNull Monster newItem) {
return oldItem.id.equals(newItem.id); return Monster.areItemsTheSame(oldItem, newItem);
} }
@Override @Override
public boolean areContentsTheSame(@NonNull Monster oldItem, @NonNull Monster newItem) { public boolean areContentsTheSame(@NonNull Monster oldItem, @NonNull Monster newItem) {
return oldItem.equals(newItem); return Monster.areContentsTheSame(oldItem, newItem);
} }
}; };
private final ItemCallback mOnClick; private final ItemCallback mOnClick;
@@ -51,7 +51,6 @@ public class DashboardRecyclerViewAdapter extends ListAdapter<Monster, Dashboard
@Override @Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) { public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
Logger.logUnimplementedMethod();
Monster monster = getItem(position); Monster monster = getItem(position);
holder.monster = monster; holder.monster = monster;
holder.name.setText(monster.name); holder.name.setText(monster.name);
@@ -242,7 +241,6 @@ public class DashboardRecyclerViewAdapter extends ListAdapter<Monster, Dashboard
@NonNull @NonNull
public static String getChallengeRatingAbbreviation(@NonNull ChallengeRating challengeRating) { public static String getChallengeRatingAbbreviation(@NonNull ChallengeRating challengeRating) {
Logger.logUnimplementedMethod();
switch (challengeRating) { switch (challengeRating) {
case CUSTOM: case CUSTOM:
return "*"; return "*";

View File

@@ -5,7 +5,7 @@ import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import androidx.annotation.NonNull; import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider; import androidx.lifecycle.ViewModelProvider;
import androidx.navigation.NavBackStackEntry; import androidx.navigation.NavBackStackEntry;
import androidx.navigation.NavController; import androidx.navigation.NavController;
@@ -15,9 +15,7 @@ import com.majinnaibu.monstercards.R;
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.ui.shared.MCFragment;
import java.util.Locale; public class EditAbilityScoresFragment extends Fragment {
public class EditAbilityScoresFragment extends MCFragment {
private final String ABILITY_SCORE_FORMAT = "%d (%+d)"; private final String ABILITY_SCORE_FORMAT = "%d (%+d)";
private EditMonsterViewModel mViewModel; private EditMonsterViewModel mViewModel;
private ViewHolder mHolder; private ViewHolder mHolder;
@@ -27,37 +25,38 @@ public class EditAbilityScoresFragment extends MCFragment {
} }
@Override @Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) { Bundle savedInstanceState) {
NavController navController = Navigation.findNavController(requireActivity(), R.id.nav_host_fragment); NavController navController = Navigation.findNavController(requireActivity(), R.id.nav_host_fragment);
NavBackStackEntry backStackEntry = navController.getBackStackEntry(R.id.edit_monster_navigation); NavBackStackEntry backStackEntry = navController.getBackStackEntry(R.id.edit_monster_navigation);
mViewModel = new ViewModelProvider(backStackEntry).get(EditMonsterViewModel.class); mViewModel = new ViewModelProvider(backStackEntry).get(EditMonsterViewModel.class);
View root = inflater.inflate(R.layout.fragment_edit_ability_scores, container, false); View root = inflater.inflate(R.layout.fragment_edit_ability_scores, container, false);
mHolder = new ViewHolder(root); mHolder = new ViewHolder(root);
setTitle(getString(R.string.title_edit_ability_scores));
mViewModel.getStrength().observe(getViewLifecycleOwner(), value -> mHolder.strength.setValue(value)); mViewModel.getStrength().observe(getViewLifecycleOwner(), value -> mHolder.strength.setValue(value));
mHolder.strength.setOnValueChangeListener((newValue, oldValue) -> mViewModel.setStrength(newValue)); mHolder.strength.setOnValueChangeListener((newValue, oldValue) -> mViewModel.setStrength(newValue));
mHolder.strength.setOnFormatValueCallback(value -> String.format(Locale.getDefault(), ABILITY_SCORE_FORMAT, value, getModifier(value))); mHolder.strength.setOnFormatValueCallback(value -> String.format(ABILITY_SCORE_FORMAT, value, getModifier(value)));
mViewModel.getDexterity().observe(getViewLifecycleOwner(), value -> mHolder.dexterity.setValue(value)); mViewModel.getDexterity().observe(getViewLifecycleOwner(), value -> mHolder.dexterity.setValue(value));
mHolder.dexterity.setOnValueChangeListener((newValue, oldValue) -> mViewModel.setDexterity(newValue)); mHolder.dexterity.setOnValueChangeListener((newValue, oldValue) -> mViewModel.setDexterity(newValue));
mHolder.dexterity.setOnFormatValueCallback(value -> String.format(Locale.getDefault(), ABILITY_SCORE_FORMAT, value, getModifier(value))); mHolder.dexterity.setOnFormatValueCallback(value -> String.format(ABILITY_SCORE_FORMAT, value, getModifier(value)));
mViewModel.getConstitution().observe(getViewLifecycleOwner(), value -> mHolder.constitution.setValue(value)); mViewModel.getConstitution().observe(getViewLifecycleOwner(), value -> mHolder.constitution.setValue(value));
mHolder.constitution.setOnValueChangeListener((newValue, oldValue) -> mViewModel.setConstitution(newValue)); mHolder.constitution.setOnValueChangeListener((newValue, oldValue) -> mViewModel.setConstitution(newValue));
mHolder.constitution.setOnFormatValueCallback(value -> String.format(Locale.getDefault(), ABILITY_SCORE_FORMAT, value, getModifier(value))); mHolder.constitution.setOnFormatValueCallback(value -> String.format(ABILITY_SCORE_FORMAT, value, getModifier(value)));
mViewModel.getIntelligence().observe(getViewLifecycleOwner(), value -> mHolder.intelligence.setValue(value)); mViewModel.getIntelligence().observe(getViewLifecycleOwner(), value -> mHolder.intelligence.setValue(value));
mHolder.intelligence.setOnValueChangeListener((newValue, oldValue) -> mViewModel.setIntelligence(newValue)); mHolder.intelligence.setOnValueChangeListener((newValue, oldValue) -> mViewModel.setIntelligence(newValue));
mHolder.intelligence.setOnFormatValueCallback(value -> String.format(Locale.getDefault(), ABILITY_SCORE_FORMAT, value, getModifier(value))); mHolder.intelligence.setOnFormatValueCallback(value -> String.format(ABILITY_SCORE_FORMAT, value, getModifier(value)));
mViewModel.getWisdom().observe(getViewLifecycleOwner(), value -> mHolder.wisdom.setValue(value)); mViewModel.getWisdom().observe(getViewLifecycleOwner(), value -> mHolder.wisdom.setValue(value));
mHolder.wisdom.setOnValueChangeListener((newValue, oldValue) -> mViewModel.setWisdom(newValue)); mHolder.wisdom.setOnValueChangeListener((newValue, oldValue) -> mViewModel.setWisdom(newValue));
mHolder.wisdom.setOnFormatValueCallback(value -> String.format(Locale.getDefault(), ABILITY_SCORE_FORMAT, value, getModifier(value))); mHolder.wisdom.setOnFormatValueCallback(value -> String.format(ABILITY_SCORE_FORMAT, value, getModifier(value)));
mViewModel.getCharisma().observe(getViewLifecycleOwner(), value -> mHolder.charisma.setValue(value)); mViewModel.getCharisma().observe(getViewLifecycleOwner(), value -> mHolder.charisma.setValue(value));
mHolder.charisma.setOnValueChangeListener((newValue, oldValue) -> mViewModel.setCharisma(newValue)); mHolder.charisma.setOnValueChangeListener((newValue, oldValue) -> mViewModel.setCharisma(newValue));
mHolder.charisma.setOnFormatValueCallback(value -> String.format(Locale.getDefault(), ABILITY_SCORE_FORMAT, value, getModifier(value))); mHolder.charisma.setOnFormatValueCallback(value -> String.format(ABILITY_SCORE_FORMAT, value, getModifier(value)));
return root; return root;
} }
@@ -70,7 +69,7 @@ public class EditAbilityScoresFragment extends MCFragment {
final Stepper wisdom; final Stepper wisdom;
final Stepper charisma; final Stepper charisma;
ViewHolder(@NonNull View root) { ViewHolder(View root) {
strength = root.findViewById(R.id.strength); strength = root.findViewById(R.id.strength);
dexterity = root.findViewById(R.id.dexterity); dexterity = root.findViewById(R.id.dexterity);
constitution = root.findViewById(R.id.constitution); constitution = root.findViewById(R.id.constitution);

View File

@@ -30,13 +30,14 @@ public class EditArmorFragment extends MCFragment {
private ViewHolder mHolder; private ViewHolder mHolder;
@Override @Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) { Bundle savedInstanceState) {
NavController navController = Navigation.findNavController(requireActivity(), R.id.nav_host_fragment); NavController navController = Navigation.findNavController(requireActivity(), R.id.nav_host_fragment);
NavBackStackEntry backStackEntry = navController.getBackStackEntry(R.id.edit_monster_navigation); NavBackStackEntry backStackEntry = navController.getBackStackEntry(R.id.edit_monster_navigation);
mViewModel = new ViewModelProvider(backStackEntry).get(EditMonsterViewModel.class); mViewModel = new ViewModelProvider(backStackEntry).get(EditMonsterViewModel.class);
View root = inflater.inflate(R.layout.fragment_edit_armor, container, false); View root = inflater.inflate(R.layout.fragment_edit_armor, container, false);
mHolder = new ViewHolder(root); mHolder = new ViewHolder(root);
setTitle(getString(R.string.title_edit_armor));
mHolder.armorType.setAdapter(new ArrayAdapter<ArmorType>(requireContext(), R.layout.dropdown_list_item, ArmorType.values()) { mHolder.armorType.setAdapter(new ArrayAdapter<ArmorType>(requireContext(), R.layout.dropdown_list_item, ArmorType.values()) {
@NonNull @NonNull
@@ -93,7 +94,7 @@ public class EditArmorFragment extends MCFragment {
private final Stepper shieldBonus; private final Stepper shieldBonus;
private final EditText customArmor; private final EditText customArmor;
ViewHolder(@NonNull View root) { ViewHolder(View root) {
armorType = root.findViewById(R.id.armorType); armorType = root.findViewById(R.id.armorType);
naturalArmorBonus = root.findViewById(R.id.naturalArmorBonus); naturalArmorBonus = root.findViewById(R.id.naturalArmorBonus);
hasShield = root.findViewById(R.id.hasShield); hasShield = root.findViewById(R.id.hasShield);

View File

@@ -6,7 +6,6 @@ import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.EditText; import android.widget.EditText;
import androidx.annotation.NonNull;
import androidx.lifecycle.ViewModelProvider; import androidx.lifecycle.ViewModelProvider;
import androidx.navigation.NavBackStackEntry; import androidx.navigation.NavBackStackEntry;
import androidx.navigation.NavController; import androidx.navigation.NavController;
@@ -29,12 +28,13 @@ public class EditBasicInfoFragment extends MCFragment {
} }
@Override @Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) { Bundle savedInstanceState) {
NavController navController = Navigation.findNavController(requireActivity(), R.id.nav_host_fragment); NavController navController = Navigation.findNavController(requireActivity(), R.id.nav_host_fragment);
NavBackStackEntry backStackEntry = navController.getBackStackEntry(R.id.edit_monster_navigation); NavBackStackEntry backStackEntry = navController.getBackStackEntry(R.id.edit_monster_navigation);
mViewModel = new ViewModelProvider(backStackEntry).get(EditMonsterViewModel.class); mViewModel = new ViewModelProvider(backStackEntry).get(EditMonsterViewModel.class);
View root = inflater.inflate(R.layout.fragment_edit_basic_info, container, false); View root = inflater.inflate(R.layout.fragment_edit_basic_info, container, false);
setTitle(getString(R.string.title_edit_basic_info));
mHolder = new ViewHolder(root); mHolder = new ViewHolder(root);
mHolder.name.setText(mViewModel.getName().getValue()); mHolder.name.setText(mViewModel.getName().getValue());
@@ -74,7 +74,7 @@ public class EditBasicInfoFragment extends MCFragment {
private final Stepper hitDice; private final Stepper hitDice;
private final SwitchMaterial hasCustomHitPoints; private final SwitchMaterial hasCustomHitPoints;
ViewHolder(@NonNull View root) { ViewHolder(View root) {
name = root.findViewById(R.id.name); name = root.findViewById(R.id.name);
size = root.findViewById(R.id.size); size = root.findViewById(R.id.size);
type = root.findViewById(R.id.type); type = root.findViewById(R.id.type);

View File

@@ -28,13 +28,14 @@ public class EditChallengeRatingFragment extends MCFragment {
private ViewHolder mHolder; private ViewHolder mHolder;
@Override @Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) { Bundle savedInstanceState) {
NavController navController = Navigation.findNavController(requireActivity(), R.id.nav_host_fragment); NavController navController = Navigation.findNavController(requireActivity(), R.id.nav_host_fragment);
NavBackStackEntry backStackEntry = navController.getBackStackEntry(R.id.edit_monster_navigation); NavBackStackEntry backStackEntry = navController.getBackStackEntry(R.id.edit_monster_navigation);
mViewModel = new ViewModelProvider(backStackEntry).get(EditMonsterViewModel.class); mViewModel = new ViewModelProvider(backStackEntry).get(EditMonsterViewModel.class);
View root = inflater.inflate(R.layout.fragment_edit_challenge_rating, container, false); View root = inflater.inflate(R.layout.fragment_edit_challenge_rating, container, false);
mHolder = new ViewHolder(root); mHolder = new ViewHolder(root);
setTitle(getString(R.string.title_edit_challenge_rating));
mHolder.challengeRating.setAdapter(new ArrayAdapter<ChallengeRating>(requireContext(), R.layout.dropdown_list_item, ChallengeRating.values()) { mHolder.challengeRating.setAdapter(new ArrayAdapter<ChallengeRating>(requireContext(), R.layout.dropdown_list_item, ChallengeRating.values()) {
@NonNull @NonNull
@@ -82,7 +83,7 @@ public class EditChallengeRatingFragment extends MCFragment {
final EditText customChallengeRatingDescription; final EditText customChallengeRatingDescription;
final EditText customProficiencyBonus; final EditText customProficiencyBonus;
ViewHolder(@NonNull View root) { ViewHolder(View root) {
challengeRating = root.findViewById(R.id.challengeRating); challengeRating = root.findViewById(R.id.challengeRating);
customChallengeRatingDescription = root.findViewById(R.id.customChallengeRatingDescription); customChallengeRatingDescription = root.findViewById(R.id.customChallengeRatingDescription);
customProficiencyBonus = root.findViewById(R.id.customProficiencyBonus); customProficiencyBonus = root.findViewById(R.id.customProficiencyBonus);

View File

@@ -44,12 +44,13 @@ public class EditLanguageFragment extends MCFragment {
@Nullable @Nullable
@Override @Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable @org.jetbrains.annotations.Nullable Bundle savedInstanceState) {
NavController navController = Navigation.findNavController(requireActivity(), R.id.nav_host_fragment); NavController navController = Navigation.findNavController(requireActivity(), R.id.nav_host_fragment);
NavBackStackEntry backStackEntry = navController.getBackStackEntry(R.id.edit_monster_navigation); NavBackStackEntry backStackEntry = navController.getBackStackEntry(R.id.edit_monster_navigation);
mEditMonsterViewModel = new ViewModelProvider(backStackEntry).get(EditMonsterViewModel.class); mEditMonsterViewModel = new ViewModelProvider(backStackEntry).get(EditMonsterViewModel.class);
View root = inflater.inflate(R.layout.fragment_edit_language, container, false); View root = inflater.inflate(R.layout.fragment_edit_language, container, false);
mHolder = new ViewHolder(root); mHolder = new ViewHolder(root);
setTitle(getString(R.string.title_edit_language));
mHolder.name.setText(mViewModel.getName().getValue()); mHolder.name.setText(mViewModel.getName().getValue());
mHolder.name.addTextChangedListener(new TextChangedListener((TextChangedListener.OnTextChangedCallback) (s, start, before, count) -> mViewModel.setName(s.toString()))); mHolder.name.addTextChangedListener(new TextChangedListener((TextChangedListener.OnTextChangedCallback) (s, start, before, count) -> mViewModel.setName(s.toString())));
@@ -80,7 +81,7 @@ public class EditLanguageFragment extends MCFragment {
EditText name; EditText name;
SwitchCompat canSpeak; SwitchCompat canSpeak;
ViewHolder(@NonNull View root) { ViewHolder(View root) {
name = root.findViewById(R.id.name); name = root.findViewById(R.id.name);
canSpeak = root.findViewById(R.id.canSpeak); canSpeak = root.findViewById(R.id.canSpeak);
} }

View File

@@ -1,6 +1,5 @@
package com.majinnaibu.monstercards.ui.editmonster; package com.majinnaibu.monstercards.ui.editmonster;
import androidx.annotation.NonNull;
import androidx.lifecycle.LiveData; import androidx.lifecycle.LiveData;
import com.majinnaibu.monstercards.models.Language; import com.majinnaibu.monstercards.models.Language;
@@ -19,7 +18,7 @@ public class EditLanguageViewModel extends ChangeTrackedViewModel {
mLanguage = new ChangeTrackedLiveData<>(makeLanguage(), this::makeDirty); mLanguage = new ChangeTrackedLiveData<>(makeLanguage(), this::makeDirty);
} }
public void copyFromLanguage(@NonNull Language language) { public void copyFromLanguage(Language language) {
mName.resetValue(language.getName()); mName.resetValue(language.getName());
mCanSpeak.resetValue(language.getSpeaks()); mCanSpeak.resetValue(language.getSpeaks());
makeClean(); makeClean();
@@ -59,7 +58,6 @@ public class EditLanguageViewModel extends ChangeTrackedViewModel {
return getCanSpeakValue(false); return getCanSpeakValue(false);
} }
@NonNull
private Language makeLanguage() { private Language makeLanguage() {
Boolean boxedValue = mCanSpeak.getValue(); Boolean boxedValue = mCanSpeak.getValue();
boolean canSpeak = boxedValue != null && boxedValue; boolean canSpeak = boxedValue != null && boxedValue;

View File

@@ -30,19 +30,20 @@ public class EditLanguagesFragment extends MCFragment {
private EditMonsterViewModel mViewModel; private EditMonsterViewModel mViewModel;
private ViewHolder mHolder; private ViewHolder mHolder;
private void navigateToEditLanguage(@NonNull Language language) { private void navigateToEditLanguage(Language language) {
NavDirections action = EditLanguagesFragmentDirections.actionEditLanguagesFragmentToEditLanguageFragment(language.getName(), language.getSpeaks()); NavDirections action = EditLanguagesFragmentDirections.actionEditLanguagesFragmentToEditLanguageFragment(language.getName(), language.getSpeaks());
Navigation.findNavController(requireView()).navigate(action); Navigation.findNavController(requireView()).navigate(action);
} }
@Override @Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) { Bundle savedInstanceState) {
NavController navController = Navigation.findNavController(requireActivity(), R.id.nav_host_fragment); NavController navController = Navigation.findNavController(requireActivity(), R.id.nav_host_fragment);
NavBackStackEntry backStackEntry = navController.getBackStackEntry(R.id.edit_monster_navigation); NavBackStackEntry backStackEntry = navController.getBackStackEntry(R.id.edit_monster_navigation);
mViewModel = new ViewModelProvider(backStackEntry).get(EditMonsterViewModel.class); mViewModel = new ViewModelProvider(backStackEntry).get(EditMonsterViewModel.class);
View root = inflater.inflate(R.layout.fragment_edit_languages_list, container, false); View root = inflater.inflate(R.layout.fragment_edit_languages_list, container, false);
mHolder = new ViewHolder(root); mHolder = new ViewHolder(root);
setTitle(getString(R.string.title_edit_languages));
setupRecyclerView(mHolder.list); setupRecyclerView(mHolder.list);
setupAddLanguageButton(mHolder.addLanguage); setupAddLanguageButton(mHolder.addLanguage);
@@ -93,7 +94,7 @@ public class EditLanguagesFragment extends MCFragment {
RecyclerView list; RecyclerView list;
FloatingActionButton addLanguage; FloatingActionButton addLanguage;
ViewHolder(@NonNull View root) { ViewHolder(View root) {
this.list = root.findViewById(R.id.list); this.list = root.findViewById(R.id.list);
this.addLanguage = root.findViewById(R.id.add_language); this.addLanguage = root.findViewById(R.id.add_language);
} }

View File

@@ -6,7 +6,6 @@ import android.view.ViewGroup;
import android.widget.EditText; import android.widget.EditText;
import android.widget.TextView; import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import com.majinnaibu.monstercards.databinding.FragmentEditLanguagesListHeaderBinding; import com.majinnaibu.monstercards.databinding.FragmentEditLanguagesListHeaderBinding;
@@ -14,8 +13,9 @@ import com.majinnaibu.monstercards.databinding.FragmentEditLanguagesListItemBind
import com.majinnaibu.monstercards.models.Language; import com.majinnaibu.monstercards.models.Language;
import com.majinnaibu.monstercards.ui.components.Stepper; import com.majinnaibu.monstercards.ui.components.Stepper;
import org.jetbrains.annotations.NotNull;
import java.util.List; import java.util.List;
import java.util.Locale;
public class EditLanguagesRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { public class EditLanguagesRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private final List<Language> mValues; private final List<Language> mValues;
@@ -29,18 +29,18 @@ public class EditLanguagesRecyclerViewAdapter extends RecyclerView.Adapter<Recyc
private final int ITEM_VIEW_TYPE = 2; private final int ITEM_VIEW_TYPE = 2;
private final String DISTANCE_IN_FEET_FORMAT = "%d ft."; private final String DISTANCE_IN_FEET_FORMAT = "%d ft.";
public EditLanguagesRecyclerViewAdapter(List<Language> items, ItemCallback onClick, int telepathyRange, Stepper.OnValueChangeListener telepathyRangeChangedListener, String understandsBut, TextWatcher understandsButChangedListener) { public EditLanguagesRecyclerViewAdapter(List<Language> items, ItemCallback onClick, int telepathyRange, Stepper.OnValueChangeListener telepathyRangeChangedListener, String undderstandsBut, TextWatcher understandsButChangedListener) {
mValues = items; mValues = items;
mOnClick = onClick; mOnClick = onClick;
mTelepathyRange = telepathyRange; mTelepathyRange = telepathyRange;
mOnTelepathyRangeChanged = telepathyRangeChangedListener; mOnTelepathyRangeChanged = telepathyRangeChangedListener;
mUnderstandsBut = understandsBut; mUnderstandsBut = undderstandsBut;
mOnUnderstandsButChanged = understandsButChangedListener; mOnUnderstandsButChanged = understandsButChangedListener;
} }
@NonNull @NotNull
@Override @Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { public RecyclerView.ViewHolder onCreateViewHolder(@NotNull ViewGroup parent, int viewType) {
if (viewType == HEADER_VIEW_TYPE) { if (viewType == HEADER_VIEW_TYPE) {
return new HeaderViewHolder(FragmentEditLanguagesListHeaderBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false)); return new HeaderViewHolder(FragmentEditLanguagesListHeaderBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false));
} }
@@ -48,10 +48,10 @@ public class EditLanguagesRecyclerViewAdapter extends RecyclerView.Adapter<Recyc
} }
@Override @Override
public void onBindViewHolder(@NonNull final RecyclerView.ViewHolder holder, int position) { public void onBindViewHolder(@NotNull final RecyclerView.ViewHolder holder, int position) {
if (holder instanceof HeaderViewHolder) { if (holder instanceof HeaderViewHolder) {
HeaderViewHolder headerViewHolder = (HeaderViewHolder) holder; HeaderViewHolder headerViewHolder = (HeaderViewHolder) holder;
headerViewHolder.telepathy.setOnFormatValueCallback(value -> String.format(Locale.getDefault(), DISTANCE_IN_FEET_FORMAT, value)); headerViewHolder.telepathy.setOnFormatValueCallback(value -> String.format(DISTANCE_IN_FEET_FORMAT, value));
headerViewHolder.telepathy.setValue(mTelepathyRange); headerViewHolder.telepathy.setValue(mTelepathyRange);
headerViewHolder.telepathy.setOnValueChangeListener(mOnTelepathyRangeChanged); headerViewHolder.telepathy.setOnValueChangeListener(mOnTelepathyRangeChanged);
headerViewHolder.understandsBut.setText(mUnderstandsBut); headerViewHolder.understandsBut.setText(mUnderstandsBut);
@@ -89,7 +89,7 @@ public class EditLanguagesRecyclerViewAdapter extends RecyclerView.Adapter<Recyc
public final Stepper telepathy; public final Stepper telepathy;
public final EditText understandsBut; public final EditText understandsBut;
public HeaderViewHolder(@NonNull FragmentEditLanguagesListHeaderBinding binding) { public HeaderViewHolder(FragmentEditLanguagesListHeaderBinding binding) {
super(binding.getRoot()); super(binding.getRoot());
telepathy = binding.telepathy; telepathy = binding.telepathy;
understandsBut = binding.understandsBut; understandsBut = binding.understandsBut;
@@ -100,12 +100,12 @@ public class EditLanguagesRecyclerViewAdapter extends RecyclerView.Adapter<Recyc
public final TextView mContentView; public final TextView mContentView;
public Language mItem; public Language mItem;
public ItemViewHolder(@NonNull FragmentEditLanguagesListItemBinding binding) { public ItemViewHolder(FragmentEditLanguagesListItemBinding binding) {
super(binding.getRoot()); super(binding.getRoot());
mContentView = binding.content; mContentView = binding.content;
} }
@NonNull @NotNull
@Override @Override
public String toString() { public String toString() {
return super.toString() + " '" + mContentView.getText() + "'"; return super.toString() + " '" + mContentView.getText() + "'";

View File

@@ -55,7 +55,7 @@ public class EditMonsterFragment extends MCFragment {
View root = inflater.inflate(R.layout.fragment_edit_monster, container, false); View root = inflater.inflate(R.layout.fragment_edit_monster, container, false);
mHolder = new ViewHolder(root); mHolder = new ViewHolder(root);
setTitle(getString(R.string.title_editMonster_fmt, getString(R.string.default_monster_name))); setTitle(getString(R.string.title_edit_monster, getString(R.string.default_monster_name)));
// TODO: Show a loading spinner until we have the monster loaded. // TODO: Show a loading spinner until we have the monster loaded.
if (mViewModel.hasError() || !mViewModel.hasLoaded() || !Objects.equals(mViewModel.getMonsterId().getValue(), monsterId)) { if (mViewModel.hasError() || !mViewModel.hasLoaded() || !Objects.equals(mViewModel.getMonsterId().getValue(), monsterId)) {
@@ -67,7 +67,7 @@ public class EditMonsterFragment extends MCFragment {
mViewModel.setHasLoaded(true); mViewModel.setHasLoaded(true);
mViewModel.setHasError(false); mViewModel.setHasError(false);
mViewModel.copyFromMonster(monster); mViewModel.copyFromMonster(monster);
setTitle(getString(R.string.title_editMonster_fmt, monster.name)); setTitle(getString(R.string.title_edit_monster, monster.name));
dispose(); dispose();
} }
@@ -247,7 +247,7 @@ public class EditMonsterFragment extends MCFragment {
TextView lairActions; TextView lairActions;
TextView regionalActions; TextView regionalActions;
ViewHolder(@NonNull View root) { ViewHolder(View root) {
basicInfoButton = root.findViewById(R.id.basicInfo); basicInfoButton = root.findViewById(R.id.basicInfo);
armorButton = root.findViewById(R.id.armor); armorButton = root.findViewById(R.id.armor);
speedButton = root.findViewById(R.id.speed); speedButton = root.findViewById(R.id.speed);

View File

@@ -28,7 +28,7 @@ import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.util.UUID; import java.util.UUID;
@SuppressWarnings({"ConstantConditions"}) @SuppressWarnings({"ConstantConditions", "unused"})
public class EditMonsterViewModel extends ChangeTrackedViewModel { 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;
@@ -158,7 +158,7 @@ public class EditMonsterViewModel extends ChangeTrackedViewModel {
mRegionalActions = new ChangeTrackedLiveData<>(new ArrayList<>(), this::makeDirty); mRegionalActions = new ChangeTrackedLiveData<>(new ArrayList<>(), this::makeDirty);
} }
public void copyFromMonster(@NonNull Monster monster) { public void copyFromMonster(Monster monster) {
mMonsterId.resetValue(monster.id); mMonsterId.resetValue(monster.id);
mName.resetValue(monster.name); mName.resetValue(monster.name);
mSize.resetValue(monster.size); mSize.resetValue(monster.size);
@@ -206,7 +206,7 @@ public class EditMonsterViewModel extends ChangeTrackedViewModel {
mUnderstandsButDescription.resetValue(monster.understandsButDescription); mUnderstandsButDescription.resetValue(monster.understandsButDescription);
ArrayList<Skill> skills = new ArrayList<>(monster.skills); ArrayList<Skill> skills = new ArrayList<>(monster.skills);
Collections.sort(skills, Skill::compareTo); Collections.sort(skills, (skill1, skill2) -> skill1.name.compareToIgnoreCase(skill2.name));
mSkills.resetValue(skills); mSkills.resetValue(skills);
ArrayList<String> senses = new ArrayList<>(monster.senses); ArrayList<String> senses = new ArrayList<>(monster.senses);
Collections.sort(senses, String::compareToIgnoreCase); Collections.sort(senses, String::compareToIgnoreCase);
@@ -224,7 +224,7 @@ public class EditMonsterViewModel extends ChangeTrackedViewModel {
Collections.sort(conditionImmunities, String::compareToIgnoreCase); Collections.sort(conditionImmunities, String::compareToIgnoreCase);
mConditionImmunities.resetValue(conditionImmunities); mConditionImmunities.resetValue(conditionImmunities);
ArrayList<Language> languages = new ArrayList<>(monster.languages); ArrayList<Language> languages = new ArrayList<>(monster.languages);
Collections.sort(languages, Language::compareTo); Collections.sort(languages, (lang1, lang2) -> lang1.getName().compareToIgnoreCase(lang2.getName()));
mLanguages.resetValue(languages); mLanguages.resetValue(languages);
mAbilities.resetValue(new ArrayList<>(monster.abilities)); mAbilities.resetValue(new ArrayList<>(monster.abilities));
mActions.resetValue(new ArrayList<>(monster.actions)); mActions.resetValue(new ArrayList<>(monster.actions));
@@ -247,6 +247,10 @@ public class EditMonsterViewModel extends ChangeTrackedViewModel {
return mMonsterId; return mMonsterId;
} }
public LiveData<String> getErrorMessage() {
return mErrorMessage;
}
public void setErrorMessage(@NonNull String errorMessage) { public void setErrorMessage(@NonNull String errorMessage) {
mErrorMessage.setValue(errorMessage); mErrorMessage.setValue(errorMessage);
} }
@@ -315,22 +319,48 @@ public class EditMonsterViewModel extends ChangeTrackedViewModel {
mCustomHitPoints.setValue(customHitPoints); mCustomHitPoints.setValue(customHitPoints);
} }
public LiveData<Integer> getHitDice() {
return mHitDice;
}
public void setHitDice(int hitDice) { public void setHitDice(int hitDice) {
mHitDice.setValue(hitDice); mHitDice.setValue(hitDice);
} }
public void setHitDice(String hitDice) {
Integer parsedHitDice = StringHelper.parseInt(hitDice);
this.setHitDice(parsedHitDice != null ? parsedHitDice : 0);
}
public int getHitDiceUnboxed() { public int getHitDiceUnboxed() {
return Helpers.unboxInteger(mHitDice.getValue(), 1); return Helpers.unboxInteger(mHitDice.getValue(), 1);
} }
public String getHitDiceValueAsString() {
return mHitDice.getValue().toString();
}
public LiveData<Integer> getNaturalArmorBonus() {
return mNaturalArmorBonus;
}
public void setNaturalArmorBonus(int naturalArmorBonus) { public void setNaturalArmorBonus(int naturalArmorBonus) {
mNaturalArmorBonus.setValue(naturalArmorBonus); mNaturalArmorBonus.setValue(naturalArmorBonus);
} }
public void setNaturalArmorBonus(String naturalArmorBonus) {
Integer parsedValue = StringHelper.parseInt(naturalArmorBonus);
this.setNaturalArmorBonus(parsedValue != null ? parsedValue : 0);
}
public int getNaturalArmorBonusUnboxed() { public int getNaturalArmorBonusUnboxed() {
return Helpers.unboxInteger(mNaturalArmorBonus.getValue(), 0); return Helpers.unboxInteger(mNaturalArmorBonus.getValue(), 0);
} }
public String getNaturalArmorBonusValueAsString() {
return mNaturalArmorBonus.getValue().toString();
}
public LiveData<Boolean> getHasCustomHitPoints() { public LiveData<Boolean> getHasCustomHitPoints() {
return mHasCustomHitPoints; return mHasCustomHitPoints;
} }
@@ -351,6 +381,10 @@ public class EditMonsterViewModel extends ChangeTrackedViewModel {
mArmorType.setValue(armorType); mArmorType.setValue(armorType);
} }
public LiveData<Boolean> getHasShield() {
return mHasShield;
}
public void setHasShield(boolean hasShield) { public void setHasShield(boolean hasShield) {
mHasShield.setValue(hasShield); mHasShield.setValue(hasShield);
} }
@@ -359,10 +393,19 @@ public class EditMonsterViewModel extends ChangeTrackedViewModel {
return mHasShield.getValue(); return mHasShield.getValue();
} }
public LiveData<Integer> getShieldBonus() {
return mShieldBonus;
}
public void setShieldBonus(int shieldBonus) { public void setShieldBonus(int shieldBonus) {
mShieldBonus.setValue(shieldBonus); mShieldBonus.setValue(shieldBonus);
} }
public void setShieldBonus(String shieldBonus) {
Integer parsedValue = StringHelper.parseInt(shieldBonus);
this.setShieldBonus(parsedValue != null ? parsedValue : 0);
}
public int getShieldBonusUnboxed() { public int getShieldBonusUnboxed() {
return Helpers.unboxInteger(mShieldBonus.getValue(), 0); return Helpers.unboxInteger(mShieldBonus.getValue(), 0);
} }
@@ -387,6 +430,14 @@ public class EditMonsterViewModel extends ChangeTrackedViewModel {
mWalkSpeed.setValue(walkSpeed); mWalkSpeed.setValue(walkSpeed);
} }
public void incrementWalkSpeed() {
setWalkSpeed(mWalkSpeed.getValue() + 5);
}
public void decrementWalkSpeed() {
setWalkSpeed(mWalkSpeed.getValue() - 5);
}
public LiveData<Integer> getBurrowSpeed() { public LiveData<Integer> getBurrowSpeed() {
return mBurrowSpeed; return mBurrowSpeed;
} }
@@ -443,6 +494,38 @@ public class EditMonsterViewModel extends ChangeTrackedViewModel {
mCustomSpeed.setValue(customSpeed); mCustomSpeed.setValue(customSpeed);
} }
public void incrementBurrowSpeed() {
setBurrowSpeed(mBurrowSpeed.getValue() + 5);
}
public void decrementBurrowSpeed() {
setBurrowSpeed(mBurrowSpeed.getValue() - 5);
}
public void incrementClimbSpeed() {
setClimbSpeed(mClimbSpeed.getValue() + 5);
}
public void decrementClimbSpeed() {
setClimbSpeed(mClimbSpeed.getValue() - 5);
}
public void incrementFlySpeed() {
setFlySpeed(mFlySpeed.getValue() + 5);
}
public void decrementFlySpeed() {
setFlySpeed(mFlySpeed.getValue() - 5);
}
public void incrementSwimSpeed() {
setSwimSpeed(mSwimSpeed.getValue() + 5);
}
public void decrementSwimSpeed() {
setSwimSpeed(mSwimSpeed.getValue() - 5);
}
public LiveData<Integer> getStrength() { public LiveData<Integer> getStrength() {
return mStrength; return mStrength;
} }
@@ -451,6 +534,14 @@ public class EditMonsterViewModel extends ChangeTrackedViewModel {
mStrength.setValue(strength); mStrength.setValue(strength);
} }
public void incrementStrength() {
setStrength(mStrength.getValue() + 1);
}
public void decrementStrength() {
setStrength(mStrength.getValue() - 1);
}
public LiveData<Integer> getDexterity() { public LiveData<Integer> getDexterity() {
return mDexterity; return mDexterity;
} }
@@ -459,6 +550,14 @@ public class EditMonsterViewModel extends ChangeTrackedViewModel {
mDexterity.setValue(dexterity); mDexterity.setValue(dexterity);
} }
public void incrementDexterity() {
setDexterity(mDexterity.getValue() + 1);
}
public void decrementDexterity() {
setDexterity(mDexterity.getValue() - 1);
}
public LiveData<Integer> getConstitution() { public LiveData<Integer> getConstitution() {
return mConstitution; return mConstitution;
} }
@@ -467,6 +566,14 @@ public class EditMonsterViewModel extends ChangeTrackedViewModel {
mConstitution.setValue(constitution); mConstitution.setValue(constitution);
} }
public void incrementConstitution() {
setConstitution(mConstitution.getValue() + 1);
}
public void decrementConstitution() {
setConstitution(mConstitution.getValue() - 1);
}
public LiveData<Integer> getIntelligence() { public LiveData<Integer> getIntelligence() {
return mIntelligence; return mIntelligence;
} }
@@ -475,6 +582,14 @@ public class EditMonsterViewModel extends ChangeTrackedViewModel {
mIntelligence.setValue(intelligence); mIntelligence.setValue(intelligence);
} }
public void incrementIntelligence() {
setIntelligence(mIntelligence.getValue() + 1);
}
public void decrementIntelligence() {
setIntelligence(mIntelligence.getValue() - 1);
}
public LiveData<Integer> getWisdom() { public LiveData<Integer> getWisdom() {
return mWisdom; return mWisdom;
} }
@@ -483,6 +598,14 @@ public class EditMonsterViewModel extends ChangeTrackedViewModel {
mWisdom.setValue(wisdom); mWisdom.setValue(wisdom);
} }
public void incrementWisdom() {
setWisdom(mWisdom.getValue() + 1);
}
public void decrementWisdom() {
setWisdom(mWisdom.getValue() - 1);
}
public LiveData<Integer> getCharisma() { public LiveData<Integer> getCharisma() {
return mCharisma; return mCharisma;
} }
@@ -491,6 +614,14 @@ public class EditMonsterViewModel extends ChangeTrackedViewModel {
mCharisma.setValue(charisma); mCharisma.setValue(charisma);
} }
public void incrementCharisma() {
setCharisma(mCharisma.getValue() + 1);
}
public void decrementCharisma() {
setCharisma(mCharisma.getValue() - 1);
}
public LiveData<ProficiencyType> getStrengthProficiency() { public LiveData<ProficiencyType> getStrengthProficiency() {
return mStrengthProficiency; return mStrengthProficiency;
} }
@@ -690,6 +821,22 @@ public class EditMonsterViewModel extends ChangeTrackedViewModel {
return mSenses; return mSenses;
} }
public List<String> getSensesArray() {
return mSenses.getValue();
}
public String addNewSense() {
return Helpers.addItemToList(mSenses, "", String::compareToIgnoreCase);
}
public void removeSense(int position) {
Helpers.removeFromList(mSenses, position);
}
public void replaceSense(String oldSense, String newSense) {
Helpers.replaceItemInList(mSenses, oldSense, newSense, String::compareToIgnoreCase);
}
public LiveData<List<String>> getDamageImmunities() { public LiveData<List<String>> getDamageImmunities() {
return mDamageImmunities; return mDamageImmunities;
} }
@@ -698,10 +845,78 @@ public class EditMonsterViewModel extends ChangeTrackedViewModel {
return mDamageImmunities.getValue(); return mDamageImmunities.getValue();
} }
public String addNewDamageImmunity() {
return Helpers.addStringToList("", mDamageImmunities);
}
public void removeDamageImmunity(int position) {
Helpers.removeFromList(mDamageImmunities, position);
}
public void replaceDamageImmunity(String oldDamageType, String newDamageType) {
Helpers.replaceItemInList(mDamageImmunities, oldDamageType, newDamageType, String::compareToIgnoreCase);
}
public LiveData<List<String>> getDamageResistances() { public LiveData<List<String>> getDamageResistances() {
return mDamageResistances; return mDamageResistances;
} }
public List<String> getDamageResistancesArray() {
return mDamageResistances.getValue();
}
public String addNewDamageResistance() {
return Helpers.addStringToList("", mDamageResistances);
}
public void removeDamageResistance(int position) {
Helpers.removeFromList(mDamageResistances, position);
}
public void replaceDamageResistance(String oldDamageType, String newDamageType) {
Helpers.replaceItemInList(mDamageResistances, oldDamageType, newDamageType, String::compareToIgnoreCase);
}
public LiveData<List<String>> getDamageVulnerabilities() {
return mDamageVulnerabilities;
}
public List<String> getDamageVulnerabilitiesArray() {
return mDamageVulnerabilities.getValue();
}
public String addNewDamageVulnerability() {
return Helpers.addStringToList("", mDamageVulnerabilities);
}
public void removeDamageVulnerability(int position) {
Helpers.removeFromList(mDamageVulnerabilities, position);
}
public void replaceDamageVulnerability(String oldDamageType, String newDamageType) {
Helpers.replaceItemInList(mDamageVulnerabilities, oldDamageType, newDamageType, String::compareToIgnoreCase);
}
public LiveData<List<String>> getConditionImmunities() {
return mConditionImmunities;
}
public List<String> getConditionImmunitiesArray() {
return mConditionImmunities.getValue();
}
public String addNewConditionImmunity() {
return Helpers.addStringToList("", mConditionImmunities);
}
public void removeConditionImmunity(int position) {
Helpers.removeFromList(mConditionImmunities, position);
}
public void replaceConditionImmunity(String oldDamageType, String newDamageType) {
Helpers.replaceItemInList(mConditionImmunities, oldDamageType, newDamageType, String::compareToIgnoreCase);
}
public LiveData<List<Language>> getLanguages() { public LiveData<List<Language>> getLanguages() {
return mLanguages; return mLanguages;
} }
@@ -787,7 +1002,7 @@ public class EditMonsterViewModel extends ChangeTrackedViewModel {
return monster; return monster;
} }
public LiveData<List<Trait>> getTraits(@NonNull TraitType type) { public LiveData<List<Trait>> getTraits(TraitType type) {
switch (type) { switch (type) {
case ABILITY: case ABILITY:
return mAbilities; return mAbilities;
@@ -807,7 +1022,7 @@ public class EditMonsterViewModel extends ChangeTrackedViewModel {
} }
} }
public void removeTrait(@NonNull TraitType type, int position) { public void removeTrait(TraitType type, int position) {
switch (type) { switch (type) {
case ABILITY: case ABILITY:
Helpers.removeFromList(mAbilities, position); Helpers.removeFromList(mAbilities, position);
@@ -833,7 +1048,7 @@ public class EditMonsterViewModel extends ChangeTrackedViewModel {
} }
} }
public void replaceTrait(@NonNull TraitType type, Trait oldTrait, Trait newTrait) { public void replaceTrait(TraitType type, Trait oldTrait, Trait newTrait) {
switch (type) { switch (type) {
case ABILITY: case ABILITY:
Helpers.replaceItemInList(mAbilities, oldTrait, newTrait); Helpers.replaceItemInList(mAbilities, oldTrait, newTrait);
@@ -858,7 +1073,7 @@ public class EditMonsterViewModel extends ChangeTrackedViewModel {
} }
} }
public Trait addNewTrait(@NonNull TraitType type) { public Trait addNewTrait(TraitType type) {
Trait newAction = new Trait("", ""); Trait newAction = new Trait("", "");
switch (type) { switch (type) {
case ABILITY: case ABILITY:
@@ -879,7 +1094,7 @@ public class EditMonsterViewModel extends ChangeTrackedViewModel {
} }
} }
public LiveData<List<String>> getStrings(@NonNull StringType type) { public LiveData<List<String>> getStrings(StringType type) {
switch (type) { switch (type) {
case CONDITION_IMMUNITY: case CONDITION_IMMUNITY:
return mConditionImmunities; return mConditionImmunities;
@@ -897,7 +1112,7 @@ public class EditMonsterViewModel extends ChangeTrackedViewModel {
} }
} }
public void removeString(@NonNull StringType type, int position) { public void removeString(StringType type, int position) {
switch (type) { switch (type) {
case CONDITION_IMMUNITY: case CONDITION_IMMUNITY:
Helpers.removeFromList(mConditionImmunities, position); Helpers.removeFromList(mConditionImmunities, position);
@@ -920,7 +1135,7 @@ public class EditMonsterViewModel extends ChangeTrackedViewModel {
} }
} }
public String addNewString(@NonNull StringType type) { public String addNewString(StringType type) {
String newString = ""; String newString = "";
switch (type) { switch (type) {
case CONDITION_IMMUNITY: case CONDITION_IMMUNITY:
@@ -939,7 +1154,7 @@ public class EditMonsterViewModel extends ChangeTrackedViewModel {
} }
} }
public void replaceString(@NonNull StringType type, String oldValue, String newValue) { public void replaceString(StringType type, String oldValue, String newValue) {
switch (type) { switch (type) {
case CONDITION_IMMUNITY: case CONDITION_IMMUNITY:
Helpers.replaceItemInList(mConditionImmunities, oldValue, newValue); Helpers.replaceItemInList(mConditionImmunities, oldValue, newValue);
@@ -961,7 +1176,7 @@ public class EditMonsterViewModel extends ChangeTrackedViewModel {
} }
} }
public boolean moveTrait(@NonNull TraitType type, int from, int to) { public boolean moveTrait(TraitType type, int from, int to) {
switch (type) { switch (type) {
case ABILITY: case ABILITY:
return Helpers.moveItemInList(mAbilities, from, to); return Helpers.moveItemInList(mAbilities, from, to);
@@ -989,7 +1204,7 @@ public class EditMonsterViewModel extends ChangeTrackedViewModel {
return addItemToList(listData, newItem, null); return addItemToList(listData, newItem, null);
} }
static <T> T addItemToList(@NonNull MutableLiveData<List<T>> listData, T newItem, Comparator<? super T> comparator) { static <T> T addItemToList(MutableLiveData<List<T>> listData, T newItem, Comparator<? super T> comparator) {
ArrayList<T> newList = new ArrayList<>(listData.getValue()); ArrayList<T> newList = new ArrayList<>(listData.getValue());
newList.add(newItem); newList.add(newItem);
if (comparator != null) { if (comparator != null) {
@@ -999,14 +1214,14 @@ public class EditMonsterViewModel extends ChangeTrackedViewModel {
return newItem; return newItem;
} }
static <T> void removeFromList(@NonNull MutableLiveData<List<T>> listData, int position) { static <T> void removeFromList(MutableLiveData<List<T>> listData, int position) {
List<T> oldList = listData.getValue(); List<T> oldList = listData.getValue();
ArrayList<T> newList = new ArrayList<>(oldList); ArrayList<T> newList = new ArrayList<>(oldList);
newList.remove(position); newList.remove(position);
listData.setValue(newList); listData.setValue(newList);
} }
static <T> void replaceItemInList(@NonNull MutableLiveData<List<T>> listData, int position, T newItem, Comparator<? super T> comparator) { static <T> void replaceItemInList(MutableLiveData<List<T>> listData, int position, T newItem, Comparator<? super T> comparator) {
List<T> oldList = listData.getValue(); List<T> oldList = listData.getValue();
if (oldList == null) { if (oldList == null) {
oldList = new ArrayList<>(); oldList = new ArrayList<>();
@@ -1036,7 +1251,7 @@ public class EditMonsterViewModel extends ChangeTrackedViewModel {
replaceItemInList(listData, position, newItem, null); replaceItemInList(listData, position, newItem, null);
} }
static <T> void replaceItemInList(@NonNull MutableLiveData<List<T>> listData, T oldItem, T newItem, Comparator<? super T> comparator) { static <T> void replaceItemInList(MutableLiveData<List<T>> listData, T oldItem, T newItem, Comparator<? super T> comparator) {
List<T> oldList = listData.getValue(); List<T> oldList = listData.getValue();
if (oldList == null) { if (oldList == null) {
oldList = new ArrayList<>(); oldList = new ArrayList<>();
@@ -1071,7 +1286,7 @@ public class EditMonsterViewModel extends ChangeTrackedViewModel {
return value; return value;
} }
static <T> boolean moveItemInList(@NonNull ChangeTrackedLiveData<List<T>> listData, int from, int to) { static <T> boolean moveItemInList(ChangeTrackedLiveData<List<T>> listData, int from, int to) {
List<T> oldList = listData.getValue(); List<T> oldList = listData.getValue();
if (oldList == null) { if (oldList == null) {
oldList = new ArrayList<>(); oldList = new ArrayList<>();

View File

@@ -5,7 +5,7 @@ import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import androidx.annotation.NonNull; import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider; import androidx.lifecycle.ViewModelProvider;
import androidx.navigation.NavBackStackEntry; import androidx.navigation.NavBackStackEntry;
import androidx.navigation.NavController; import androidx.navigation.NavController;
@@ -16,18 +16,19 @@ 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.ui.shared.MCFragment;
public class EditSavingThrowsFragment extends MCFragment { public class EditSavingThrowsFragment extends Fragment {
private EditMonsterViewModel mViewModel; private EditMonsterViewModel mViewModel;
private ViewHolder mViewHolder; private ViewHolder mViewHolder;
@Override @Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) { Bundle savedInstanceState) {
NavController navController = Navigation.findNavController(requireActivity(), R.id.nav_host_fragment); NavController navController = Navigation.findNavController(requireActivity(), R.id.nav_host_fragment);
NavBackStackEntry backStackEntry = navController.getBackStackEntry(R.id.edit_monster_navigation); NavBackStackEntry backStackEntry = navController.getBackStackEntry(R.id.edit_monster_navigation);
mViewModel = new ViewModelProvider(backStackEntry).get(EditMonsterViewModel.class); mViewModel = new ViewModelProvider(backStackEntry).get(EditMonsterViewModel.class);
View root = inflater.inflate(R.layout.fragment_edit_saving_throws, container, false); View root = inflater.inflate(R.layout.fragment_edit_saving_throws, container, false);
mViewHolder = new ViewHolder(root); mViewHolder = new ViewHolder(root);
setTitle(getString(R.string.title_edit_saving_throws));
mViewHolder.strengthProficiency.setValue(mViewModel.getStrengthProficiency().getValue()); mViewHolder.strengthProficiency.setValue(mViewModel.getStrengthProficiency().getValue());
mViewHolder.strengthProficiency.setOnValueChangedListener(value -> mViewModel.setStrengthProficiency(value)); mViewHolder.strengthProficiency.setOnValueChangedListener(value -> mViewModel.setStrengthProficiency(value));
@@ -76,7 +77,7 @@ public class EditSavingThrowsFragment extends MCFragment {
AdvantagePicker charismaAdvantage; AdvantagePicker charismaAdvantage;
ProficiencyPicker charismaProficiency; ProficiencyPicker charismaProficiency;
ViewHolder(@NonNull View root) { ViewHolder(View root) {
strengthAdvantage = root.findViewById(R.id.strengthAdvantage); strengthAdvantage = root.findViewById(R.id.strengthAdvantage);
strengthProficiency = root.findViewById(R.id.strengthProficiency); strengthProficiency = root.findViewById(R.id.strengthProficiency);
dexterityAdvantage = root.findViewById(R.id.dexterityAdvantage); dexterityAdvantage = root.findViewById(R.id.dexterityAdvantage);

View File

@@ -51,6 +51,7 @@ public class EditSkillFragment extends MCFragment {
mEditMonsterViewModel = new ViewModelProvider(backStackEntry).get(EditMonsterViewModel.class); mEditMonsterViewModel = new ViewModelProvider(backStackEntry).get(EditMonsterViewModel.class);
View root = inflater.inflate(R.layout.fragment_edit_skill, container, false); View root = inflater.inflate(R.layout.fragment_edit_skill, container, false);
mHolder = new ViewHolder(root); mHolder = new ViewHolder(root);
setTitle(getString(R.string.title_edit_skill));
mHolder.abilityScore.setValue(mViewModel.getAbilityScore().getValue()); mHolder.abilityScore.setValue(mViewModel.getAbilityScore().getValue());
mHolder.abilityScore.setOnValueChangedListener(value -> mViewModel.setAbilityScore(value)); mHolder.abilityScore.setOnValueChangedListener(value -> mViewModel.setAbilityScore(value));
@@ -89,7 +90,7 @@ public class EditSkillFragment extends MCFragment {
ProficiencyPicker proficiency; ProficiencyPicker proficiency;
EditText name; EditText name;
ViewHolder(@NonNull View root) { ViewHolder(View root) {
abilityScore = root.findViewById(R.id.abilityScore); abilityScore = root.findViewById(R.id.abilityScore);
advantage = root.findViewById(R.id.advantage); advantage = root.findViewById(R.id.advantage);
proficiency = root.findViewById(R.id.proficiency); proficiency = root.findViewById(R.id.proficiency);

View File

@@ -1,6 +1,5 @@
package com.majinnaibu.monstercards.ui.editmonster; package com.majinnaibu.monstercards.ui.editmonster;
import androidx.annotation.NonNull;
import androidx.lifecycle.LiveData; import androidx.lifecycle.LiveData;
import com.majinnaibu.monstercards.data.enums.AbilityScore; import com.majinnaibu.monstercards.data.enums.AbilityScore;
@@ -22,16 +21,15 @@ public class EditSkillViewModel extends ChangeTrackedViewModel {
mAbilityScore = new ChangeTrackedLiveData<>(AbilityScore.STRENGTH, this::makeDirty); mAbilityScore = new ChangeTrackedLiveData<>(AbilityScore.STRENGTH, this::makeDirty);
mAdvantageType = new ChangeTrackedLiveData<>(AdvantageType.NONE, this::makeDirty); mAdvantageType = new ChangeTrackedLiveData<>(AdvantageType.NONE, this::makeDirty);
mProficiencyType = new ChangeTrackedLiveData<>(ProficiencyType.NONE, this::makeDirty); mProficiencyType = new ChangeTrackedLiveData<>(ProficiencyType.NONE, this::makeDirty);
mName = new ChangeTrackedLiveData<>("New Skill", this::makeDirty); mName = new ChangeTrackedLiveData<>("Unknown Skill", this::makeDirty);
mSkill = new ChangeTrackedLiveData<>(makeSkill(), this::makeDirty); mSkill = new ChangeTrackedLiveData<>(makeSkill(), this::makeDirty);
} }
public void copyFromSkill(@NonNull Skill skill) { public void copyFromSkill(Skill skill) {
mAbilityScore.resetValue(skill.abilityScore); mAbilityScore.resetValue(skill.abilityScore);
mAdvantageType.resetValue(skill.advantageType); mAdvantageType.resetValue(skill.advantageType);
mProficiencyType.resetValue(skill.proficiencyType); mProficiencyType.resetValue(skill.proficiencyType);
mName.resetValue(skill.name); mName.resetValue(skill.name);
makeClean();
} }
public LiveData<Skill> getSkill() { public LiveData<Skill> getSkill() {
@@ -74,7 +72,6 @@ public class EditSkillViewModel extends ChangeTrackedViewModel {
mSkill.setValue(makeSkill()); mSkill.setValue(makeSkill());
} }
@NonNull
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());
} }

View File

@@ -31,19 +31,22 @@ public class EditSkillsFragment extends MCFragment {
private EditMonsterViewModel mViewModel; private EditMonsterViewModel mViewModel;
private ViewHolder mHolder; private ViewHolder mHolder;
private void navigateToEditSkill(@NonNull Skill skill) { private void navigateToEditSkill(Skill skill) {
NavDirections action = EditSkillsFragmentDirections.actionEditSkillsFragmentToEditSkillFragment(skill.name, skill.abilityScore, skill.proficiencyType, skill.advantageType); NavDirections action = EditSkillsFragmentDirections.actionEditSkillsFragmentToEditSkillFragment(skill.name, skill.abilityScore, skill.proficiencyType, skill.advantageType);
Navigation.findNavController(requireView()).navigate(action); View view = getView();
assert view != null;
Navigation.findNavController(view).navigate(action);
} }
@Override @Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) { Bundle savedInstanceState) {
NavController navController = Navigation.findNavController(requireActivity(), R.id.nav_host_fragment); NavController navController = Navigation.findNavController(requireActivity(), R.id.nav_host_fragment);
NavBackStackEntry backStackEntry = navController.getBackStackEntry(R.id.edit_monster_navigation); NavBackStackEntry backStackEntry = navController.getBackStackEntry(R.id.edit_monster_navigation);
mViewModel = new ViewModelProvider(backStackEntry).get(EditMonsterViewModel.class); mViewModel = new ViewModelProvider(backStackEntry).get(EditMonsterViewModel.class);
View root = inflater.inflate(R.layout.fragment_edit_skills_list, container, false); View root = inflater.inflate(R.layout.fragment_edit_skills_list, container, false);
mHolder = new ViewHolder(root); mHolder = new ViewHolder(root);
setTitle(getString(R.string.title_edit_skills));
setupRecyclerView(mHolder.list); setupRecyclerView(mHolder.list);
setupAddSkillButton(mHolder.addSkill); setupAddSkillButton(mHolder.addSkill);
@@ -84,7 +87,7 @@ public class EditSkillsFragment extends MCFragment {
RecyclerView list; RecyclerView list;
FloatingActionButton addSkill; FloatingActionButton addSkill;
ViewHolder(@NonNull View root) { ViewHolder(View root) {
this.list = root.findViewById(R.id.list); this.list = root.findViewById(R.id.list);
this.addSkill = root.findViewById(R.id.add_skill); this.addSkill = root.findViewById(R.id.add_skill);
} }

View File

@@ -4,7 +4,6 @@ import android.view.LayoutInflater;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.TextView; import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import com.majinnaibu.monstercards.databinding.FragmentEditSkillsListItemBinding; import com.majinnaibu.monstercards.databinding.FragmentEditSkillsListItemBinding;
@@ -14,31 +13,25 @@ import java.util.List;
/** /**
* {@link RecyclerView.Adapter} that can display a {@link Skill}. * {@link RecyclerView.Adapter} that can display a {@link Skill}.
* TODO: Replace the implementation with code for your data type.
*/ */
public class EditSkillsRecyclerViewAdapter extends RecyclerView.Adapter<EditSkillsRecyclerViewAdapter.ViewHolder> { public class EditSkillsRecyclerViewAdapter extends RecyclerView.Adapter<EditSkillsRecyclerViewAdapter.ViewHolder> {
private final List<Skill> mValues;
private final ItemCallback mOnClick;
public EditSkillsRecyclerViewAdapter(List<Skill> items, ItemCallback onClick) { private final List<Skill> mValues;
public EditSkillsRecyclerViewAdapter(List<Skill> items) {
mValues = items; mValues = items;
mOnClick = onClick;
} }
@NonNull
@Override @Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new ViewHolder(FragmentEditSkillsListItemBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false)); return new ViewHolder(FragmentEditSkillsListItemBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false));
} }
@Override @Override
public void onBindViewHolder(@NonNull final ViewHolder holder, int position) { public void onBindViewHolder(final ViewHolder holder, int position) {
holder.mItem = mValues.get(position); holder.mItem = mValues.get(position);
holder.mContentView.setText(mValues.get(position).name); holder.mContentView.setText(mValues.get(position).name);
holder.itemView.setOnClickListener(v -> {
if (mOnClick != null) {
mOnClick.onItemCallback(holder.mItem);
}
});
} }
@Override @Override
@@ -46,20 +39,15 @@ public class EditSkillsRecyclerViewAdapter extends RecyclerView.Adapter<EditSkil
return mValues.size(); return mValues.size();
} }
public interface ItemCallback { public class ViewHolder extends RecyclerView.ViewHolder {
void onItemCallback(Skill skill);
}
public static class ViewHolder extends RecyclerView.ViewHolder {
public final TextView mContentView; public final TextView mContentView;
public Skill mItem; public Skill mItem;
public ViewHolder(@NonNull FragmentEditSkillsListItemBinding binding) { public ViewHolder(FragmentEditSkillsListItemBinding binding) {
super(binding.getRoot()); super(binding.getRoot());
mContentView = binding.content; mContentView = binding.content;
} }
@NonNull
@Override @Override
public String toString() { public String toString() {
return super.toString() + " '" + mContentView.getText() + "'"; return super.toString() + " '" + mContentView.getText() + "'";

View File

@@ -6,8 +6,8 @@ import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.EditText; import android.widget.EditText;
import androidx.annotation.NonNull;
import androidx.appcompat.widget.SwitchCompat; import androidx.appcompat.widget.SwitchCompat;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider; import androidx.lifecycle.ViewModelProvider;
import androidx.navigation.NavBackStackEntry; import androidx.navigation.NavBackStackEntry;
import androidx.navigation.NavController; import androidx.navigation.NavController;
@@ -18,18 +18,19 @@ import com.majinnaibu.monstercards.ui.components.Stepper;
import com.majinnaibu.monstercards.ui.shared.MCFragment; 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 Fragment {
private EditMonsterViewModel mViewModel; private EditMonsterViewModel mViewModel;
private ViewHolder mHolder; private ViewHolder mHolder;
@Override @Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) { Bundle savedInstanceState) {
NavController navController = Navigation.findNavController(requireActivity(), R.id.nav_host_fragment); NavController navController = Navigation.findNavController(requireActivity(), R.id.nav_host_fragment);
NavBackStackEntry backStackEntry = navController.getBackStackEntry(R.id.edit_monster_navigation); NavBackStackEntry backStackEntry = navController.getBackStackEntry(R.id.edit_monster_navigation);
mViewModel = new ViewModelProvider(backStackEntry).get(EditMonsterViewModel.class); mViewModel = new ViewModelProvider(backStackEntry).get(EditMonsterViewModel.class);
View root = inflater.inflate(R.layout.fragment_edit_speed, container, false); View root = inflater.inflate(R.layout.fragment_edit_speed, container, false);
mHolder = new ViewHolder(root); mHolder = new ViewHolder(root);
setTitle(getString(R.string.title_edit_speed));
mHolder.baseSpeed.setOnValueChangeListener((newValue, oldValue) -> mViewModel.setWalkSpeed(newValue)); mHolder.baseSpeed.setOnValueChangeListener((newValue, oldValue) -> mViewModel.setWalkSpeed(newValue));
mHolder.baseSpeed.setOnFormatValueCallback(value -> String.format(getString(R.string.format_distance_in_feet), value)); mHolder.baseSpeed.setOnFormatValueCallback(value -> String.format(getString(R.string.format_distance_in_feet), value));
@@ -75,7 +76,7 @@ public class EditSpeedFragment extends MCFragment {
final SwitchCompat hasCustomSpeed; final SwitchCompat hasCustomSpeed;
final EditText customSpeed; final EditText customSpeed;
ViewHolder(@NonNull View root) { ViewHolder(View root) {
baseSpeed = root.findViewById(R.id.baseSpeed); baseSpeed = root.findViewById(R.id.baseSpeed);
burrowSpeed = root.findViewById(R.id.burrowSpeed); burrowSpeed = root.findViewById(R.id.burrowSpeed);
climbSpeed = root.findViewById(R.id.climbSpeed); climbSpeed = root.findViewById(R.id.climbSpeed);

View File

@@ -28,7 +28,7 @@ public class EditStringFragment extends MCFragment {
private StringType mStringType; private StringType mStringType;
@Override @Override
public void onCreate(@Nullable Bundle savedInstanceState) { public void onCreate(@Nullable @org.jetbrains.annotations.Nullable Bundle savedInstanceState) {
mViewModel = new ViewModelProvider(this).get(EditStringViewModel.class); mViewModel = new ViewModelProvider(this).get(EditStringViewModel.class);
if (getArguments() != null) { if (getArguments() != null) {
EditStringFragmentArgs args = EditStringFragmentArgs.fromBundle(getArguments()); EditStringFragmentArgs args = EditStringFragmentArgs.fromBundle(getArguments());
@@ -43,6 +43,7 @@ public class EditStringFragment extends MCFragment {
} }
@Nullable @Nullable
@org.jetbrains.annotations.Nullable
@Override @Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
NavController navController = Navigation.findNavController(requireActivity(), R.id.nav_host_fragment); NavController navController = Navigation.findNavController(requireActivity(), R.id.nav_host_fragment);
@@ -68,21 +69,20 @@ public class EditStringFragment extends MCFragment {
return root; return root;
} }
@NonNull private String getTitleForStringType(StringType type) {
private String getTitleForStringType(@NonNull StringType type) {
switch (type) { switch (type) {
case CONDITION_IMMUNITY: case CONDITION_IMMUNITY:
return getString(R.string.title_editConditionImmunity); return getString(R.string.title_edit_condition_immunity);
case DAMAGE_IMMUNITY: case DAMAGE_IMMUNITY:
return getString(R.string.title_editDamageImmunity); return getString(R.string.title_edit_damage_immunity);
case DAMAGE_RESISTANCE: case DAMAGE_RESISTANCE:
return getString(R.string.title_editDamageResistance); return getString(R.string.title_edit_damage_resistance);
case DAMAGE_VULNERABILITY: case DAMAGE_VULNERABILITY:
return getString(R.string.title_editDamageVulnerability); return getString(R.string.title_edit_damage_vulnerability);
case SENSE: case SENSE:
return getString(R.string.title_editSense); return getString(R.string.title_edit_sense);
default: default:
return getString(R.string.title_editString); return "";
} }
} }
@@ -95,7 +95,7 @@ public class EditStringFragment extends MCFragment {
private static class ViewHolder { private static class ViewHolder {
EditText description; EditText description;
ViewHolder(@NonNull View root) { ViewHolder(View root) {
description = root.findViewById(R.id.description); description = root.findViewById(R.id.description);
} }
} }

View File

@@ -8,7 +8,11 @@ import android.view.ViewGroup;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
<<<<<<<< HEAD:Android/app/src/main/java/com/majinnaibu/monstercards/ui/editmonster/EditConditionImmunitiesFragment.java
import androidx.fragment.app.Fragment;
========
import androidx.lifecycle.LiveData; import androidx.lifecycle.LiveData;
>>>>>>>> f924bdd (Replaces condition immunities, damage immunities, damage resistances, damage vulnerabilities, and senses with a unified list of strings editor.):Android/app/src/main/java/com/majinnaibu/monstercards/ui/editmonster/EditStringsFragment.java
import androidx.lifecycle.ViewModelProvider; import androidx.lifecycle.ViewModelProvider;
import androidx.navigation.NavBackStackEntry; import androidx.navigation.NavBackStackEntry;
import androidx.navigation.NavController; import androidx.navigation.NavController;
@@ -21,20 +25,39 @@ 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;
<<<<<<<< HEAD:Android/app/src/main/java/com/majinnaibu/monstercards/ui/editmonster/EditConditionImmunitiesFragment.java
========
import com.majinnaibu.monstercards.data.enums.StringType; import com.majinnaibu.monstercards.data.enums.StringType;
import com.majinnaibu.monstercards.ui.shared.MCFragment; import com.majinnaibu.monstercards.ui.shared.MCFragment;
>>>>>>>> f924bdd (Replaces condition immunities, damage immunities, damage resistances, damage vulnerabilities, and senses with a unified list of strings editor.):Android/app/src/main/java/com/majinnaibu/monstercards/ui/editmonster/EditStringsFragment.java
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;
import org.jetbrains.annotations.NotNull;
<<<<<<<< HEAD:Android/app/src/main/java/com/majinnaibu/monstercards/ui/editmonster/EditConditionImmunitiesFragment.java
/**
* A fragment representing a list of Items.
*/
public class EditConditionImmunitiesFragment extends Fragment {
========
import java.util.List; import java.util.List;
public class EditStringsFragment extends MCFragment { public class EditStringsFragment extends MCFragment {
>>>>>>>> f924bdd (Replaces condition immunities, damage immunities, damage resistances, damage vulnerabilities, and senses with a unified list of strings editor.):Android/app/src/main/java/com/majinnaibu/monstercards/ui/editmonster/EditStringsFragment.java
private EditMonsterViewModel mViewModel; private EditMonsterViewModel mViewModel;
private ViewHolder mHolder; private ViewHolder mHolder;
private StringType mStringType; private StringType mStringType;
<<<<<<<< HEAD:Android/app/src/main/java/com/majinnaibu/monstercards/ui/editmonster/EditConditionImmunitiesFragment.java
private void navigateToEditConditionImmunity(String condition) {
NavDirections action = EditConditionImmunitiesFragmentDirections.actionEditConditionImmunitiesFragmentToEditConditionImmunity(condition);
View view = getView();
assert view != null;
Navigation.findNavController(view).navigate(action);
========
@Override @Override
public void onCreate(@Nullable Bundle savedInstanceState) { public void onCreate(@Nullable @org.jetbrains.annotations.Nullable Bundle savedInstanceState) {
Bundle arguments = getArguments(); Bundle arguments = getArguments();
if (arguments != null) { if (arguments != null) {
EditStringsFragmentArgs args = EditStringsFragmentArgs.fromBundle(arguments); EditStringsFragmentArgs args = EditStringsFragmentArgs.fromBundle(arguments);
@@ -43,11 +66,13 @@ public class EditStringsFragment extends MCFragment {
Logger.logWTF("EditStringsFragment needs arguments"); Logger.logWTF("EditStringsFragment needs arguments");
} }
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
>>>>>>>> f924bdd (Replaces condition immunities, damage immunities, damage resistances, damage vulnerabilities, and senses with a unified list of strings editor.):Android/app/src/main/java/com/majinnaibu/monstercards/ui/editmonster/EditStringsFragment.java
} }
@Nullable @Nullable
@org.jetbrains.annotations.Nullable
@Override @Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { public View onCreateView(@NonNull @NotNull LayoutInflater inflater, @Nullable @org.jetbrains.annotations.Nullable ViewGroup container, @Nullable @org.jetbrains.annotations.Nullable Bundle savedInstanceState) {
NavController navController = Navigation.findNavController(requireActivity(), R.id.nav_host_fragment); NavController navController = Navigation.findNavController(requireActivity(), R.id.nav_host_fragment);
NavBackStackEntry backStackEntry = navController.getBackStackEntry(R.id.edit_monster_navigation); NavBackStackEntry backStackEntry = navController.getBackStackEntry(R.id.edit_monster_navigation);
mViewModel = new ViewModelProvider(backStackEntry).get(EditMonsterViewModel.class); mViewModel = new ViewModelProvider(backStackEntry).get(EditMonsterViewModel.class);
@@ -59,21 +84,20 @@ public class EditStringsFragment extends MCFragment {
return root; return root;
} }
@NonNull
private String getTitleForStringType(StringType type) { private String getTitleForStringType(StringType type) {
switch (type) { switch (type) {
case CONDITION_IMMUNITY: case CONDITION_IMMUNITY:
return getString(R.string.title_editConditionImmunities); return getString(R.string.title_edit_condition_immunities);
case DAMAGE_IMMUNITY: case DAMAGE_IMMUNITY:
return getString(R.string.title_editDamageImmunities); return getString(R.string.title_edit_damage_immunities);
case DAMAGE_RESISTANCE: case DAMAGE_RESISTANCE:
return getString(R.string.title_editDamageResistances); return getString(R.string.title_edit_damage_resistances);
case DAMAGE_VULNERABILITY: case DAMAGE_VULNERABILITY:
return getString(R.string.title_editDamageVulnerabilities); return getString(R.string.title_edit_damage_vulnerabilities);
case SENSE: case SENSE:
return getString(R.string.title_editSenses); return getString(R.string.title_edit_senses);
default: default:
return getString(R.string.title_editStrings); return "";
} }
} }
@@ -121,7 +145,7 @@ public class EditStringsFragment extends MCFragment {
RecyclerView list; RecyclerView list;
FloatingActionButton addItem; FloatingActionButton addItem;
ViewHolder(@NonNull View root) { ViewHolder(View root) {
list = root.findViewById(R.id.list); list = root.findViewById(R.id.list);
addItem = root.findViewById(R.id.add_item); addItem = root.findViewById(R.id.add_item);
} }

View File

@@ -4,11 +4,12 @@ import android.view.LayoutInflater;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.TextView; import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import com.majinnaibu.monstercards.databinding.FragmentEditStringsListItemBinding; import com.majinnaibu.monstercards.databinding.FragmentEditStringsListItemBinding;
import org.jetbrains.annotations.NotNull;
import java.util.List; import java.util.List;
public class EditStringsRecyclerViewAdapter extends RecyclerView.Adapter<EditStringsRecyclerViewAdapter.ViewHolder> { public class EditStringsRecyclerViewAdapter extends RecyclerView.Adapter<EditStringsRecyclerViewAdapter.ViewHolder> {
@@ -20,14 +21,14 @@ public class EditStringsRecyclerViewAdapter extends RecyclerView.Adapter<EditStr
mOnClick = onClick; mOnClick = onClick;
} }
@NonNull @NotNull
@Override @Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { public ViewHolder onCreateViewHolder(@NotNull ViewGroup parent, int viewType) {
return new ViewHolder(FragmentEditStringsListItemBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false)); return new ViewHolder(FragmentEditStringsListItemBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false));
} }
@Override @Override
public void onBindViewHolder(@NonNull final ViewHolder holder, int position) { public void onBindViewHolder(final ViewHolder holder, int position) {
holder.mItem = mValues.get(position); holder.mItem = mValues.get(position);
holder.mContentView.setText(mValues.get(position)); holder.mContentView.setText(mValues.get(position));
holder.itemView.setOnClickListener(v -> { holder.itemView.setOnClickListener(v -> {
@@ -50,12 +51,12 @@ public class EditStringsRecyclerViewAdapter extends RecyclerView.Adapter<EditStr
public final TextView mContentView; public final TextView mContentView;
public String mItem; public String mItem;
public ViewHolder(@NonNull FragmentEditStringsListItemBinding binding) { public ViewHolder(FragmentEditStringsListItemBinding binding) {
super(binding.getRoot()); super(binding.getRoot());
mContentView = binding.content; mContentView = binding.content;
} }
@NonNull @NotNull
@Override @Override
public String toString() { public String toString() {
return super.toString() + " '" + mContentView.getText() + "'"; return super.toString() + " '" + mContentView.getText() + "'";

View File

@@ -29,7 +29,7 @@ public class EditTraitFragment extends MCFragment {
private TraitType mTraitType; private TraitType mTraitType;
@Override @Override
public void onCreate(@Nullable Bundle savedInstanceState) { public void onCreate(@Nullable @org.jetbrains.annotations.Nullable Bundle savedInstanceState) {
mViewModel = new ViewModelProvider(this).get(EditTraitViewModel.class); mViewModel = new ViewModelProvider(this).get(EditTraitViewModel.class);
if (getArguments() != null) { if (getArguments() != null) {
EditTraitFragmentArgs args = EditTraitFragmentArgs.fromBundle(getArguments()); EditTraitFragmentArgs args = EditTraitFragmentArgs.fromBundle(getArguments());
@@ -44,7 +44,7 @@ public class EditTraitFragment extends MCFragment {
} }
@Nullable @Nullable
@org.jetbrains.annotations.Nullable
@Override @Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
NavController navController = Navigation.findNavController(requireActivity(), R.id.nav_host_fragment); NavController navController = Navigation.findNavController(requireActivity(), R.id.nav_host_fragment);
@@ -82,19 +82,19 @@ public class EditTraitFragment extends MCFragment {
private String getTitleForTraitType(TraitType type) { private String getTitleForTraitType(TraitType type) {
switch (type) { switch (type) {
case ABILITY: case ABILITY:
return getString(R.string.title_editAbility); return getString(R.string.title_edit_ability);
case ACTION: case ACTION:
return getString(R.string.title_editAction); return getString(R.string.title_edit_action);
case LAIR_ACTION: case LAIR_ACTION:
return getString(R.string.title_editLairAction); return getString(R.string.title_edit_lair_action);
case LEGENDARY_ACTION: case LEGENDARY_ACTION:
return getString(R.string.title_editLegendaryAction); return getString(R.string.title_edit_legendary_action);
case REACTIONS: case REACTIONS:
return getString(R.string.title_editReaction); return getString(R.string.title_edit_reaction);
case REGIONAL_ACTION: case REGIONAL_ACTION:
return getString(R.string.title_editRegionalAction); return getString(R.string.title_edit_regional_action);
default: default:
return getString(R.string.title_editTrait); return "";
} }
} }
@@ -102,7 +102,7 @@ public class EditTraitFragment extends MCFragment {
EditText description; EditText description;
EditText name; EditText name;
ViewHolder(@NonNull View root) { ViewHolder(View root) {
description = root.findViewById(R.id.description); description = root.findViewById(R.id.description);
name = root.findViewById(R.id.name); name = root.findViewById(R.id.name);
} }

View File

@@ -1,6 +1,5 @@
package com.majinnaibu.monstercards.ui.editmonster; package com.majinnaibu.monstercards.ui.editmonster;
import androidx.annotation.NonNull;
import androidx.lifecycle.LiveData; import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData; import androidx.lifecycle.MutableLiveData;
@@ -50,13 +49,12 @@ public class EditTraitViewModel extends ChangeTrackedViewModel {
return mAbility.getValue(); return mAbility.getValue();
} }
public void copyFromTrait(@NonNull Trait trait) { public void copyFromTrait(Trait trait) {
makeClean(); makeClean();
mName.resetValue(trait.name); mName.resetValue(trait.name);
mDescription.resetValue(trait.description); mDescription.resetValue(trait.description);
} }
@NonNull
private Trait makeAbility() { private Trait makeAbility() {
return new Trait(mName.getValue(), mDescription.getValue()); return new Trait(mName.getValue(), mDescription.getValue());
} }

View File

@@ -35,7 +35,6 @@ public class EditTraitsFragment extends MCFragment {
private TraitType mTraitType; private TraitType mTraitType;
private EditTraitsRecyclerViewAdapter mAdapter; private EditTraitsRecyclerViewAdapter mAdapter;
@Override @Override
public void onCreate(@Nullable Bundle savedInstanceState) { public void onCreate(@Nullable Bundle savedInstanceState) {
if (getArguments() != null) { if (getArguments() != null) {
@@ -47,9 +46,8 @@ public class EditTraitsFragment extends MCFragment {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
} }
@Nullable
@Override @Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
NavController navController = Navigation.findNavController(requireActivity(), R.id.nav_host_fragment); NavController navController = Navigation.findNavController(requireActivity(), R.id.nav_host_fragment);
NavBackStackEntry backStackEntry = navController.getBackStackEntry(R.id.edit_monster_navigation); NavBackStackEntry backStackEntry = navController.getBackStackEntry(R.id.edit_monster_navigation);
mViewModel = new ViewModelProvider(backStackEntry).get(EditMonsterViewModel.class); mViewModel = new ViewModelProvider(backStackEntry).get(EditMonsterViewModel.class);

View File

@@ -12,16 +12,18 @@ import androidx.recyclerview.widget.RecyclerView;
import com.majinnaibu.monstercards.databinding.FragmentEditTraitsListItemBinding; import com.majinnaibu.monstercards.databinding.FragmentEditTraitsListItemBinding;
import com.majinnaibu.monstercards.models.Trait; import com.majinnaibu.monstercards.models.Trait;
import org.jetbrains.annotations.NotNull;
public class EditTraitsRecyclerViewAdapter extends ListAdapter<Trait, EditTraitsRecyclerViewAdapter.ViewHolder> { public class EditTraitsRecyclerViewAdapter extends ListAdapter<Trait, EditTraitsRecyclerViewAdapter.ViewHolder> {
private static final DiffUtil.ItemCallback<Trait> DIFF_CALLBACK = new DiffUtil.ItemCallback<Trait>() { private static final DiffUtil.ItemCallback<Trait> DIFF_CALLBACK = new DiffUtil.ItemCallback<Trait>() {
@Override @Override
public boolean areItemsTheSame(@NonNull Trait oldItem, @NonNull Trait newItem) { public boolean areItemsTheSame(@NonNull @NotNull Trait oldItem, @NonNull @NotNull Trait newItem) {
return oldItem.equals(newItem); return oldItem.equals(newItem);
} }
@Override @Override
public boolean areContentsTheSame(@NonNull Trait oldItem, @NonNull Trait newItem) { public boolean areContentsTheSame(@NonNull @NotNull Trait oldItem, @NonNull @NotNull Trait newItem) {
return oldItem.equals(newItem); return oldItem.equals(newItem);
} }
}; };
@@ -32,14 +34,14 @@ public class EditTraitsRecyclerViewAdapter extends ListAdapter<Trait, EditTraits
mOnClick = onClick; mOnClick = onClick;
} }
@NonNull @NotNull
@Override @Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { public ViewHolder onCreateViewHolder(@NotNull ViewGroup parent, int viewType) {
return new ViewHolder(FragmentEditTraitsListItemBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false)); return new ViewHolder(FragmentEditTraitsListItemBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false));
} }
@Override @Override
public void onBindViewHolder(@NonNull final ViewHolder holder, int position) { public void onBindViewHolder(final ViewHolder holder, int position) {
holder.mItem = getItem(position); holder.mItem = getItem(position);
holder.mContentView.setText(holder.mItem.name); holder.mContentView.setText(holder.mItem.name);
holder.itemView.setOnClickListener(v -> { holder.itemView.setOnClickListener(v -> {
@@ -57,12 +59,12 @@ public class EditTraitsRecyclerViewAdapter extends ListAdapter<Trait, EditTraits
public final TextView mContentView; public final TextView mContentView;
public Trait mItem; public Trait mItem;
public ViewHolder(@NonNull FragmentEditTraitsListItemBinding binding) { public ViewHolder(FragmentEditTraitsListItemBinding binding) {
super(binding.getRoot()); super(binding.getRoot());
mContentView = binding.content; mContentView = binding.content;
} }
@NonNull @NotNull
@Override @Override
public String toString() { public String toString() {
return super.toString() + " '" + mContentView.getText() + "'"; return super.toString() + " '" + mContentView.getText() + "'";

View File

@@ -114,8 +114,10 @@ public class LibraryFragment extends MCFragment {
}); });
} }
protected void navigateToMonsterDetail(@NonNull UUID monsterId) { protected void navigateToMonsterDetail(UUID monsterId) {
NavDirections action = LibraryFragmentDirections.actionNavigationLibraryToNavigationMonster(monsterId.toString()); NavDirections action = LibraryFragmentDirections.actionNavigationLibraryToNavigationMonster(monsterId.toString());
Navigation.findNavController(requireView()).navigate(action); View view = getView();
assert view != null;
Navigation.findNavController(view).navigate(action);
} }
} }

View File

@@ -0,0 +1,19 @@
package com.majinnaibu.monstercards.ui.library;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;
public class LibraryViewModel extends ViewModel {
private MutableLiveData<String> mText;
public LibraryViewModel() {
mText = new MutableLiveData<>();
mText.setValue("This is library fragment");
}
public LiveData<String> getText() {
return mText;
}
}

View File

@@ -13,7 +13,6 @@ import android.view.MenuInflater;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import android.widget.TextView; import android.widget.TextView;
@@ -30,15 +29,13 @@ import com.majinnaibu.monstercards.models.Monster;
import com.majinnaibu.monstercards.ui.shared.MCFragment; import com.majinnaibu.monstercards.ui.shared.MCFragment;
import com.majinnaibu.monstercards.utils.Logger; import com.majinnaibu.monstercards.utils.Logger;
import java.util.List;
import java.util.UUID; import java.util.UUID;
import io.reactivex.rxjava3.observers.DisposableSingleObserver; import io.reactivex.rxjava3.observers.DisposableSingleObserver;
public class MonsterDetailFragment extends MCFragment { public class MonsterDetailFragment extends MCFragment {
private ViewHolder mHolder;
private MonsterDetailViewModel mViewModel; private MonsterDetailViewModel monsterDetailViewModel;
public View onCreateView(@NonNull LayoutInflater inflater, public View onCreateView(@NonNull LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) { ViewGroup container, Bundle savedInstanceState) {
@@ -47,13 +44,16 @@ public class MonsterDetailFragment extends MCFragment {
assert arguments != null; assert arguments != null;
UUID monsterId = UUID.fromString(MonsterDetailFragmentArgs.fromBundle(arguments).getMonsterId()); UUID monsterId = UUID.fromString(MonsterDetailFragmentArgs.fromBundle(arguments).getMonsterId());
setHasOptionsMenu(true); setHasOptionsMenu(true);
mViewModel = new ViewModelProvider(this).get(MonsterDetailViewModel.class);
monsterDetailViewModel = new ViewModelProvider(this).get(MonsterDetailViewModel.class);
View root = inflater.inflate(R.layout.fragment_monster, container, false);
repository.getMonster(monsterId).toObservable() repository.getMonster(monsterId).toObservable()
.firstOrError() .firstOrError()
.subscribe(new DisposableSingleObserver<Monster>() { .subscribe(new DisposableSingleObserver<Monster>() {
@Override @Override
public void onSuccess(@io.reactivex.rxjava3.annotations.NonNull Monster monster) { public void onSuccess(@io.reactivex.rxjava3.annotations.NonNull Monster monster) {
mViewModel.setMonster(monster); monsterDetailViewModel.setMonster(monster);
dispose(); dispose();
} }
@@ -63,70 +63,125 @@ public class MonsterDetailFragment extends MCFragment {
dispose(); dispose();
} }
}); });
View root = inflater.inflate(R.layout.fragment_monster, container, false);
mHolder = new ViewHolder(root);
mViewModel.getName().observe(getViewLifecycleOwner(), name -> { final TextView monsterName = root.findViewById(R.id.name);
mHolder.name.setText(name); monsterDetailViewModel.getName().observe(getViewLifecycleOwner(), monsterName::setText);
setTitle(getString(R.string.title_monsterDetails_fmt, name));
final TextView monsterMeta = root.findViewById(R.id.meta);
monsterDetailViewModel.getMeta().observe(getViewLifecycleOwner(), monsterMeta::setText);
final TextView monsterArmorClass = root.findViewById(R.id.armor_class);
monsterDetailViewModel.getArmorClass().observe(getViewLifecycleOwner(), armorText -> monsterArmorClass.setText(Html.fromHtml("<b>Armor Class</b> " + armorText)));
final TextView monsterHitPoints = root.findViewById(R.id.hit_points);
monsterDetailViewModel.getHitPoints().observe(getViewLifecycleOwner(), hitPoints -> monsterHitPoints.setText(Html.fromHtml("<b>Hit Points</b> " + hitPoints)));
final TextView monsterSpeed = root.findViewById(R.id.speed);
monsterDetailViewModel.getSpeed().observe(getViewLifecycleOwner(), speed -> monsterSpeed.setText(Html.fromHtml("<b>Speed</b> " + speed)));
final TextView monsterStrength = root.findViewById(R.id.strength);
monsterDetailViewModel.getStrength().observe(getViewLifecycleOwner(), monsterStrength::setText);
final TextView monsterDexterity = root.findViewById(R.id.dexterity);
monsterDetailViewModel.getDexterity().observe(getViewLifecycleOwner(), monsterDexterity::setText);
final TextView monsterConstitution = root.findViewById(R.id.constitution);
monsterDetailViewModel.getConstitution().observe(getViewLifecycleOwner(), monsterConstitution::setText);
final TextView monsterIntelligence = root.findViewById(R.id.intelligence);
monsterDetailViewModel.getIntelligence().observe(getViewLifecycleOwner(), monsterIntelligence::setText);
final TextView monsterWisdom = root.findViewById(R.id.wisdom);
monsterDetailViewModel.getWisdom().observe(getViewLifecycleOwner(), monsterWisdom::setText);
final TextView monsterCharisma = root.findViewById(R.id.charisma);
monsterDetailViewModel.getCharisma().observe(getViewLifecycleOwner(), monsterCharisma::setText);
final TextView monsterSavingThrows = root.findViewById(R.id.saving_throws);
monsterDetailViewModel.getSavingThrows().observe(getViewLifecycleOwner(), savingThrows -> {
if (StringHelper.isNullOrEmpty(savingThrows)) {
monsterSavingThrows.setVisibility(View.GONE);
} else {
monsterSavingThrows.setVisibility(View.VISIBLE);
}
monsterSavingThrows.setText(Html.fromHtml("<b>Saving Throws</b> " + savingThrows));
}); });
mViewModel.getMeta().observe(getViewLifecycleOwner(), mHolder.meta::setText);
mViewModel.getArmorClass().observe(getViewLifecycleOwner(), armorText -> setupLabeledTextView(mHolder.armorClass, armorText, R.string.label_armor_class));
mViewModel.getHitPoints().observe(getViewLifecycleOwner(), hitPoints -> setupLabeledTextView(mHolder.hitPoints, hitPoints, R.string.label_hit_points));
mViewModel.getSpeed().observe(getViewLifecycleOwner(), speed -> setupLabeledTextView(mHolder.speed, speed, R.string.label_speed));
mViewModel.getStrength().observe(getViewLifecycleOwner(), mHolder.strength::setText);
mViewModel.getDexterity().observe(getViewLifecycleOwner(), mHolder.dexterity::setText);
mViewModel.getConstitution().observe(getViewLifecycleOwner(), mHolder.constitution::setText);
mViewModel.getIntelligence().observe(getViewLifecycleOwner(), mHolder.intelligence::setText);
mViewModel.getWisdom().observe(getViewLifecycleOwner(), mHolder.wisdom::setText);
mViewModel.getCharisma().observe(getViewLifecycleOwner(), mHolder.charisma::setText);
mViewModel.getSavingThrows().observe(getViewLifecycleOwner(), savingThrows -> setupOptionalTextView(mHolder.savingThrows, savingThrows, R.string.label_saving_throws));
mViewModel.getSkills().observe(getViewLifecycleOwner(), skills -> setupOptionalTextView(mHolder.skills, skills, R.string.label_skills));
mViewModel.getDamageVulnerabilities().observe(getViewLifecycleOwner(), damageTypes -> setupOptionalTextView(mHolder.damageVulnerabilities, damageTypes, R.string.label_damage_vulnerabilities));
mViewModel.getDamageResistances().observe(getViewLifecycleOwner(), damageTypes -> setupOptionalTextView(mHolder.damageResistances, damageTypes, R.string.label_damage_resistances));
mViewModel.getDamageImmunities().observe(getViewLifecycleOwner(), damageTypes -> setupOptionalTextView(mHolder.damageImmunities, damageTypes, R.string.label_damage_immunities));
mViewModel.getConditionImmunities().observe(getViewLifecycleOwner(), conditionImmunities -> setupOptionalTextView(mHolder.conditionImmunities, conditionImmunities, R.string.label_condition_immunities));
mViewModel.getSenses().observe(getViewLifecycleOwner(), senses -> setupOptionalTextView(mHolder.senses, senses, R.string.label_senses));
mViewModel.getLanguages().observe(getViewLifecycleOwner(), languages -> setupOptionalTextView(mHolder.languages, languages, R.string.label_languages));
mViewModel.getChallenge().observe(getViewLifecycleOwner(), challengeRating -> setupLabeledTextView(mHolder.challenge, challengeRating, R.string.label_challenge_rating));
mViewModel.getAbilities().observe(getViewLifecycleOwner(), abilities -> setupTraitList(mHolder.abilities, abilities));
mViewModel.getActions().observe(getViewLifecycleOwner(), actions -> setupTraitList(mHolder.actions, actions, mHolder.actions_label, mHolder.actions_divider));
mViewModel.getReactions().observe(getViewLifecycleOwner(), reactions -> setupTraitList(mHolder.reactions, reactions, mHolder.reactions_label, mHolder.reactions_divider));
mViewModel.getRegionalEffects().observe(getViewLifecycleOwner(), regionalEffects -> setupTraitList(mHolder.regionalEffects, regionalEffects, mHolder.regionalEffects_label, mHolder.regionalEffects_divider));
mViewModel.getLairActions().observe(getViewLifecycleOwner(), lairActions -> setupTraitList(mHolder.lairActions, lairActions, mHolder.lairActions_label, mHolder.lairActions_divider));
mViewModel.getLegendaryActions().observe(getViewLifecycleOwner(), legendaryActions -> setupTraitList(mHolder.legendaryActions, legendaryActions, mHolder.legendaryActions_label, mHolder.legendaryActions_divider));
return root; final TextView monsterSkills = root.findViewById(R.id.skills);
} monsterDetailViewModel.getSkills().observe(getViewLifecycleOwner(), skills -> {
if (StringHelper.isNullOrEmpty(skills)) {
private void setupLabeledTextView(@NonNull TextView view, String text, int titleId) { monsterSkills.setVisibility(View.GONE);
String title = getString(titleId);
String fullText = String.format("<b>%s</b> %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 { } else {
root.setVisibility(View.VISIBLE); monsterSkills.setVisibility(View.VISIBLE);
} }
Spanned formatted; monsterSkills.setText(Html.fromHtml("<b>Skills</b> " + skills));
if (StringHelper.isNullOrEmpty(title)) { });
formatted = Html.fromHtml(text);
final TextView monsterDamageVulnerabilities = root.findViewById(R.id.damage_vulnerabilities);
monsterDetailViewModel.getDamageVulnerabilities().observe(getViewLifecycleOwner(), damageType -> {
if (StringHelper.isNullOrEmpty(damageType)) {
monsterDamageVulnerabilities.setVisibility(View.GONE);
} else { } else {
formatted = Html.fromHtml(String.format("<b>%s</b> %s", title, text)); monsterDamageVulnerabilities.setVisibility(View.VISIBLE);
}
root.setText(formatted);
} }
monsterDamageVulnerabilities.setText(Html.fromHtml("<b>Damage Vulnerabilities</b> " + damageType));
});
private void setupTraitList(@NonNull LinearLayout root, @NonNull List<String> traits) { final TextView monsterDamageResistances = root.findViewById(R.id.damage_resistances);
setupTraitList(root, traits, null, null); monsterDetailViewModel.getDamageResistances().observe(getViewLifecycleOwner(), damageType -> {
if (StringHelper.isNullOrEmpty(damageType)) {
monsterDamageResistances.setVisibility(View.GONE);
} else {
monsterDamageResistances.setVisibility(View.VISIBLE);
} }
monsterDamageResistances.setText(Html.fromHtml("<b>Damage Resistances</b> " + damageType));
});
private void setupTraitList(@NonNull LinearLayout root, @NonNull List<String> traits, View label, View divider) { final TextView monsterDamageImmunities = root.findViewById(R.id.damage_immunities);
int visibility = traits.size() > 0 ? View.VISIBLE : View.GONE; monsterDetailViewModel.getDamageImmunities().observe(getViewLifecycleOwner(), damageType -> {
if (StringHelper.isNullOrEmpty(damageType)) {
monsterDamageImmunities.setVisibility(View.GONE);
} else {
monsterDamageImmunities.setVisibility(View.VISIBLE);
}
monsterDamageImmunities.setText(Html.fromHtml("<b>Damage Immunities</b> " + damageType));
});
final TextView monsterConditionImmunities = root.findViewById(R.id.condition_immunities);
monsterDetailViewModel.getConditionImmunities().observe(getViewLifecycleOwner(), conditionImmunities -> {
if (StringHelper.isNullOrEmpty(conditionImmunities)) {
monsterConditionImmunities.setVisibility(View.GONE);
} else {
monsterConditionImmunities.setVisibility(View.VISIBLE);
}
monsterConditionImmunities.setText(Html.fromHtml("<b>Condition Immunities</b> " + conditionImmunities));
});
final TextView monsterSenses = root.findViewById(R.id.senses);
monsterDetailViewModel.getSenses().observe(getViewLifecycleOwner(), senses -> {
if (StringHelper.isNullOrEmpty(senses)) {
monsterSenses.setVisibility(View.GONE);
} else {
monsterSenses.setVisibility(View.VISIBLE);
}
monsterSenses.setText(Html.fromHtml("<b>Senses</b> " + senses));
});
final TextView monsterLanguages = root.findViewById(R.id.languages);
monsterDetailViewModel.getLanguages().observe(getViewLifecycleOwner(), languages -> {
if (StringHelper.isNullOrEmpty(languages)) {
monsterLanguages.setVisibility(View.GONE);
} else {
monsterLanguages.setVisibility(View.VISIBLE);
}
monsterLanguages.setText(Html.fromHtml("<b>Languages</b> " + languages));
});
final TextView monsterChallenge = root.findViewById(R.id.challenge);
monsterDetailViewModel.getChallenge().observe(getViewLifecycleOwner(), challengeRating -> monsterChallenge.setText(Html.fromHtml("<b>Challenge</b> " + challengeRating)));
final LinearLayout monsterAbilities = root.findViewById(R.id.abilities);
monsterDetailViewModel.getAbilities().observe(getViewLifecycleOwner(), abilities -> {
Context context = getContext(); Context context = getContext();
DisplayMetrics displayMetrics = null; DisplayMetrics displayMetrics = null;
if (context != null) { if (context != null) {
@@ -135,24 +190,48 @@ public class MonsterDetailFragment extends MCFragment {
displayMetrics = resources.getDisplayMetrics(); displayMetrics = resources.getDisplayMetrics();
} }
} }
root.removeAllViews(); monsterAbilities.removeAllViews();
for (String action : traits) { if (abilities != null) {
TextView tvAction = new TextView(getContext()); for (String ability : abilities) {
TextView tvAbility = new TextView(context);
// TODO: Handle multiline block quotes specially so they stay multiline. // 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 // 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
Spanned spannedText = Html.fromHtml(CommonMarkHelper.toHtml(ability));
tvAbility.setText(spannedText);
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);
tvAbility.setLayoutParams(layoutParams);
monsterAbilities.addView(tvAbility);
}
}
});
final LinearLayout monsterActions = root.findViewById(R.id.actions);
monsterDetailViewModel.getActions().observe(getViewLifecycleOwner(), actions -> {
Context context = getContext();
DisplayMetrics displayMetrics = null;
if (context != null) {
Resources resources = context.getResources();
if (resources != null) {
displayMetrics = resources.getDisplayMetrics();
}
}
monsterActions.removeAllViews();
if (actions != null) {
for (String action : actions) {
TextView tvAction = new TextView(getContext());
tvAction.setText(Html.fromHtml(CommonMarkHelper.toHtml(action))); tvAction.setText(Html.fromHtml(CommonMarkHelper.toHtml(action)));
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); 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); layoutParams.topMargin = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 8, displayMetrics);
tvAction.setLayoutParams(layoutParams); tvAction.setLayoutParams(layoutParams);
root.addView(tvAction); monsterActions.addView(tvAction);
} }
root.setVisibility(visibility);
if (label != null) {
label.setVisibility(visibility);
}
if (divider != null) {
divider.setVisibility(visibility);
} }
});
// TODO: add lair actions, legendary actions, reactions, and regional actions
return root;
} }
@Override @Override
@@ -164,10 +243,12 @@ 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) {
UUID monsterId = mViewModel.getId().getValue(); UUID monsterId = monsterDetailViewModel.getId().getValue();
if (monsterId != null) { if (monsterId != null) {
NavDirections action = MonsterDetailFragmentDirections.actionNavigationMonsterToEditMonsterFragment(monsterId.toString()); NavDirections action = MonsterDetailFragmentDirections.actionNavigationMonsterToEditMonsterFragment(monsterId.toString());
Navigation.findNavController(requireView()).navigate(action); View view = getView();
assert view != null;
Navigation.findNavController(view).navigate(action);
} else { } else {
Logger.logWTF("monsterId cannot be null."); Logger.logWTF("monsterId cannot be null.");
} }
@@ -175,82 +256,4 @@ public class MonsterDetailFragment extends MCFragment {
} }
return super.onOptionsItemSelected(item); return super.onOptionsItemSelected(item);
} }
private static class ViewHolder {
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(@NonNull View 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);
}
}
} }

View File

@@ -1,6 +1,5 @@
package com.majinnaibu.monstercards.ui.monster; package com.majinnaibu.monstercards.ui.monster;
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 androidx.lifecycle.ViewModel;
@@ -181,7 +180,7 @@ public class MonsterDetailViewModel extends ViewModel {
return mMonsterId; return mMonsterId;
} }
public void setMonster(@NonNull Monster monster) { public void setMonster(Monster monster) {
mMonster = monster; mMonster = monster;
mAbilities.setValue(mMonster.getAbilityDescriptions()); mAbilities.setValue(mMonster.getAbilityDescriptions());
mActions.setValue(mMonster.getActionDescriptions()); mActions.setValue(mMonster.getActionDescriptions());

View File

@@ -88,7 +88,7 @@ public class MonsterImportFragment extends MCFragment {
return root; return root;
} }
private void setupLabeledTextView(@NonNull TextView view, String text, int titleId) { private void setupLabeledTextView(TextView view, String text, int titleId) {
String title = getString(titleId); String title = getString(titleId);
String fullText = String.format("<b>%s</b> %s", title, text); String fullText = String.format("<b>%s</b> %s", title, text);
view.setText(Html.fromHtml(fullText)); view.setText(Html.fromHtml(fullText));
@@ -184,7 +184,7 @@ public class MonsterImportFragment extends MCFragment {
return super.onOptionsItemSelected(item); return super.onOptionsItemSelected(item);
} }
private void navigateToEditMonster(@NonNull UUID monsterId) { private void navigateToEditMonster(UUID monsterId) {
NavController navController = Navigation.findNavController(requireView()); NavController navController = Navigation.findNavController(requireView());
NavDirections action; NavDirections action;
action = MonsterImportFragmentDirections.actionMonsterImportFragmentToNavigationLibrary(); action = MonsterImportFragmentDirections.actionMonsterImportFragmentToNavigationLibrary();
@@ -234,7 +234,7 @@ public class MonsterImportFragment extends MCFragment {
final TextView regionalEffects_label; final TextView regionalEffects_label;
final ImageView regionalEffects_divider; final ImageView regionalEffects_divider;
ViewHolder(@NonNull View root) { ViewHolder(View root) {
this.root = root; this.root = root;
name = root.findViewById(R.id.name); name = root.findViewById(R.id.name);
meta = root.findViewById(R.id.meta); meta = root.findViewById(R.id.meta);

View File

@@ -1,6 +1,5 @@
package com.majinnaibu.monstercards.ui.monster; package com.majinnaibu.monstercards.ui.monster;
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 androidx.lifecycle.ViewModel;
@@ -184,7 +183,7 @@ public class MonsterImportViewModel extends ViewModel {
return mMonster; return mMonster;
} }
public void setMonster(@NonNull Monster monster) { public void setMonster(Monster monster) {
mMonster = monster; mMonster = monster;
mAbilities.setValue(mMonster.getAbilityDescriptions()); mAbilities.setValue(mMonster.getAbilityDescriptions());
mActions.setValue(mMonster.getActionDescriptions()); mActions.setValue(mMonster.getActionDescriptions());

View File

@@ -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;
@@ -25,7 +27,6 @@ public class SearchResultsRecyclerViewAdapter extends RecyclerView.Adapter<Searc
private String mSearchText; private String mSearchText;
private List<Monster> mValues; private List<Monster> mValues;
private Disposable mSubscriptionHandler; private Disposable mSubscriptionHandler;
public SearchResultsRecyclerViewAdapter(MonsterRepository repository, public SearchResultsRecyclerViewAdapter(MonsterRepository repository,
ItemCallback onClick) { ItemCallback onClick) {
mRepository = repository; mRepository = repository;
@@ -50,7 +51,7 @@ public class SearchResultsRecyclerViewAdapter extends RecyclerView.Adapter<Searc
throwable -> Logger.logError("Error performing search", throwable)); throwable -> Logger.logError("Error performing search", throwable));
} }
@NonNull @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())
@@ -59,7 +60,7 @@ public class SearchResultsRecyclerViewAdapter extends RecyclerView.Adapter<Searc
} }
@Override @Override
public void onBindViewHolder(@NonNull final ViewHolder holder, int position) { public void onBindViewHolder(final ViewHolder holder, int position) {
Monster monster = mValues.get(position); Monster monster = mValues.get(position);
holder.mContentView.setText(monster.name); holder.mContentView.setText(monster.name);
holder.itemView.setTag(monster); holder.itemView.setTag(monster);

View File

@@ -0,0 +1,19 @@
package com.majinnaibu.monstercards.ui.search;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;
public class SearchViewModel extends ViewModel {
private MutableLiveData<String> mSearchQuery;
public SearchViewModel() {
mSearchQuery = new MutableLiveData<>();
mSearchQuery.setValue("");
}
public LiveData<String> getSearchQuery() {
return mSearchQuery;
}
}

View File

@@ -25,7 +25,7 @@ public class SwipeToDeleteCallback extends ItemTouchHelper.SimpleCallback {
private final OnMoveCallback mOnMove; private final OnMoveCallback mOnMove;
private final Context mContext; private final Context mContext;
public SwipeToDeleteCallback(@NonNull Context context, OnSwipeCallback onDelete, OnMoveCallback onMove) { public SwipeToDeleteCallback(Context context, OnSwipeCallback onDelete, OnMoveCallback onMove) {
super(onMove == null ? 0 : ItemTouchHelper.UP | ItemTouchHelper.DOWN, onDelete == null ? 0 : ItemTouchHelper.LEFT); super(onMove == null ? 0 : ItemTouchHelper.UP | ItemTouchHelper.DOWN, onDelete == null ? 0 : ItemTouchHelper.LEFT);
mOnDelete = onDelete; mOnDelete = onDelete;
mOnMove = onMove; mOnMove = onMove;

View File

@@ -4,7 +4,6 @@ import androidx.lifecycle.MutableLiveData;
import java.util.Objects; import java.util.Objects;
@SuppressWarnings("unused")
public class ChangeTrackedLiveData<T> extends MutableLiveData<T> { public class ChangeTrackedLiveData<T> extends MutableLiveData<T> {
private final OnValueChangedCallback<T> mOnValueChangedCallback; private final OnValueChangedCallback<T> mOnValueChangedCallback;
private final OnValueDirtiedCallback mOnValueDirtiedCallback; private final OnValueDirtiedCallback mOnValueDirtiedCallback;

View File

@@ -2,7 +2,6 @@ package com.majinnaibu.monstercards.utils;
import android.util.Log; import android.util.Log;
@SuppressWarnings("unused")
public class Logger { public class Logger {
public static final String LOG_TAG = "MonsterCards"; public static final String LOG_TAG = "MonsterCards";
@@ -38,7 +37,7 @@ public class Logger {
StackTraceElement stackTraceElement = throwable.getStackTrace()[0]; StackTraceElement stackTraceElement = throwable.getStackTrace()[0];
String location = stackTraceElement.getClassName() + "." + stackTraceElement.getMethodName() + ":" + stackTraceElement.getLineNumber(); String location = stackTraceElement.getClassName() + "." + stackTraceElement.getMethodName() + ":" + stackTraceElement.getLineNumber();
String message = String.format("Unexpected error occurred at %s.", location); String message = String.format("Unexpected error occured at %s.", location);
Log.wtf(LOG_TAG, message, throwable); Log.wtf(LOG_TAG, message, throwable);
} }
@@ -56,7 +55,7 @@ public class Logger {
StackTraceElement stackTraceElement = throwable.getStackTrace()[0]; StackTraceElement stackTraceElement = throwable.getStackTrace()[0];
String location = stackTraceElement.getClassName() + "." + stackTraceElement.getMethodName() + ":" + stackTraceElement.getLineNumber(); String location = stackTraceElement.getClassName() + "." + stackTraceElement.getMethodName() + ":" + stackTraceElement.getLineNumber();
String message = String.format("Unexpected error occurred at %s.", location); String message = String.format("Unexpected error occured at %s.", location);
Log.e(LOG_TAG, message, throwable); Log.e(LOG_TAG, message, throwable);
} }
@@ -74,7 +73,7 @@ public class Logger {
StackTraceElement stackTraceElement = throwable.getStackTrace()[0]; StackTraceElement stackTraceElement = throwable.getStackTrace()[0];
String location = stackTraceElement.getClassName() + "." + stackTraceElement.getMethodName() + ":" + stackTraceElement.getLineNumber(); String location = stackTraceElement.getClassName() + "." + stackTraceElement.getMethodName() + ":" + stackTraceElement.getLineNumber();
String message = String.format("Unexpected error occurred at %s.", location); String message = String.format("Unexpected error occured at %s.", location);
Log.w(LOG_TAG, message, throwable); Log.w(LOG_TAG, message, throwable);
} }
@@ -92,7 +91,7 @@ public class Logger {
StackTraceElement stackTraceElement = throwable.getStackTrace()[0]; StackTraceElement stackTraceElement = throwable.getStackTrace()[0];
String location = stackTraceElement.getClassName() + "." + stackTraceElement.getMethodName() + ":" + stackTraceElement.getLineNumber(); String location = stackTraceElement.getClassName() + "." + stackTraceElement.getMethodName() + ":" + stackTraceElement.getLineNumber();
String message = String.format("Unexpected error occurred at %s.", location); String message = String.format("Unexpected error occured at %s.", location);
Log.i(LOG_TAG, message, throwable); Log.i(LOG_TAG, message, throwable);
} }
@@ -110,7 +109,7 @@ public class Logger {
StackTraceElement stackTraceElement = throwable.getStackTrace()[0]; StackTraceElement stackTraceElement = throwable.getStackTrace()[0];
String location = stackTraceElement.getClassName() + "." + stackTraceElement.getMethodName() + ":" + stackTraceElement.getLineNumber(); String location = stackTraceElement.getClassName() + "." + stackTraceElement.getMethodName() + ":" + stackTraceElement.getLineNumber();
String message = String.format("Unexpected error occurred at %s.", location); String message = String.format("Unexpected error occured at %s.", location);
Log.d(LOG_TAG, message, throwable); Log.d(LOG_TAG, message, throwable);
} }
@@ -128,7 +127,7 @@ public class Logger {
StackTraceElement stackTraceElement = throwable.getStackTrace()[0]; StackTraceElement stackTraceElement = throwable.getStackTrace()[0];
String location = stackTraceElement.getClassName() + "." + stackTraceElement.getMethodName() + ":" + stackTraceElement.getLineNumber(); String location = stackTraceElement.getClassName() + "." + stackTraceElement.getMethodName() + ":" + stackTraceElement.getLineNumber();
String message = String.format("Unexpected error occurred at %s.", location); String message = String.format("Unexpected error occured at %s.", location);
Log.v(LOG_TAG, message, throwable); Log.v(LOG_TAG, message, throwable);
} }

View File

@@ -3,7 +3,6 @@ package com.majinnaibu.monstercards.utils;
import android.text.Editable; import android.text.Editable;
import android.text.TextWatcher; import android.text.TextWatcher;
@SuppressWarnings("unused")
public class TextChangedListener implements TextWatcher { public class TextChangedListener implements TextWatcher {
private final BeforeTextChangedCallback mBeforeTextChangedCallback; private final BeforeTextChangedCallback mBeforeTextChangedCallback;

View File

@@ -17,7 +17,7 @@
app:layout_constraintRight_toRightOf="parent" app:layout_constraintRight_toRightOf="parent"
app:menu="@menu/bottom_nav_menu" /> app:menu="@menu/bottom_nav_menu" />
<androidx.fragment.app.FragmentContainerView <fragment
android:id="@+id/nav_host_fragment" android:id="@+id/nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment" android:name="androidx.navigation.fragment.NavHostFragment"

View File

@@ -10,9 +10,9 @@
android:id="@+id/name" android:id="@+id/name"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_margin="@dimen/text_icon_border_padding" android:layout_margin="2dp"
android:textColor="@android:color/primary_text_light" android:textColor="@android:color/primary_text_light"
android:textSize="@dimen/text_icon_tiny" android:textSize="8sp"
android:textStyle="bold" android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
@@ -23,9 +23,9 @@
android:id="@+id/advantage" android:id="@+id/advantage"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_margin="@dimen/text_icon_border_padding" android:layout_margin="2dp"
android:textColor="@android:color/primary_text_light" android:textColor="@android:color/primary_text_light"
android:textSize="@dimen/text_icon_tiny" android:textSize="8sp"
android:textStyle="bold" android:textStyle="bold"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
@@ -35,9 +35,9 @@
android:id="@+id/proficiency" android:id="@+id/proficiency"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_margin="@dimen/text_icon_border_padding" android:layout_margin="2dp"
android:textColor="@android:color/primary_text_light" android:textColor="@android:color/primary_text_light"
android:textSize="@dimen/text_icon_tiny" android:textSize="8sp"
android:textStyle="bold" android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
@@ -48,7 +48,7 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:textColor="@android:color/primary_text_light" android:textColor="@android:color/primary_text_light"
android:textSize="@dimen/text_icon_size" android:textSize="20sp"
android:textStyle="bold" android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"

View File

@@ -3,17 +3,17 @@
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="@dimen/action_card_height" android:layout_height="match_parent"
android:background="@drawable/rectangle_background"> android:background="@drawable/rectangle_background">
<TextView <TextView
android:id="@+id/name" android:id="@+id/name"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginHorizontal="@dimen/padding_normal" android:layout_marginHorizontal="8dp"
android:layout_marginTop="@dimen/padding_small" android:layout_marginTop="4dp"
android:textSize="@dimen/action_card_name_text_size" android:textSize="14sp"
android:textStyle="bold" android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
@@ -25,11 +25,11 @@
android:id="@+id/description" android:id="@+id/description"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="0dp" android:layout_height="0dp"
android:layout_marginHorizontal="@dimen/padding_normal" android:layout_marginHorizontal="8dp"
android:layout_marginBottom="@dimen/padding_normal" android:layout_marginBottom="8dp"
android:ellipsize="end" android:ellipsize="end"
android:singleLine="false" android:singleLine="false"
android:textSize="@dimen/action_card_description_text_size" android:textSize="10sp"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"

View File

@@ -2,18 +2,18 @@
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="@dimen/icon_size" android:layout_width="40dp"
android:layout_height="@dimen/icon_size" android:layout_height="40dp"
android:background="@drawable/rectangle_background"> android:background="@drawable/rectangle_background">
<TextView <TextView
android:id="@+id/name" android:id="@+id/name"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_margin="@dimen/text_icon_border_padding" android:layout_margin="2dp"
android:text="@string/label_armorClass_icon" android:text="AC"
android:textColor="@android:color/primary_text_light" android:textColor="@android:color/primary_text_light"
android:textSize="@dimen/text_icon_tiny" android:textSize="8sp"
android:textStyle="bold" android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
@@ -24,7 +24,7 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:textColor="@android:color/primary_text_light" android:textColor="@android:color/primary_text_light"
android:textSize="@dimen/text_icon_size" android:textSize="20sp"
android:textStyle="bold" android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"

View File

@@ -2,29 +2,29 @@
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="@dimen/icon_size" android:layout_width="40dp"
android:layout_height="@dimen/icon_size" android:layout_height="40dp"
android:background="@drawable/rectangle_background"> android:background="@drawable/rectangle_background">
<TextView <TextView
android:id="@+id/name" android:id="@+id/name"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_margin="@dimen/text_icon_border_padding" android:layout_margin="2dp"
android:text="@string/label_challengeRating_icon"
android:textColor="@android:color/primary_text_light" android:textColor="@android:color/primary_text_light"
android:textSize="@dimen/text_icon_tiny" android:textSize="8sp"
android:textStyle="bold" android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" /> app:layout_constraintStart_toStartOf="parent"
android:text="CR" />
<TextView <TextView
android:id="@+id/value" android:id="@+id/value"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:textColor="@android:color/primary_text_light" android:textColor="@android:color/primary_text_light"
android:textSize="@dimen/text_icon_size" android:textSize="20sp"
android:textStyle="bold" android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"

View File

@@ -2,18 +2,18 @@
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="@dimen/icon_size" android:layout_width="40dp"
android:layout_height="@dimen/icon_size" android:layout_height="40dp"
android:background="@drawable/rectangle_background"> android:background="@drawable/rectangle_background">
<TextView <TextView
android:id="@+id/name" android:id="@+id/name"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_margin="@dimen/text_icon_border_padding" android:layout_margin="2dp"
android:text="@string/label_hitPoints_icon" android:text="HP"
android:textColor="@android:color/primary_text_light" android:textColor="@android:color/primary_text_light"
android:textSize="@dimen/text_icon_tiny" android:textSize="8sp"
android:textStyle="bold" android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
@@ -24,7 +24,7 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:textColor="@android:color/primary_text_light" android:textColor="@android:color/primary_text_light"
android:textSize="@dimen/text_icon_size" android:textSize="20sp"
android:textStyle="bold" android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"

View File

@@ -2,18 +2,18 @@
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="@dimen/icon_size" android:layout_width="40dp"
android:layout_height="@dimen/icon_size" android:layout_height="40dp"
android:background="@drawable/rectangle_background"> android:background="@drawable/rectangle_background">
<TextView <TextView
android:id="@+id/name" android:id="@+id/name"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_margin="@dimen/text_icon_border_padding" android:layout_margin="2dp"
android:text="@string/label_initiative_icon" android:text="INIT"
android:textColor="@android:color/primary_text_light" android:textColor="@android:color/primary_text_light"
android:textSize="@dimen/text_icon_tiny" android:textSize="8sp"
android:textStyle="bold" android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
@@ -24,7 +24,7 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:textColor="@android:color/primary_text_light" android:textColor="@android:color/primary_text_light"
android:textSize="@dimen/text_icon_size" android:textSize="20sp"
android:textStyle="bold" android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"

View File

@@ -4,15 +4,15 @@
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_margin="@dimen/padding_normal" android:layout_margin="@dimen/text_margin"
android:background="@drawable/rectangle_background"> android:background="@drawable/rectangle_background">
<TextView <TextView
android:id="@+id/name" android:id="@+id/name"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_margin="@dimen/padding_normal" android:layout_margin="8dp"
android:textSize="@dimen/monster_card_name_text_size" android:textSize="20sp"
android:textStyle="bold" android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
@@ -23,8 +23,8 @@
android:id="@+id/meta" android:id="@+id/meta"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_margin="@dimen/padding_normal" android:layout_margin="8dp"
android:textSize="@dimen/monster_card_meta_text_size" android:textSize="12sp"
android:textStyle="italic" android:textStyle="italic"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
@@ -35,8 +35,8 @@
android:id="@+id/challengeRating" android:id="@+id/challengeRating"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_margin="@dimen/padding_normal" android:layout_margin="8dp"
android:textSize="@dimen/monster_card_name_text_size" android:textSize="20sp"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
tools:text="CR 1/8" /> tools:text="CR 1/8" />
@@ -45,7 +45,7 @@
android:id="@+id/boxesRow" android:id="@+id/boxesRow"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_margin="@dimen/padding_normal" android:layout_margin="8dp"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/meta"> app:layout_constraintTop_toBottomOf="@id/meta">
@@ -53,8 +53,8 @@
<include <include
android:id="@+id/strength" android:id="@+id/strength"
layout="@layout/card_ability_score" layout="@layout/card_ability_score"
android:layout_width="@dimen/icon_size" android:layout_width="40dp"
android:layout_height="@dimen/icon_size" /> android:layout_height="40dp" />
<Space <Space
android:layout_width="0dp" android:layout_width="0dp"
@@ -64,8 +64,8 @@
<include <include
android:id="@+id/dexterity" android:id="@+id/dexterity"
layout="@layout/card_ability_score" layout="@layout/card_ability_score"
android:layout_width="@dimen/icon_size" android:layout_width="40dp"
android:layout_height="@dimen/icon_size" /> android:layout_height="40dp" />
<Space <Space
android:layout_width="0dp" android:layout_width="0dp"
@@ -75,8 +75,8 @@
<include <include
android:id="@+id/constitution" android:id="@+id/constitution"
layout="@layout/card_ability_score" layout="@layout/card_ability_score"
android:layout_width="@dimen/icon_size" android:layout_width="40dp"
android:layout_height="@dimen/icon_size" /> android:layout_height="40dp" />
<Space <Space
android:layout_width="0dp" android:layout_width="0dp"
@@ -86,8 +86,8 @@
<include <include
android:id="@+id/intelligence" android:id="@+id/intelligence"
layout="@layout/card_ability_score" layout="@layout/card_ability_score"
android:layout_width="@dimen/icon_size" android:layout_width="40dp"
android:layout_height="@dimen/icon_size" /> android:layout_height="40dp" />
<Space <Space
android:layout_width="0dp" android:layout_width="0dp"
@@ -97,8 +97,8 @@
<include <include
android:id="@+id/wisdom" android:id="@+id/wisdom"
layout="@layout/card_ability_score" layout="@layout/card_ability_score"
android:layout_width="@dimen/icon_size" android:layout_width="40dp"
android:layout_height="@dimen/icon_size" /> android:layout_height="40dp" />
<Space <Space
android:layout_width="0dp" android:layout_width="0dp"
@@ -108,8 +108,8 @@
<include <include
android:id="@+id/charisma" android:id="@+id/charisma"
layout="@layout/card_ability_score" layout="@layout/card_ability_score"
android:layout_width="@dimen/icon_size" android:layout_width="40dp"
android:layout_height="@dimen/icon_size" /> android:layout_height="40dp" />
<Space <Space
android:layout_width="0dp" android:layout_width="0dp"
@@ -119,8 +119,8 @@
<include <include
android:id="@+id/armorClass" android:id="@+id/armorClass"
layout="@layout/card_armor_class" layout="@layout/card_armor_class"
android:layout_width="@dimen/icon_size" android:layout_width="40dp"
android:layout_height="@dimen/icon_size" /> android:layout_height="40dp" />
<Space <Space
android:layout_width="0dp" android:layout_width="0dp"
@@ -130,15 +130,15 @@
<include <include
android:id="@+id/hitPoints" android:id="@+id/hitPoints"
layout="@layout/card_hit_points" layout="@layout/card_hit_points"
android:layout_width="@dimen/icon_size" android:layout_width="40dp"
android:layout_height="@dimen/icon_size" /> android:layout_height="40dp" />
</LinearLayout> </LinearLayout>
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginHorizontal="@dimen/padding_small" android:layout_marginHorizontal="4dp"
android:layout_marginVertical="@dimen/padding_normal" android:layout_marginVertical="8dp"
android:baselineAligned="false" android:baselineAligned="false"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
@@ -149,24 +149,24 @@
android:id="@+id/action1" android:id="@+id/action1"
layout="@layout/card_action" layout="@layout/card_action"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="@dimen/action_card_height" android:layout_height="80dp"
android:layout_marginHorizontal="@dimen/padding_small" android:layout_marginHorizontal="4dp"
android:layout_weight="1" /> android:layout_weight="1" />
<include <include
android:id="@+id/action2" android:id="@+id/action2"
layout="@layout/card_action" layout="@layout/card_action"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="@dimen/action_card_height" android:layout_height="80dp"
android:layout_marginHorizontal="@dimen/padding_small" android:layout_marginHorizontal="4dp"
android:layout_weight="1" /> android:layout_weight="1" />
<include <include
android:id="@+id/action3" android:id="@+id/action3"
layout="@layout/card_action" layout="@layout/card_action"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="@dimen/action_card_height" android:layout_height="80dp"
android:layout_marginHorizontal="@dimen/padding_small" android:layout_marginHorizontal="4dp"
android:layout_weight="1" /> android:layout_weight="1" />
</LinearLayout> </LinearLayout>

View File

@@ -10,8 +10,8 @@
android:id="@+id/name" android:id="@+id/name"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_margin="@dimen/padding_normal" android:layout_margin="8dp"
android:textSize="@dimen/monster_card_name_text_size" android:textSize="20sp"
android:textStyle="bold" android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
@@ -22,8 +22,8 @@
android:id="@+id/meta" android:id="@+id/meta"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_margin="@dimen/padding_normal" android:layout_margin="8dp"
android:textSize="@dimen/monster_card_meta_text_size" android:textSize="12sp"
android:textStyle="italic" android:textStyle="italic"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
@@ -34,8 +34,8 @@
android:id="@+id/challengeRating" android:id="@+id/challengeRating"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_margin="@dimen/padding_normal" android:layout_margin="8dp"
android:textSize="@dimen/monster_card_name_text_size" android:textSize="20sp"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
tools:text="CR 1/8" /> tools:text="CR 1/8" />
@@ -44,7 +44,7 @@
android:id="@+id/boxesRow" android:id="@+id/boxesRow"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_margin="@dimen/padding_normal" android:layout_margin="8dp"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
@@ -53,8 +53,8 @@
<include <include
android:id="@+id/strength" android:id="@+id/strength"
layout="@layout/card_ability_score" layout="@layout/card_ability_score"
android:layout_width="@dimen/icon_size" android:layout_width="40dp"
android:layout_height="@dimen/icon_size" /> android:layout_height="40dp" />
<Space <Space
android:layout_width="0dp" android:layout_width="0dp"
@@ -64,8 +64,8 @@
<include <include
android:id="@+id/dexterity" android:id="@+id/dexterity"
layout="@layout/card_ability_score" layout="@layout/card_ability_score"
android:layout_width="@dimen/icon_size" android:layout_width="40dp"
android:layout_height="@dimen/icon_size" /> android:layout_height="40dp" />
<Space <Space
android:layout_width="0dp" android:layout_width="0dp"
@@ -75,8 +75,8 @@
<include <include
android:id="@+id/constitution" android:id="@+id/constitution"
layout="@layout/card_ability_score" layout="@layout/card_ability_score"
android:layout_width="@dimen/icon_size" android:layout_width="40dp"
android:layout_height="@dimen/icon_size" /> android:layout_height="40dp" />
<Space <Space
android:layout_width="0dp" android:layout_width="0dp"
@@ -86,8 +86,8 @@
<include <include
android:id="@+id/intelligence" android:id="@+id/intelligence"
layout="@layout/card_ability_score" layout="@layout/card_ability_score"
android:layout_width="@dimen/icon_size" android:layout_width="40dp"
android:layout_height="@dimen/icon_size" /> android:layout_height="40dp" />
<Space <Space
android:layout_width="0dp" android:layout_width="0dp"
@@ -97,8 +97,8 @@
<include <include
android:id="@+id/wisdom" android:id="@+id/wisdom"
layout="@layout/card_ability_score" layout="@layout/card_ability_score"
android:layout_width="@dimen/icon_size" android:layout_width="40dp"
android:layout_height="@dimen/icon_size" /> android:layout_height="40dp" />
<Space <Space
android:layout_width="0dp" android:layout_width="0dp"
@@ -108,8 +108,8 @@
<include <include
android:id="@+id/charisma" android:id="@+id/charisma"
layout="@layout/card_ability_score" layout="@layout/card_ability_score"
android:layout_width="@dimen/icon_size" android:layout_width="40dp"
android:layout_height="@dimen/icon_size" /> android:layout_height="40dp" />
<Space <Space
android:layout_width="0dp" android:layout_width="0dp"
@@ -119,8 +119,8 @@
<include <include
android:id="@+id/armorClass" android:id="@+id/armorClass"
layout="@layout/card_armor_class" layout="@layout/card_armor_class"
android:layout_width="@dimen/icon_size" android:layout_width="40dp"
android:layout_height="@dimen/icon_size" /> android:layout_height="40dp" />
<Space <Space
android:layout_width="0dp" android:layout_width="0dp"
@@ -130,7 +130,7 @@
<include <include
android:id="@+id/hitPoints" android:id="@+id/hitPoints"
layout="@layout/card_hit_points" layout="@layout/card_hit_points"
android:layout_width="@dimen/icon_size" android:layout_width="40dp"
android:layout_height="@dimen/icon_size" /> android:layout_height="40dp" />
</LinearLayout> </LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -27,7 +27,7 @@
app:layout_constraintTop_toBottomOf="@id/label"> app:layout_constraintTop_toBottomOf="@id/label">
<com.google.android.material.radiobutton.MaterialRadioButton <com.google.android.material.radiobutton.MaterialRadioButton
android:id="@+id/hasNoAdvantage" android:id="@+id/none"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginHorizontal="@dimen/padding_small" android:layout_marginHorizontal="@dimen/padding_small"
@@ -43,7 +43,7 @@
tools:checked="true" /> tools:checked="true" />
<com.google.android.material.radiobutton.MaterialRadioButton <com.google.android.material.radiobutton.MaterialRadioButton
android:id="@+id/hasAdvantage" android:id="@+id/advantage"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginHorizontal="@dimen/padding_small" android:layout_marginHorizontal="@dimen/padding_small"
@@ -59,7 +59,7 @@
tools:checked="false" /> tools:checked="false" />
<com.google.android.material.radiobutton.MaterialRadioButton <com.google.android.material.radiobutton.MaterialRadioButton
android:id="@+id/hasDisadvantage" android:id="@+id/disadvantage"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginHorizontal="@dimen/padding_small" android:layout_marginHorizontal="@dimen/padding_small"

View File

@@ -10,10 +10,8 @@
android:id="@+id/list" android:id="@+id/list"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:clipToPadding="false"
android:divider="?android:attr/dividerVertical" android:divider="?android:attr/dividerVertical"
android:dividerPadding="@dimen/text_margin" android:dividerPadding="@dimen/text_margin"
android:padding="@dimen/padding_normal"
app:layoutManager="LinearLayoutManager" app:layoutManager="LinearLayoutManager"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"

View File

@@ -3,7 +3,7 @@
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="match_parent"
android:orientation="vertical"> android:orientation="vertical">
<!-- understands but textbox --> <!-- understands but textbox -->

View File

@@ -181,7 +181,7 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_margin="@dimen/text_margin" android:layout_margin="@dimen/text_margin"
android:text="@string/label_regional_effects" android:text="@string/label_regional_actions"
android:textSize="@dimen/text_h4_size" android:textSize="@dimen/text_h4_size"
app:drawableEndCompat="@drawable/ic_chevron_right_24" /> app:drawableEndCompat="@drawable/ic_chevron_right_24" />

View File

@@ -1,33 +1,13 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" <androidx.recyclerview.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.editmonster.EditSkillsFragment">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/list" android:id="@+id/list"
android:name="com.majinnaibu.monstercards.ui.editmonster.EditSkillsFragment"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:divider="?android:attr/dividerVertical" android:layout_marginLeft="16dp"
android:dividerPadding="@dimen/text_margin" android:layout_marginRight="16dp"
app:layoutManager="LinearLayoutManager" app:layoutManager="LinearLayoutManager"
app:layout_constraintBottom_toBottomOf="parent" tools:context=".ui.editmonster.EditSkillsFragment"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:listitem="@layout/fragment_edit_skills_list_item" /> tools:listitem="@layout/fragment_edit_skills_list_item" />
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/add_skill"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="@dimen/fab_margin"
android:contentDescription="@string/action_add_skill"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:srcCompat="@android:drawable/ic_input_add"
app:tint="@android:color/white" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -1,14 +1,10 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android" <com.google.android.material.textfield.TextInputLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.editmonster.EditStringFragment">
<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_margin="@dimen/text_margin"> android:layout_margin="@dimen/text_margin"
tools:context=".ui.editmonster.EditStringFragment">
<com.google.android.material.textfield.TextInputEditText <com.google.android.material.textfield.TextInputEditText
android:id="@+id/description" android:id="@+id/description"
@@ -18,5 +14,5 @@
android:importantForAutofill="no" android:importantForAutofill="no"
android:inputType="text" android:inputType="text"
tools:text="blinded" /> tools:text="blinded" />
</com.google.android.material.textfield.TextInputLayout> </com.google.android.material.textfield.TextInputLayout>
</ScrollView>

View File

@@ -1,15 +1,11 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".ui.editmonster.EditTraitFragment"> tools:context=".ui.editmonster.EditTraitFragment">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<com.google.android.material.textfield.TextInputLayout <com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@@ -36,8 +32,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:hint="@string/label_description" android:hint="@string/label_description"
android:importantForAutofill="no" android:importantForAutofill="no"
android:inputType="textMultiLine" android:inputType="text"
tools:text="John Doe" /> tools:text="John Doe" />
</com.google.android.material.textfield.TextInputLayout> </com.google.android.material.textfield.TextInputLayout>
</LinearLayout> </LinearLayout>
</ScrollView>

View File

@@ -11,11 +11,9 @@
android:id="@+id/monster_list" android:id="@+id/monster_list"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
app:layoutManager="LinearLayoutManager" app:layoutManager="LinearLayoutManager"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:context=".MonsterListFragment" tools:context=".MonsterListFragment"
tools:listitem="@layout/monster_list_content" /> tools:listitem="@layout/monster_list_content" />
@@ -26,8 +24,8 @@
android:layout_gravity="bottom|end" android:layout_gravity="bottom|end"
android:layout_margin="@dimen/fab_margin" android:layout_margin="@dimen/fab_margin"
android:contentDescription="@string/action_add_monster" android:contentDescription="@string/action_add_monster"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:srcCompat="@android:drawable/ic_input_add" app:srcCompat="@android:drawable/ic_input_add"
app:tint="@android:color/white" /> app:tint="@android:color/white"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android" <ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
@@ -56,7 +57,7 @@
app:layout_constraintTop_toBottomOf="@+id/meta" /> app:layout_constraintTop_toBottomOf="@+id/meta" />
<TextView <TextView
android:id="@+id/armorClass" android:id="@+id/armor_class"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="8dp" android:layout_marginStart="8dp"
@@ -69,7 +70,7 @@
tools:text="Armor Class 15" /> tools:text="Armor Class 15" />
<TextView <TextView
android:id="@+id/hitPoints" android:id="@+id/hit_points"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="8dp" android:layout_marginStart="8dp"
@@ -78,7 +79,7 @@
android:layout_marginBottom="8dp" android:layout_marginBottom="8dp"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/armorClass" app:layout_constraintTop_toBottomOf="@+id/armor_class"
tools:text="Hit Points 1 (1d4 - 1)" /> tools:text="Hit Points 1 (1d4 - 1)" />
<TextView <TextView
@@ -91,7 +92,7 @@
android:layout_marginBottom="8dp" android:layout_marginBottom="8dp"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/hitPoints" app:layout_constraintTop_toBottomOf="@+id/hit_points"
tools:text="10 ft., fly 30 ft." /> tools:text="10 ft., fly 30 ft." />
<ImageView <ImageView
@@ -111,19 +112,19 @@
<!-- Strength --> <!-- Strength -->
<TextView <TextView
android:id="@+id/strength_label" android:id="@+id/label_str"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="8dp" android:layout_marginStart="8dp"
android:layout_marginTop="8dp" android:layout_marginTop="8dp"
android:layout_marginEnd="8dp" android:layout_marginEnd="8dp"
android:layout_marginBottom="8dp" android:layout_marginBottom="8dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toStartOf="@+id/label_dex"
app:layout_constraintTop_toBottomOf="@+id/divider2"
android:text="@string/strength_abbreviation" android:text="@string/strength_abbreviation"
android:textAlignment="center" android:textAlignment="center"
android:textStyle="bold" android:textStyle="bold" />
app:layout_constraintEnd_toStartOf="@+id/dexterity_label"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/divider2" />
<TextView <TextView
android:id="@+id/strength" android:id="@+id/strength"
@@ -133,27 +134,27 @@
android:layout_marginTop="8dp" android:layout_marginTop="8dp"
android:layout_marginEnd="8dp" android:layout_marginEnd="8dp"
android:layout_marginBottom="8dp" android:layout_marginBottom="8dp"
app:layout_constraintStart_toStartOf="@+id/label_str"
app:layout_constraintEnd_toEndOf="@+id/label_str"
app:layout_constraintTop_toBottomOf="@+id/label_str"
android:textAlignment="center" android:textAlignment="center"
app:layout_constraintEnd_toEndOf="@+id/strength_label"
app:layout_constraintStart_toStartOf="@+id/strength_label"
app:layout_constraintTop_toBottomOf="@+id/strength_label"
tools:text="2 (-4)" /> tools:text="2 (-4)" />
<!-- Dexterity --> <!-- Dexterity -->
<TextView <TextView
android:id="@+id/dexterity_label" android:id="@+id/label_dex"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="8dp" android:layout_marginStart="8dp"
android:layout_marginTop="8dp" android:layout_marginTop="8dp"
android:layout_marginEnd="8dp" android:layout_marginEnd="8dp"
android:layout_marginBottom="8dp" android:layout_marginBottom="8dp"
app:layout_constraintStart_toEndOf="@+id/label_str"
app:layout_constraintEnd_toStartOf="@+id/label_con"
app:layout_constraintTop_toBottomOf="@+id/divider2"
android:text="@string/dexterity_abbreviation" android:text="@string/dexterity_abbreviation"
android:textAlignment="center" android:textAlignment="center"
android:textStyle="bold" android:textStyle="bold" />
app:layout_constraintEnd_toStartOf="@+id/constitution_label"
app:layout_constraintStart_toEndOf="@+id/strength_label"
app:layout_constraintTop_toBottomOf="@+id/divider2" />
<TextView <TextView
android:id="@+id/dexterity" android:id="@+id/dexterity"
@@ -163,57 +164,57 @@
android:layout_marginTop="8dp" android:layout_marginTop="8dp"
android:layout_marginEnd="8dp" android:layout_marginEnd="8dp"
android:layout_marginBottom="8dp" android:layout_marginBottom="8dp"
app:layout_constraintStart_toStartOf="@+id/label_dex"
app:layout_constraintEnd_toEndOf="@+id/label_dex"
app:layout_constraintTop_toBottomOf="@+id/label_dex"
android:textAlignment="center" android:textAlignment="center"
app:layout_constraintEnd_toEndOf="@+id/dexterity_label"
app:layout_constraintStart_toStartOf="@+id/dexterity_label"
app:layout_constraintTop_toBottomOf="@+id/dexterity_label"
tools:text="20 (+5)" /> tools:text="20 (+5)" />
<!-- Constitution --> <!-- Constitution -->
<TextView <TextView
android:id="@+id/constitution_label" android:id="@+id/label_con"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="8dp" android:layout_marginStart="8dp"
android:layout_marginTop="8dp" android:layout_marginTop="8dp"
android:layout_marginEnd="8dp" android:layout_marginEnd="8dp"
android:layout_marginBottom="8dp" android:layout_marginBottom="8dp"
app:layout_constraintStart_toEndOf="@+id/label_dex"
app:layout_constraintEnd_toStartOf="@+id/label_int"
app:layout_constraintTop_toBottomOf="@+id/divider2"
android:text="@string/constitution_abbreviation" android:text="@string/constitution_abbreviation"
android:textAlignment="center" android:textAlignment="center"
android:textStyle="bold" android:textStyle="bold" />
app:layout_constraintEnd_toStartOf="@+id/intelligence_label"
app:layout_constraintStart_toEndOf="@+id/dexterity_label"
app:layout_constraintTop_toBottomOf="@+id/divider2" />
<TextView <TextView
android:id="@+id/constitution" android:id="@+id/constitution"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:textAlignment="center"
android:layout_marginStart="8dp" android:layout_marginStart="8dp"
android:layout_marginTop="8dp" android:layout_marginTop="8dp"
android:layout_marginEnd="8dp" android:layout_marginEnd="8dp"
android:layout_marginBottom="8dp" android:layout_marginBottom="8dp"
android:textAlignment="center" app:layout_constraintStart_toStartOf="@+id/label_con"
app:layout_constraintEnd_toEndOf="@+id/constitution_label" app:layout_constraintEnd_toEndOf="@+id/label_con"
app:layout_constraintStart_toStartOf="@+id/constitution_label" app:layout_constraintTop_toBottomOf="@+id/label_con"
app:layout_constraintTop_toBottomOf="@+id/constitution_label"
tools:text="8 (-1)" /> tools:text="8 (-1)" />
<!-- Intelligence --> <!-- Intelligence -->
<TextView <TextView
android:id="@+id/intelligence_label" android:id="@+id/label_int"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="8dp" android:layout_marginStart="8dp"
android:layout_marginTop="8dp" android:layout_marginTop="8dp"
android:layout_marginEnd="8dp" android:layout_marginEnd="8dp"
android:layout_marginBottom="8dp" android:layout_marginBottom="8dp"
app:layout_constraintStart_toEndOf="@+id/label_con"
app:layout_constraintEnd_toStartOf="@+id/label_wis"
app:layout_constraintTop_toBottomOf="@+id/divider2"
android:text="@string/intelligence_abbreviation" android:text="@string/intelligence_abbreviation"
android:textAlignment="center" android:textAlignment="center"
android:textStyle="bold" android:textStyle="bold" />
app:layout_constraintEnd_toStartOf="@+id/wisdom_label"
app:layout_constraintStart_toEndOf="@+id/constitution_label"
app:layout_constraintTop_toBottomOf="@+id/divider2" />
<TextView <TextView
android:id="@+id/intelligence" android:id="@+id/intelligence"
@@ -223,27 +224,27 @@
android:layout_marginTop="8dp" android:layout_marginTop="8dp"
android:layout_marginEnd="8dp" android:layout_marginEnd="8dp"
android:layout_marginBottom="8dp" android:layout_marginBottom="8dp"
app:layout_constraintStart_toStartOf="@+id/label_int"
app:layout_constraintEnd_toEndOf="@+id/label_int"
app:layout_constraintTop_toBottomOf="@+id/label_int"
android:textAlignment="center" android:textAlignment="center"
app:layout_constraintEnd_toEndOf="@+id/intelligence_label"
app:layout_constraintStart_toStartOf="@+id/intelligence_label"
app:layout_constraintTop_toBottomOf="@+id/intelligence_label"
tools:text="10 (+0)" /> tools:text="10 (+0)" />
<!-- Wisdom --> <!-- Wisdom -->
<TextView <TextView
android:id="@+id/wisdom_label" android:id="@+id/label_wis"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="8dp" android:layout_marginStart="8dp"
android:layout_marginTop="8dp" android:layout_marginTop="8dp"
android:layout_marginEnd="8dp" android:layout_marginEnd="8dp"
android:layout_marginBottom="8dp" android:layout_marginBottom="8dp"
app:layout_constraintStart_toEndOf="@+id/label_int"
app:layout_constraintEnd_toStartOf="@+id/label_cha"
app:layout_constraintTop_toBottomOf="@+id/divider2"
android:text="@string/wisdom_abbreviation" android:text="@string/wisdom_abbreviation"
android:textAlignment="center" android:textAlignment="center"
android:textStyle="bold" android:textStyle="bold" />
app:layout_constraintEnd_toStartOf="@+id/charisma_label"
app:layout_constraintStart_toEndOf="@+id/intelligence_label"
app:layout_constraintTop_toBottomOf="@+id/divider2" />
<TextView <TextView
android:id="@+id/wisdom" android:id="@+id/wisdom"
@@ -253,27 +254,27 @@
android:layout_marginTop="8dp" android:layout_marginTop="8dp"
android:layout_marginEnd="8dp" android:layout_marginEnd="8dp"
android:layout_marginBottom="8dp" android:layout_marginBottom="8dp"
app:layout_constraintStart_toStartOf="@+id/label_wis"
app:layout_constraintEnd_toEndOf="@+id/label_wis"
app:layout_constraintTop_toBottomOf="@+id/label_wis"
android:textAlignment="center" android:textAlignment="center"
app:layout_constraintEnd_toEndOf="@+id/wisdom_label"
app:layout_constraintStart_toStartOf="@+id/wisdom_label"
app:layout_constraintTop_toBottomOf="@+id/wisdom_label"
tools:text="14 (+2)" /> tools:text="14 (+2)" />
<!-- Charisma --> <!-- Charisma -->
<TextView <TextView
android:id="@+id/charisma_label" android:id="@+id/label_cha"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="8dp" android:layout_marginStart="8dp"
android:layout_marginTop="8dp" android:layout_marginTop="8dp"
android:layout_marginEnd="8dp" android:layout_marginEnd="8dp"
android:layout_marginBottom="8dp" android:layout_marginBottom="8dp"
app:layout_constraintStart_toEndOf="@+id/label_wis"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@+id/divider2"
android:text="@string/charisma_abbreviation" android:text="@string/charisma_abbreviation"
android:textAlignment="center" android:textAlignment="center"
android:textStyle="bold" android:textStyle="bold" />
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/wisdom_label"
app:layout_constraintTop_toBottomOf="@+id/divider2" />
<TextView <TextView
android:id="@+id/charisma" android:id="@+id/charisma"
@@ -283,10 +284,10 @@
android:layout_marginTop="8dp" android:layout_marginTop="8dp"
android:layout_marginEnd="8dp" android:layout_marginEnd="8dp"
android:layout_marginBottom="8dp" android:layout_marginBottom="8dp"
app:layout_constraintStart_toStartOf="@+id/label_cha"
app:layout_constraintEnd_toEndOf="@+id/label_cha"
app:layout_constraintTop_toBottomOf="@+id/label_cha"
android:textAlignment="center" android:textAlignment="center"
app:layout_constraintEnd_toEndOf="@+id/charisma_label"
app:layout_constraintStart_toStartOf="@+id/charisma_label"
app:layout_constraintTop_toBottomOf="@+id/charisma_label"
tools:text="15 (+2)" /> tools:text="15 (+2)" />
<ImageView <ImageView
@@ -305,7 +306,7 @@
app:layout_constraintTop_toBottomOf="@+id/strength" /> app:layout_constraintTop_toBottomOf="@+id/strength" />
<TextView <TextView
android:id="@+id/savingThrows" android:id="@+id/saving_throws"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="8dp" android:layout_marginStart="8dp"
@@ -327,11 +328,11 @@
android:layout_marginBottom="8dp" android:layout_marginBottom="8dp"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/savingThrows" app:layout_constraintTop_toBottomOf="@+id/saving_throws"
tools:text="Skills" /> tools:text="Skills" />
<TextView <TextView
android:id="@+id/damageVulnerabilities" android:id="@+id/damage_vulnerabilities"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="8dp" android:layout_marginStart="8dp"
@@ -344,7 +345,7 @@
tools:text="Damage Vulnerabilities" /> tools:text="Damage Vulnerabilities" />
<TextView <TextView
android:id="@+id/damageResistances" android:id="@+id/damage_resistances"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="8dp" android:layout_marginStart="8dp"
@@ -353,11 +354,11 @@
android:layout_marginBottom="8dp" android:layout_marginBottom="8dp"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/damageVulnerabilities" app:layout_constraintTop_toBottomOf="@+id/damage_vulnerabilities"
tools:text="Damage Resistances" /> tools:text="Damage Resistances" />
<TextView <TextView
android:id="@+id/damageImmunities" android:id="@+id/damage_immunities"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="8dp" android:layout_marginStart="8dp"
@@ -366,11 +367,11 @@
android:layout_marginBottom="8dp" android:layout_marginBottom="8dp"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/damageResistances" app:layout_constraintTop_toBottomOf="@+id/damage_resistances"
tools:text="Damage Immunities" /> tools:text="Damage Immunities" />
<TextView <TextView
android:id="@+id/conditionImmunities" android:id="@+id/condition_immunities"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="8dp" android:layout_marginStart="8dp"
@@ -379,7 +380,7 @@
android:layout_marginBottom="8dp" android:layout_marginBottom="8dp"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/damageImmunities" app:layout_constraintTop_toBottomOf="@+id/damage_immunities"
tools:text="Condition Immunities" /> tools:text="Condition Immunities" />
<TextView <TextView
@@ -392,7 +393,7 @@
android:layout_marginBottom="8dp" android:layout_marginBottom="8dp"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/conditionImmunities" app:layout_constraintTop_toBottomOf="@+id/condition_immunities"
tools:text="Senses" /> tools:text="Senses" />
<TextView <TextView
@@ -424,241 +425,17 @@
<!-- Abilities --> <!-- Abilities -->
<LinearLayout <LinearLayout
android:id="@+id/abilities" android:id="@+id/abilities"
android:orientation="vertical"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="8dp" android:layout_marginStart="8dp"
android:layout_marginTop="0dp" android:layout_marginTop="0dp"
android:layout_marginEnd="8dp" android:layout_marginEnd="8dp"
android:layout_marginBottom="0dp" android:layout_marginBottom="0dp"
android:orientation="vertical"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/challenge" app:layout_constraintTop_toBottomOf="@+id/challenge"
tools:text="Damage Vulnerabilities" /> tools:text="Damage Vulnerabilities" />
<TextView
android:id="@+id/actions_label"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="8dp"
android:text="@string/label_actions"
android:textAppearance="@android:style/TextAppearance.Material.Title"
android:textColor="@color/colorPrimaryDark"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/abilities" />
<ImageView
android:id="@+id/actions_divider"
android:layout_width="0dp"
android:layout_height="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="8dp"
android:contentDescription="@string/section_divider"
android:scaleType="fitXY"
android:src="@drawable/ic_section_divider"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/actions_label" />
<!-- Actions -->
<LinearLayout
android:id="@+id/actions"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="0dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="0dp"
android:orientation="vertical"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/actions_divider"
tools:text="Damage Vulnerabilities" />
<TextView
android:id="@+id/reactions_label"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="8dp"
android:text="@string/label_reactions"
android:textAppearance="@android:style/TextAppearance.Material.Title"
android:textColor="@color/colorPrimaryDark"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/actions" />
<ImageView
android:id="@+id/reactions_divider"
android:layout_width="0dp"
android:layout_height="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="8dp"
android:contentDescription="@string/section_divider"
android:scaleType="fitXY"
android:src="@drawable/ic_section_divider"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/reactions_label" />
<!-- Reactions -->
<LinearLayout
android:id="@+id/reactions"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="0dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="0dp"
android:orientation="vertical"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/reactions_divider"
tools:text="Damage Vulnerabilities" />
<TextView
android:id="@+id/legendaryActions_label"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="8dp"
android:text="@string/label_legendary_actions"
android:textAppearance="@android:style/TextAppearance.Material.Title"
android:textColor="@color/colorPrimaryDark"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/reactions" />
<ImageView
android:id="@+id/legendaryActions_divider"
android:layout_width="0dp"
android:layout_height="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="8dp"
android:contentDescription="@string/section_divider"
android:scaleType="fitXY"
android:src="@drawable/ic_section_divider"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/legendaryActions_label" />
<!-- Legendary Actions -->
<LinearLayout
android:id="@+id/legendaryActions"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="0dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="0dp"
android:orientation="vertical"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/legendaryActions_divider"
tools:text="Damage Vulnerabilities" />
<TextView
android:id="@+id/lairActions_label"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="8dp"
android:text="@string/label_lair_actions"
android:textAppearance="@android:style/TextAppearance.Material.Title"
android:textColor="@color/colorPrimaryDark"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/legendaryActions" />
<ImageView
android:id="@+id/lairActions_divider"
android:layout_width="0dp"
android:layout_height="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="8dp"
android:contentDescription="@string/section_divider"
android:scaleType="fitXY"
android:src="@drawable/ic_section_divider"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/lairActions_label" />
<!-- Lair Actions -->
<LinearLayout
android:id="@+id/lairActions"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="0dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="0dp"
android:orientation="vertical"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/lairActions_divider"
tools:text="Damage Vulnerabilities" />
<TextView
android:id="@+id/regionalEffects_label"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="8dp"
android:text="@string/label_regional_effects"
android:textAppearance="@android:style/TextAppearance.Material.Title"
android:textColor="@color/colorPrimaryDark"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/lairActions" />
<ImageView
android:id="@+id/regionalEffects_divider"
android:layout_width="0dp"
android:layout_height="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="8dp"
android:contentDescription="@string/section_divider"
android:scaleType="fitXY"
android:src="@drawable/ic_section_divider"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/regionalEffects_label" />
<!-- Regional Effects -->
<LinearLayout
android:id="@+id/regionalEffects"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="0dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="0dp"
android:orientation="vertical"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/regionalEffects_divider"
tools:text="Damage Vulnerabilities" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
</ScrollView> </ScrollView>

View File

@@ -24,15 +24,15 @@
<androidx.recyclerview.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
android:id="@+id/monster_list" android:id="@+id/monster_list"
android:layout_width="0dp"
android:layout_height="0dp" android:layout_height="0dp"
android:layout_width="0dp"
android:layout_marginLeft="16dp" android:layout_marginLeft="16dp"
android:layout_marginRight="16dp" android:layout_marginRight="16dp"
app:layoutManager="LinearLayoutManager"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/search_query" app:layout_constraintTop_toBottomOf="@+id/search_query"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layoutManager="LinearLayoutManager"
tools:context=".SearchResultsFragment" tools:context=".SearchResultsFragment"
tools:listitem="@layout/monster_list_content" /> tools:listitem="@layout/monster_list_content" />

View File

@@ -10,10 +10,10 @@
android:id="@+id/name" android:id="@+id/name"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_margin="@dimen/padding_normal" android:layout_margin="8dp"
android:ellipsize="end" android:ellipsize="end"
android:lines="1" android:lines="1"
android:textSize="@dimen/monster_tile_name_text_size" android:textSize="16sp"
android:textStyle="bold" android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
@@ -24,10 +24,10 @@
android:id="@+id/meta" android:id="@+id/meta"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_margin="@dimen/padding_normal" android:layout_margin="8dp"
android:ellipsize="end" android:ellipsize="end"
android:lines="1" android:lines="1"
android:textSize="@dimen/monster_tile_meta_text_size" android:textSize="10sp"
android:textStyle="italic" android:textStyle="italic"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
@@ -38,7 +38,7 @@
android:id="@+id/boxesRow" android:id="@+id/boxesRow"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_margin="@dimen/padding_normal" android:layout_margin="8dp"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/meta"> app:layout_constraintTop_toBottomOf="@id/meta">
@@ -46,8 +46,8 @@
<include <include
android:id="@+id/armorClass" android:id="@+id/armorClass"
layout="@layout/card_armor_class" layout="@layout/card_armor_class"
android:layout_width="@dimen/icon_size" android:layout_width="40dp"
android:layout_height="@dimen/icon_size" /> android:layout_height="40dp" />
<Space <Space
@@ -58,8 +58,8 @@
<include <include
android:id="@+id/hitPoints" android:id="@+id/hitPoints"
layout="@layout/card_hit_points" layout="@layout/card_hit_points"
android:layout_width="@dimen/icon_size" android:layout_width="40dp"
android:layout_height="@dimen/icon_size" /> android:layout_height="40dp" />
<Space <Space
android:layout_width="0dp" android:layout_width="0dp"
@@ -69,8 +69,8 @@
<include <include
android:id="@+id/initiative" android:id="@+id/initiative"
layout="@layout/card_initiative" layout="@layout/card_initiative"
android:layout_width="@dimen/icon_size" android:layout_width="40dp"
android:layout_height="@dimen/icon_size" /> android:layout_height="40dp" />
<Space <Space
android:layout_width="0dp" android:layout_width="0dp"
@@ -80,8 +80,8 @@
<include <include
android:id="@+id/challengeRating" android:id="@+id/challengeRating"
layout="@layout/card_challenge_rating" layout="@layout/card_challenge_rating"
android:layout_width="@dimen/icon_size" android:layout_width="40dp"
android:layout_height="@dimen/icon_size" /> android:layout_height="40dp" />
</LinearLayout> </LinearLayout>
@@ -89,9 +89,9 @@
android:id="@+id/action" android:id="@+id/action"
layout="@layout/card_action" layout="@layout/card_action"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="@dimen/action_card_height" android:layout_height="wrap_content"
android:layout_marginHorizontal="@dimen/padding_small" android:layout_marginHorizontal="4dp"
android:layout_marginVertical="@dimen/padding_normal" android:layout_marginVertical="8dp"
android:baselineAligned="false" android:baselineAligned="false"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"

View File

@@ -10,10 +10,10 @@
android:id="@+id/name" android:id="@+id/name"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_margin="@dimen/padding_normal" android:layout_margin="8dp"
android:ellipsize="end" android:ellipsize="end"
android:lines="1" android:lines="1"
android:textSize="@dimen/monster_tile_name_text_size" android:textSize="16sp"
android:textStyle="bold" android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
@@ -24,10 +24,10 @@
android:id="@+id/meta" android:id="@+id/meta"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_margin="@dimen/padding_normal" android:layout_margin="8dp"
android:ellipsize="end" android:ellipsize="end"
android:lines="1" android:lines="1"
android:textSize="@dimen/monster_tile_meta_text_size" android:textSize="10sp"
android:textStyle="italic" android:textStyle="italic"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
@@ -38,7 +38,7 @@
android:id="@+id/boxesRow" android:id="@+id/boxesRow"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_margin="@dimen/padding_normal" android:layout_margin="8dp"
android:baselineAligned="false" android:baselineAligned="false"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
@@ -48,8 +48,8 @@
<include <include
android:id="@+id/armorClass" android:id="@+id/armorClass"
layout="@layout/card_armor_class" layout="@layout/card_armor_class"
android:layout_width="@dimen/icon_size" android:layout_width="40dp"
android:layout_height="@dimen/icon_size" /> android:layout_height="40dp" />
<Space <Space
@@ -60,8 +60,8 @@
<include <include
android:id="@+id/hitPoints" android:id="@+id/hitPoints"
layout="@layout/card_hit_points" layout="@layout/card_hit_points"
android:layout_width="@dimen/icon_size" android:layout_width="40dp"
android:layout_height="@dimen/icon_size" /> android:layout_height="40dp" />
<Space <Space
android:layout_width="0dp" android:layout_width="0dp"
@@ -71,8 +71,8 @@
<include <include
android:id="@+id/initiative" android:id="@+id/initiative"
layout="@layout/card_initiative" layout="@layout/card_initiative"
android:layout_width="@dimen/icon_size" android:layout_width="40dp"
android:layout_height="@dimen/icon_size" /> android:layout_height="40dp" />
<Space <Space
android:layout_width="0dp" android:layout_width="0dp"
@@ -82,8 +82,8 @@
<include <include
android:id="@+id/challengeRating" android:id="@+id/challengeRating"
layout="@layout/card_challenge_rating" layout="@layout/card_challenge_rating"
android:layout_width="@dimen/icon_size" android:layout_width="40dp"
android:layout_height="@dimen/icon_size" /> android:layout_height="40dp" />
</LinearLayout> </LinearLayout>

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" <menu xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:app="http://schemas.android.com/apk/res-auto"> xmlns:android="http://schemas.android.com/apk/res/android">
<item <item
android:id="@+id/menu_action_edit_monster" android:id="@+id/menu_action_edit_monster"

View File

@@ -14,6 +14,7 @@
android:id="@+id/action_navigation_search_to_navigation_monster" android:id="@+id/action_navigation_search_to_navigation_monster"
app:destination="@id/navigation_monster" /> app:destination="@id/navigation_monster" />
</fragment> </fragment>
<fragment <fragment
android:id="@+id/navigation_dashboard" android:id="@+id/navigation_dashboard"
android:name="com.majinnaibu.monstercards.ui.dashboard.DashboardFragment" android:name="com.majinnaibu.monstercards.ui.dashboard.DashboardFragment"
@@ -23,6 +24,7 @@
android:id="@+id/action_navigation_dashboard_to_navigation_monster" android:id="@+id/action_navigation_dashboard_to_navigation_monster"
app:destination="@id/navigation_monster" /> app:destination="@id/navigation_monster" />
</fragment> </fragment>
<fragment <fragment
android:id="@+id/navigation_collections" android:id="@+id/navigation_collections"
android:name="com.majinnaibu.monstercards.ui.collections.CollectionsFragment" android:name="com.majinnaibu.monstercards.ui.collections.CollectionsFragment"
@@ -32,6 +34,7 @@
android:id="@+id/action_navigation_collections_to_navigation_monster" android:id="@+id/action_navigation_collections_to_navigation_monster"
app:destination="@id/navigation_monster" /> app:destination="@id/navigation_monster" />
</fragment> </fragment>
<fragment <fragment
android:id="@+id/navigation_library" android:id="@+id/navigation_library"
android:name="com.majinnaibu.monstercards.ui.library.LibraryFragment" android:name="com.majinnaibu.monstercards.ui.library.LibraryFragment"
@@ -41,10 +44,11 @@
android:id="@+id/action_navigation_library_to_navigation_monster" android:id="@+id/action_navigation_library_to_navigation_monster"
app:destination="@id/navigation_monster" /> app:destination="@id/navigation_monster" />
</fragment> </fragment>
<fragment <fragment
android:id="@+id/navigation_monster" android:id="@+id/navigation_monster"
android:name="com.majinnaibu.monstercards.ui.monster.MonsterDetailFragment" android:name="com.majinnaibu.monstercards.ui.monster.MonsterDetailFragment"
android:label="@string/title_monsterDetails" android:label="Monster"
tools:layout="@layout/fragment_monster"> tools:layout="@layout/fragment_monster">
<argument <argument
android:name="monster_id" android:name="monster_id"
@@ -63,7 +67,7 @@
<fragment <fragment
android:id="@+id/editMonsterFragment" android:id="@+id/editMonsterFragment"
android:name="com.majinnaibu.monstercards.ui.editmonster.EditMonsterFragment" android:name="com.majinnaibu.monstercards.ui.editmonster.EditMonsterFragment"
android:label="@string/title_editMonster" android:label="Edit Monster"
tools:layout="@layout/fragment_edit_monster"> tools:layout="@layout/fragment_edit_monster">
<argument <argument
android:name="monster_id" android:name="monster_id"
@@ -102,36 +106,36 @@
<fragment <fragment
android:id="@+id/editBasicInfoFragment" android:id="@+id/editBasicInfoFragment"
android:name="com.majinnaibu.monstercards.ui.editmonster.EditBasicInfoFragment" android:name="com.majinnaibu.monstercards.ui.editmonster.EditBasicInfoFragment"
android:label="@string/title_editBasicInfo" android:label="fragment_edit_basic_info"
tools:layout="@layout/fragment_edit_basic_info" /> tools:layout="@layout/fragment_edit_basic_info" />
<fragment <fragment
android:id="@+id/editArmorFragment" android:id="@+id/editArmorFragment"
android:name="com.majinnaibu.monstercards.ui.editmonster.EditArmorFragment" android:name="com.majinnaibu.monstercards.ui.editmonster.EditArmorFragment"
android:label="@string/title_editArmor" android:label="fragment_edit_armor"
tools:layout="@layout/fragment_edit_armor" /> tools:layout="@layout/fragment_edit_armor" />
<fragment <fragment
android:id="@+id/editSpeedFragment" android:id="@+id/editSpeedFragment"
android:name="com.majinnaibu.monstercards.ui.editmonster.EditSpeedFragment" android:name="com.majinnaibu.monstercards.ui.editmonster.EditSpeedFragment"
android:label="@string/title_editSpeed" android:label="fragment_edit_speed"
tools:layout="@layout/fragment_edit_speed" /> tools:layout="@layout/fragment_edit_speed" />
<fragment <fragment
android:id="@+id/editAbilityScoresFragment" android:id="@+id/editAbilityScoresFragment"
android:name="com.majinnaibu.monstercards.ui.editmonster.EditAbilityScoresFragment" android:name="com.majinnaibu.monstercards.ui.editmonster.EditAbilityScoresFragment"
android:label="@string/title_editAbilityScores" /> android:label="EditAbilityScoresFragment" />
<fragment <fragment
android:id="@+id/editSavingThrowsFragment" android:id="@+id/editSavingThrowsFragment"
android:name="com.majinnaibu.monstercards.ui.editmonster.EditSavingThrowsFragment" android:name="com.majinnaibu.monstercards.ui.editmonster.EditSavingThrowsFragment"
android:label="@string/title_editSavingThrows" android:label="fragment_edit_saving_throws"
tools:layout="@layout/fragment_edit_saving_throws" /> tools:layout="@layout/fragment_edit_saving_throws" />
<fragment <fragment
android:id="@+id/editChallengeRatingFragment" android:id="@+id/editChallengeRatingFragment"
android:name="com.majinnaibu.monstercards.ui.editmonster.EditChallengeRatingFragment" android:name="com.majinnaibu.monstercards.ui.editmonster.EditChallengeRatingFragment"
android:label="@string/title_editChallengeRating" android:label="fragment_edit_challenge_rating"
tools:layout="@layout/fragment_edit_challenge_rating" /> tools:layout="@layout/fragment_edit_challenge_rating" />
<fragment <fragment
android:id="@+id/editSkillsFragment" android:id="@+id/editSkillsFragment"
android:name="com.majinnaibu.monstercards.ui.editmonster.EditSkillsFragment" android:name="com.majinnaibu.monstercards.ui.editmonster.EditSkillsFragment"
android:label="@string/title_editSkills" android:label="fragment_edit_skills_list"
tools:layout="@layout/fragment_edit_skills_list"> tools:layout="@layout/fragment_edit_skills_list">
<action <action
android:id="@+id/action_editSkillsFragment_to_editSkillFragment" android:id="@+id/action_editSkillsFragment_to_editSkillFragment"
@@ -140,7 +144,7 @@
<fragment <fragment
android:id="@+id/editSkillFragment" android:id="@+id/editSkillFragment"
android:name="com.majinnaibu.monstercards.ui.editmonster.EditSkillFragment" android:name="com.majinnaibu.monstercards.ui.editmonster.EditSkillFragment"
android:label="@string/title_editSkill" android:label="fragment_edit_skill"
tools:layout="@layout/fragment_edit_skill"> tools:layout="@layout/fragment_edit_skill">
<argument <argument
android:name="name" android:name="name"
@@ -158,7 +162,7 @@
<fragment <fragment
android:id="@+id/editLanguagesFragment" android:id="@+id/editLanguagesFragment"
android:name="com.majinnaibu.monstercards.ui.editmonster.EditLanguagesFragment" android:name="com.majinnaibu.monstercards.ui.editmonster.EditLanguagesFragment"
android:label="@string/title_editLanguages" android:label="fragment_edit_languages_list"
tools:layout="@layout/fragment_edit_languages_list"> tools:layout="@layout/fragment_edit_languages_list">
<action <action
android:id="@+id/action_editLanguagesFragment_to_editLanguageFragment" android:id="@+id/action_editLanguagesFragment_to_editLanguageFragment"
@@ -167,7 +171,7 @@
<fragment <fragment
android:id="@+id/editLanguageFragment" android:id="@+id/editLanguageFragment"
android:name="com.majinnaibu.monstercards.ui.editmonster.EditLanguageFragment" android:name="com.majinnaibu.monstercards.ui.editmonster.EditLanguageFragment"
android:label="@string/title_editLanguage" android:label="fragment_edit_language"
tools:layout="@layout/fragment_edit_language"> tools:layout="@layout/fragment_edit_language">
<argument <argument
android:name="name" android:name="name"
@@ -179,7 +183,7 @@
<fragment <fragment
android:id="@+id/editTraitFragment" android:id="@+id/editTraitFragment"
android:name="com.majinnaibu.monstercards.ui.editmonster.EditTraitFragment" android:name="com.majinnaibu.monstercards.ui.editmonster.EditTraitFragment"
android:label="@string/title_editTrait"> android:label="EditTraitFragment">
<argument <argument
android:name="description" android:name="description"
app:argType="string" /> app:argType="string" />
@@ -193,7 +197,7 @@
<fragment <fragment
android:id="@+id/editTraitListFragment" android:id="@+id/editTraitListFragment"
android:name="com.majinnaibu.monstercards.ui.editmonster.EditTraitsFragment" android:name="com.majinnaibu.monstercards.ui.editmonster.EditTraitsFragment"
android:label="@string/title_editTraits"> android:label="EditTraitListFragment">
<action <action
android:id="@+id/action_editTraitListFragment_to_editTraitFragment" android:id="@+id/action_editTraitListFragment_to_editTraitFragment"
app:destination="@id/editTraitFragment" /> app:destination="@id/editTraitFragment" />
@@ -215,7 +219,7 @@
<fragment <fragment
android:id="@+id/editStringFragment" android:id="@+id/editStringFragment"
android:name="com.majinnaibu.monstercards.ui.editmonster.EditStringFragment" android:name="com.majinnaibu.monstercards.ui.editmonster.EditStringFragment"
android:label="@string/title_editString"> android:label="EditStringFragment">
<argument <argument
android:name="stringType" android:name="stringType"
app:argType="com.majinnaibu.monstercards.data.enums.StringType" /> app:argType="com.majinnaibu.monstercards.data.enums.StringType" />

View File

@@ -1,14 +1,9 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<attr name="label" format="string" localization="suggested" />
<declare-styleable name="Stepper"> <declare-styleable name="Stepper">
<attr name="stepAmount" format="integer" /> <attr name="stepAmount" format="integer" />
<attr name="minValue" format="integer" /> <attr name="minValue" format="integer" />
<attr name="maxValue" format="integer" /> <attr name="maxValue" format="integer" />
<attr name="label" /> <attr name="label" format="string" localization="suggested" />
</declare-styleable>
<declare-styleable name="AbilityScorePicker">
<attr name="label" />
</declare-styleable> </declare-styleable>
</resources> </resources>

View File

@@ -1,22 +1,11 @@
<resources> <resources>
<!-- Default screen margins, per the Android Design guidelines. --> <!-- Default screen margins, per the Android Design guidelines. -->
<dimen name="action_card_description_text_size">10sp</dimen>
<dimen name="action_card_height">80dp</dimen>
<dimen name="action_card_name_text_size">14sp</dimen>
<dimen name="corner_radius">4dp</dimen>
<dimen name="fab_margin">16dp</dimen>
<dimen name="icon_size">40dp</dimen>
<dimen name="monster_card_meta_text_size">12sp</dimen>
<dimen name="monster_card_name_text_size">20sp</dimen>
<dimen name="monster_tile_meta_text_size">10sp</dimen>
<dimen name="monster_tile_name_text_size">16sp</dimen>
<dimen name="padding_huge">32dp</dimen>
<dimen name="padding_large">16dp</dimen>
<dimen name="padding_normal">8dp</dimen>
<dimen name="padding_small">4dp</dimen>
<dimen name="text_h4_size">20sp</dimen>
<dimen name="text_icon_border_padding">2dp</dimen>
<dimen name="text_icon_size">16sp</dimen>
<dimen name="text_icon_tiny">8sp</dimen>
<dimen name="text_margin">16dp</dimen> <dimen name="text_margin">16dp</dimen>
<dimen name="fab_margin">16dp</dimen>
<dimen name="text_h4_size">20sp</dimen>
<dimen name="corner_radius">4dp</dimen>
<dimen name="padding_small">4dp</dimen>
<dimen name="padding_normal">8dp</dimen>
<dimen name="padding_large">16dp</dimen>
<dimen name="padding_huge">32dp</dimen>
</resources> </resources>

View File

@@ -27,15 +27,12 @@
<string name="label_alignment">Alignment</string> <string name="label_alignment">Alignment</string>
<string name="label_armor">Armor</string> <string name="label_armor">Armor</string>
<string name="label_armor_class">Armor Class</string> <string name="label_armor_class">Armor Class</string>
<string name="label_armorClass_icon">AC</string>
<string name="label_base_speed">Base Speed</string> <string name="label_base_speed">Base Speed</string>
<string name="label_basic_info">Basic Info</string> <string name="label_basic_info">Basic Info</string>
<string name="label_burrow_speed">Burrow Speed</string> <string name="label_burrow_speed">Burrow Speed</string>
<string name="label_can_hover">Can Hover</string> <string name="label_can_hover">Can Hover</string>
<string name="label_can_speak_language">Can Speak</string> <string name="label_can_speak_language">Can Speak</string>
<string name="label_challenge_rating">Challenge Rating</string> <string name="label_challenge_rating">Challenge Rating</string>
<string name="label_challenge_rating_with_value">CR %s</string>
<string name="label_challengeRating_icon">CR</string>
<string name="label_charisma">Charisma</string> <string name="label_charisma">Charisma</string>
<string name="label_climb_speed">Climb Speed</string> <string name="label_climb_speed">Climb Speed</string>
<string name="label_condition_immunities">Condition Immunities</string> <string name="label_condition_immunities">Condition Immunities</string>
@@ -58,9 +55,7 @@
<string name="label_has_a_shield">Has a Shield</string> <string name="label_has_a_shield">Has a Shield</string>
<string name="label_hit_dice">Hit Dice</string> <string name="label_hit_dice">Hit Dice</string>
<string name="label_hit_points">Hit Points</string> <string name="label_hit_points">Hit Points</string>
<string name="label_hitPoints_icon">HP</string>
<string name="label_increment_field">+</string> <string name="label_increment_field">+</string>
<string name="label_initiative_icon">INIT</string>
<string name="label_intelligence">Intelligence</string> <string name="label_intelligence">Intelligence</string>
<string name="label_lair_actions">Lair Actions</string> <string name="label_lair_actions">Lair Actions</string>
<string name="label_languages">Languages</string> <string name="label_languages">Languages</string>
@@ -93,48 +88,41 @@
<string name="strength_abbreviation">STR</string> <string name="strength_abbreviation">STR</string>
<string name="title_collections">Collections</string> <string name="title_collections">Collections</string>
<string name="title_dashboard">Dashboard</string> <string name="title_dashboard">Dashboard</string>
<string name="title_editAbilities">Ability</string> <string name="title_edit_abilities">Ability</string>
<string name="title_editAbility">Abilities</string> <string name="title_edit_ability">Abilities</string>
<string name="title_editAbilityScores">Ability Scores</string> <string name="title_edit_ability_scores">Ability Scores</string>
<string name="title_editAction">Action</string> <string name="title_edit_action">Action</string>
<string name="title_editActions">Actions</string> <string name="title_edit_actions">Actions</string>
<string name="title_editArmor">Armor</string> <string name="title_edit_armor">Armor</string>
<string name="title_editBasicInfo">Basic Info</string> <string name="title_edit_basic_info">Basic Info</string>
<string name="title_editChallengeRating">Challenge Rating</string> <string name="title_edit_challenge_rating">Challenge Rating</string>
<string name="title_editConditionImmunities">Condition Immunities</string> <string name="title_edit_condition_immunities">Condition Immunities</string>
<string name="title_editConditionImmunity">Condition Immunity</string> <string name="title_edit_condition_immunity">Condition Immunity</string>
<string name="title_editDamageImmunities">Damage Immunities</string> <string name="title_edit_damage_immunities">Damage Immunities</string>
<string name="title_editDamageImmunity">Damage Immunity</string> <string name="title_edit_damage_immunity">Damage Immunity</string>
<string name="title_editDamageResistance">Damage Resistance</string> <string name="title_edit_damage_resistance">Damage Resistance</string>
<string name="title_editDamageResistances">Damage Resistances</string> <string name="title_edit_damage_resistances">Damage Resistances</string>
<string name="title_editDamageVulnerabilities">Damage Vulnerabilities</string> <string name="title_edit_damage_vulnerabilities">Damage Vulnerabilities</string>
<string name="title_editDamageVulnerability">Damage Vulnerability</string> <string name="title_edit_damage_vulnerability">Damage Vulnerability</string>
<string name="title_editLairAction">Lair Action</string> <string name="title_edit_lair_action">Lair Action</string>
<string name="title_editLairActions">Lair Actions</string> <string name="title_edit_lair_actions">Lair Actions</string>
<string name="title_editLanguage">Language</string> <string name="title_edit_language">Language</string>
<string name="title_editLanguages">Languages</string> <string name="title_edit_languages">Languages</string>
<string name="title_editLegendaryAction">Legendary Action</string> <string name="title_edit_legendary_action">Legendary Action</string>
<string name="title_editLegendaryActions">Legendary Actions</string> <string name="title_edit_legendary_actions">Legendary Actions</string>
<string name="title_editMonster">Edit Monster</string> <string name="title_edit_monster">Edit %1$s</string>
<string name="title_editMonster_fmt">Edit %1$s</string> <string name="title_edit_reaction">Reaction</string>
<string name="title_editReaction">Reaction</string> <string name="title_edit_reactions">Reactions</string>
<string name="title_editReactions">Reactions</string> <string name="title_edit_regional_action">Regional Action</string>
<string name="title_editRegionalAction">Regional Action</string> <string name="title_edit_regional_actions">Regional Actions</string>
<string name="title_editRegionalActions">Regional Actions</string> <string name="title_edit_speed">Speed</string>
<string name="title_editSpeed">Speed</string> <string name="title_edit_saving_throws">Saving Throws</string>
<string name="title_editSavingThrows">Saving Throws</string> <string name="title_edit_sense">Senses</string>
<string name="title_editSense">Senses</string> <string name="title_edit_senses">Senses</string>
<string name="title_editSenses">Senses</string> <string name="title_edit_skill">Skill</string>
<string name="title_editSkill">Skill</string> <string name="title_edit_skills">Skills</string>
<string name="title_editSkills">Skills</string>
<string name="title_editString">String</string>
<string name="title_editStrings">Strings</string>
<string name="title_editTrait">Trait</string>
<string name="title_editTraits">Traits</string>
<string name="title_importMonster">Import Monster</string> <string name="title_importMonster">Import Monster</string>
<string name="title_library">Library</string> <string name="title_library">Library</string>
<string name="title_monsterDetails">Monster Details</string>
<string name="title_monsterDetails_fmt">%1$s Details</string>
<string name="title_search">Search</string> <string name="title_search">Search</string>
<string name="wisdom_abbreviation">WIS</string> <string name="wisdom_abbreviation">WIS</string>
</resources> </resources>

View File

@@ -1,17 +1,10 @@
package com.majinnaibu.monstercards.init; package com.majinnaibu.monstercards.init;
import android.content.Context; import android.content.Context;
import android.os.Bundle;
import androidx.navigation.NavController;
import androidx.navigation.NavDestination;
@SuppressWarnings("unused")
public class FlipperInitializer { public class FlipperInitializer {
public static void init(Context ctx) { public static void init(Context ctx) {}
}
public static void sendNavigationEvent(NavController controller, NavDestination destination, Bundle arguments) { public static void sendNavigationEvent(NavController controller, NavDestination destination, Bundle arguments) {
} }
}

View File

@@ -2,11 +2,13 @@
buildscript { buildscript {
repositories { repositories {
google() google()
mavenCentral() jcenter()
} }
dependencies { dependencies {
classpath "com.android.tools.build:gradle:7.0.1" classpath "com.android.tools.build:gradle:4.0.1"
classpath "androidx.navigation:navigation-safe-args-gradle-plugin:2.3.5"
def nav_version = "2.3.0"
classpath "androidx.navigation:navigation-safe-args-gradle-plugin:$nav_version"
// NOTE: Do not place your application dependencies here; they belong // NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files // in the individual module build.gradle files
@@ -16,16 +18,10 @@ buildscript {
allprojects { allprojects {
repositories { repositories {
google() google()
mavenCentral() jcenter()
// maven { url "https://oss.jfrog.org/libs-snapshot" } // maven { url "https://oss.jfrog.org/libs-snapshot" }
// maven { url 'http://repo1.maven.org/maven2' } // maven { url 'http://repo1.maven.org/maven2' }
} }
// Temporary workaround until room 2.4.0 is released https://issuetracker.google.com/issues/174695268?pli=1#comment10
configurations.configureEach {
resolutionStrategy {
force 'org.xerial:sqlite-jdbc:3.34.0'
}
}
} }
task clean(type: Delete) { task clean(type: Delete) {

Some files were not shown because too many files have changed in this diff Show More