Compare commits
240 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 70b7a4e795 | |||
| 8b4d9b6b17 | |||
| 6bad5a4ed5 | |||
| 93bf987bb9 | |||
| be433bf217 | |||
| 1ae81b03b0 | |||
| 4633a50bf4 | |||
| 9ac73337af | |||
| 25340cb7fd | |||
| be544f5304 | |||
| 3dc39ad6a4 | |||
| 92ea5b6a0d | |||
| a5eec5c4c8 | |||
| e598b2984a | |||
|
|
32ae8461b7 | ||
|
|
8686dbdaea | ||
|
|
a8df37325f | ||
|
|
2743a8337b | ||
|
|
b4767676d2 | ||
|
|
7c9037af84 | ||
|
|
c582ba5eaa | ||
|
|
8b2ab8f48f | ||
|
|
2de07c54cc | ||
|
|
c50f79c273 | ||
|
|
921a02f953 | ||
|
|
ec712842ca | ||
|
|
2f9dec4d02 | ||
|
|
cb1e3343c9 | ||
| 5bded410d2 | |||
| f6a032844c | |||
| d214d615e5 | |||
| 54f863ee5f | |||
| d4d298fcc3 | |||
| 7f31d98d7e | |||
| 68348b18c2 | |||
| 42a2994f2c | |||
| 218f39f6c2 | |||
| 2512bd8d75 | |||
| 370d416a23 | |||
| 60d139078b | |||
| 611fa6c323 | |||
| ab5a3c7c67 | |||
| b889857e80 | |||
| da0e072a45 | |||
| e075fc4369 | |||
| 0db46ebb51 | |||
| 20318b0ad5 | |||
| 6debb1eb27 | |||
| 87c845bd0d | |||
| f507f9d7cd | |||
| 8bb1f64e9f | |||
| f2d0e93911 | |||
| c9a7e028ae | |||
| 807871fe5c | |||
| acadf2170c | |||
| 8215d2021c | |||
| 0cbf6022c4 | |||
| eec695bfc8 | |||
| 8363912e53 | |||
| 67db8d79d0 | |||
| b5834f3db2 | |||
| ca6a319bd9 | |||
| 95ba20b5c6 | |||
| ea65692b38 | |||
| d7cf01e30d | |||
| 30c6dc7ee5 | |||
| f13be2c1ac | |||
| 920344b5fd | |||
| 7b3d6003d4 | |||
| c837c19b87 | |||
| b9759f6364 | |||
| f24f1d978c | |||
| 2defd1fca1 | |||
| 07f81a5f6d | |||
| 985c2fb730 | |||
| 0dc96a8c45 | |||
| 10bca503e5 | |||
| 1d335e9a37 | |||
| fbf119fb8a | |||
| 3d6adaad2c | |||
| c3a972571a | |||
| 4e45a547f4 | |||
| 792628d4a4 | |||
| b6b669a0db | |||
| 540a0474da | |||
| 49734d5eef | |||
| b2c3728e9a | |||
| 39cab7f799 | |||
|
|
1e007a3553 | ||
|
|
1a487f950d | ||
|
|
ea13e38402 | ||
|
|
8e2372085d | ||
|
|
129d910126 | ||
|
|
1a23e5e35a | ||
|
|
660cf633da | ||
|
|
1e7a7c68aa | ||
|
|
070fda0989 | ||
|
|
af05c41b75 | ||
|
|
efa4c2a299 | ||
|
|
2f5918b7a2 | ||
|
|
cb6f7122ed | ||
|
|
7cfc6d4f65 | ||
|
|
cdae6a8b39 | ||
|
|
9d46d1420e | ||
|
|
6d43b0635c | ||
|
|
4c138ee499 | ||
|
|
0fcfa7e782 | ||
|
|
791cf4164c | ||
|
|
fb12deaa3e | ||
|
|
6e597462ef | ||
|
|
12ffc5b15f | ||
|
|
9c81bd4905 | ||
|
|
f1cbc60857 | ||
|
|
a2798ddc82 | ||
|
|
ecf2b01723 | ||
|
|
18d6f2a31e | ||
|
|
7cbcf8d07c | ||
|
|
dc487d238a | ||
|
|
b8c702f665 | ||
|
|
259b59f519 | ||
|
|
5289bac908 | ||
|
|
34e11d97e5 | ||
|
|
ca6684a093 | ||
|
|
6e48a6f455 | ||
| b8af70406f | |||
| 7eae6f820e | |||
| 2076d53b11 | |||
| e20602cc3d | |||
| 04dc066191 | |||
| 72b3df429f | |||
| 8d94afeb55 | |||
| 8bae59ed29 | |||
| c401b7919e | |||
| 9983ba10cb | |||
| 171bc7436e | |||
| 04a30aa766 | |||
| 2356726e3f | |||
| 6151ad889c | |||
| 1f15d73573 | |||
| 40589f171d | |||
| a58c851240 | |||
| 2c6b514538 | |||
| f6a8b83343 | |||
| eb3fa5108f | |||
| 922db42322 | |||
| 71177b92f9 | |||
| 34e68443ae | |||
| 857733ec9c | |||
| 7e78ad8b7d | |||
| 430fa61be1 | |||
| 70e05cbb21 | |||
| b67073622f | |||
| c90579903d | |||
| 1a02eab07a | |||
| 00463c8092 | |||
| 153c49fe7b | |||
| 8178ec6fd7 | |||
| 2e7e40554d | |||
| 989440de83 | |||
| 3c4adacc17 | |||
| c28e1cb8c5 | |||
| 48dab535e9 | |||
| ff26cb64b7 | |||
| 28f0787020 | |||
| 71da064423 | |||
| 23bcdc237d | |||
| b56a662c9e | |||
| dcce64f91a | |||
| 595ee0c6fb | |||
| d52102d430 | |||
| 6a4abdd547 | |||
| bd3741af2d | |||
| e254adfdce | |||
| 9c973ef348 | |||
| dc9a0827d4 | |||
| b27274928e | |||
| 6bb1e419c8 | |||
| 3cda90eedd | |||
| 98a7dc5eeb | |||
| e384e29570 | |||
| 7aa6419ece | |||
| 6b953e320d | |||
| 9f56f0283a | |||
| b5f92afae9 | |||
| f58243ef6b | |||
| 886778ee78 | |||
| 0a85324734 | |||
| b374dbfe71 | |||
| 21af6e20ba | |||
| dc9066daca | |||
| e8e19d5371 | |||
| c5242b5206 | |||
| ac2e37e494 | |||
| c5d857435d | |||
| a1fab9d399 | |||
| e02e4ec399 | |||
| 8706240fb4 | |||
| e17c492baf | |||
| 2df11701e6 | |||
| c6c0e4f758 | |||
| 8c233a3bc7 | |||
| e98b72ad7d | |||
| 1fb8dc3a86 | |||
| 8b52b0c3e5 | |||
| ee065d7b39 | |||
| 59b319c27d | |||
| cdcb7a60d4 | |||
| 79106ec9f3 | |||
| bb4cbbb98b | |||
| 84b0fee261 | |||
| 0c3ab6dc39 | |||
| a694205c74 | |||
| 793987c3fb | |||
| 7d5f9c89a9 | |||
| 6da0bfe70a | |||
| a44893bca8 | |||
| 67375292a5 | |||
| 145c827417 | |||
| 8ff1cb8779 | |||
| 706b58fd2c | |||
| 15973a79f0 | |||
| 94edc44044 | |||
| 5396b7b014 | |||
| e0cc8560d1 | |||
| c627bb0873 | |||
| 6d8ec92012 | |||
| 212358e41d | |||
| 5fca394f0e | |||
| 6c914fb947 | |||
| 5a283b8dae | |||
| 407987e410 | |||
| 27a1dd7580 | |||
| 775fbf3d9b | |||
| 2a75de4bce | |||
| 72502b3d03 | |||
| 2b8a178c05 | |||
| ab306289bd | |||
| 74b0c6695f | |||
| 44d90ff5ea | |||
| 5113283550 |
1
Android/.gitignore
vendored
1
Android/.gitignore
vendored
@@ -8,6 +8,7 @@
|
|||||||
/.idea/navEditor.xml
|
/.idea/navEditor.xml
|
||||||
/.idea/assetWizardSettings.xml
|
/.idea/assetWizardSettings.xml
|
||||||
/.idea/dictionaries
|
/.idea/dictionaries
|
||||||
|
.DS_Store
|
||||||
/build
|
/build
|
||||||
/captures
|
/captures
|
||||||
.externalNativeBuild
|
.externalNativeBuild
|
||||||
|
|||||||
2
Android/.idea/compiler.xml
generated
2
Android/.idea/compiler.xml
generated
@@ -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="11" />
|
<bytecodeTargetLevel target="1.8" />
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
||||||
2
Android/.idea/gradle.xml
generated
2
Android/.idea/gradle.xml
generated
@@ -1,6 +1,5 @@
|
|||||||
<?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>
|
||||||
@@ -15,7 +14,6 @@
|
|||||||
</set>
|
</set>
|
||||||
</option>
|
</option>
|
||||||
<option name="resolveModulePerSourceSet" value="false" />
|
<option name="resolveModulePerSourceSet" value="false" />
|
||||||
<option name="useQualifiedModuleNames" value="true" />
|
|
||||||
</GradleProjectSettings>
|
</GradleProjectSettings>
|
||||||
</option>
|
</option>
|
||||||
</component>
|
</component>
|
||||||
|
|||||||
5
Android/.idea/jarRepositories.xml
generated
5
Android/.idea/jarRepositories.xml
generated
@@ -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>
|
||||||
19
Android/.idea/misc.xml
generated
19
Android/.idea/misc.xml
generated
@@ -1,5 +1,19 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
|
<component name="DesignSurface">
|
||||||
|
<option name="filePathToZoomLevelMap">
|
||||||
|
<map>
|
||||||
|
<entry key="app/src/main/res/layout/dropdown_list_item.xml" value="0.12777777777777777" />
|
||||||
|
<entry key="app/src/main/res/layout/fragment_dashboard_list_item.xml" value="0.2210144927536232" />
|
||||||
|
<entry key="app/src/main/res/layout/fragment_edit_strings_list.xml" value="0.2210144927536232" />
|
||||||
|
<entry key="app/src/main/res/layout/fragment_edit_strings_list_item.xml" value="0.2210144927536232" />
|
||||||
|
<entry key="app/src/main/res/layout/fragment_edit_traits_list.xml" value="0.2210144927536232" />
|
||||||
|
<entry key="app/src/main/res/layout/fragment_edit_traits_list_item.xml" value="0.2210144927536232" />
|
||||||
|
<entry key="app/src/main/res/layout/fragment_search.xml" value="0.16875" />
|
||||||
|
<entry key="app/src/main/res/layout/simple_list_item.xml" value="0.2210144927536232" />
|
||||||
|
</map>
|
||||||
|
</option>
|
||||||
|
</component>
|
||||||
<component name="NullableNotNullManager">
|
<component name="NullableNotNullManager">
|
||||||
<option name="myDefaultNullable" value="androidx.annotation.Nullable" />
|
<option name="myDefaultNullable" value="androidx.annotation.Nullable" />
|
||||||
<option name="myDefaultNotNull" value="androidx.annotation.NonNull" />
|
<option name="myDefaultNotNull" value="androidx.annotation.NonNull" />
|
||||||
@@ -25,7 +39,7 @@
|
|||||||
</option>
|
</option>
|
||||||
<option name="myNotNulls">
|
<option name="myNotNulls">
|
||||||
<value>
|
<value>
|
||||||
<list size="13">
|
<list size="14">
|
||||||
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.NotNull" />
|
<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="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="2" class="java.lang.String" itemvalue="android.support.annotation.NonNull" />
|
||||||
@@ -39,11 +53,12 @@
|
|||||||
<item index="10" class="java.lang.String" itemvalue="org.eclipse.jdt.annotation.NonNull" />
|
<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="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="12" class="java.lang.String" itemvalue="io.reactivex.rxjava3.annotations.NonNull" />
|
||||||
|
<item index="13" class="java.lang.String" itemvalue="lombok.NonNull" />
|
||||||
</list>
|
</list>
|
||||||
</value>
|
</value>
|
||||||
</option>
|
</option>
|
||||||
</component>
|
</component>
|
||||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_11" default="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
|
<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">
|
||||||
|
|||||||
1
Android/.idea/runConfigurations.xml
generated
1
Android/.idea/runConfigurations.xml
generated
@@ -3,7 +3,6 @@
|
|||||||
<component name="RunConfigurationProducerService">
|
<component name="RunConfigurationProducerService">
|
||||||
<option name="ignoredProducers">
|
<option name="ignoredProducers">
|
||||||
<set>
|
<set>
|
||||||
<option value="com.android.tools.idea.compose.preview.runconfiguration.ComposePreviewRunConfigurationProducer" />
|
|
||||||
<option value="org.jetbrains.plugins.gradle.execution.test.runner.AllInPackageGradleConfigurationProducer" />
|
<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.TestClassGradleConfigurationProducer" />
|
||||||
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestMethodGradleConfigurationProducer" />
|
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestMethodGradleConfigurationProducer" />
|
||||||
|
|||||||
1
Android/.idea/saveactions_settings.xml
generated
1
Android/.idea/saveactions_settings.xml
generated
@@ -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="" />
|
||||||
|
|||||||
4
Android/README.md
Normal file
4
Android/README.md
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
[](https://appcenter.ms)
|
||||||
|
|
||||||
|
# MonsterCards for Android
|
||||||
|
|
||||||
@@ -21,7 +21,7 @@ def gson_version = '2.8.6'
|
|||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdkVersion 30
|
compileSdkVersion 30
|
||||||
buildToolsVersion '30.0.3'
|
buildToolsVersion '30.0.2'
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId "com.majinnaibu.monstercards"
|
applicationId "com.majinnaibu.monstercards"
|
||||||
@@ -70,21 +70,21 @@ 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:$nav_version"
|
implementation "androidx.navigation:navigation-fragment:$nav_version"
|
||||||
implementation "androidx.navigation:navigation-ui:$nav_version"
|
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:$rxjava_version"
|
implementation "io.reactivex.rxjava3:rxjava:$rxjava_version"
|
||||||
@@ -106,4 +106,4 @@ dependencies {
|
|||||||
// Other 3rd Party
|
// Other 3rd Party
|
||||||
implementation 'com.atlassian.commonmark:commonmark:0.15.2'
|
implementation 'com.atlassian.commonmark:commonmark:0.15.2'
|
||||||
implementation "com.google.code.gson:gson:$gson_version"
|
implementation "com.google.code.gson:gson:$gson_version"
|
||||||
}
|
}
|
||||||
@@ -51,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>
|
||||||
|
|||||||
@@ -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();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import android.os.Bundle;
|
|||||||
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;
|
||||||
@@ -55,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());
|
||||||
@@ -67,15 +68,14 @@ 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();
|
||||||
@@ -86,7 +86,7 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
} 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;
|
||||||
@@ -98,7 +98,6 @@ 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 (InputStream inputStream =
|
try (InputStream inputStream =
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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"),
|
||||||
;
|
;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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);
|
||||||
@@ -15,7 +26,7 @@ public final class CommonMarkHelper {
|
|||||||
if (parent1 == parent2 && parent1 instanceof Paragraph) {
|
if (parent1 == parent2 && parent1 instanceof Paragraph) {
|
||||||
document = new Document();
|
document = new Document();
|
||||||
Node child = parent1.getFirstChild();
|
Node child = parent1.getFirstChild();
|
||||||
while (child != null) {
|
while(child != null) {
|
||||||
Node nextChild = child.getNext();
|
Node nextChild = child.getNext();
|
||||||
document.appendChild(child);
|
document.appendChild(child);
|
||||||
child = nextChild;//child.getNext();
|
child = nextChild;//child.getNext();
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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<>();
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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,20 +74,17 @@ 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();
|
if (mOnFormatValueCallback != null) {
|
||||||
}
|
mHolder.text.setText(mOnFormatValueCallback.onFormatValue(this.mCurrentValue));
|
||||||
}
|
} else {
|
||||||
|
mHolder.text.setText(String.valueOf(this.mCurrentValue));
|
||||||
private void updateDisplayedValue() {
|
}
|
||||||
if (mOnFormatValueCallback != null) {
|
|
||||||
mHolder.text.setText(mOnFormatValueCallback.onFormatValue(this.mCurrentValue));
|
|
||||||
} else {
|
|
||||||
mHolder.text.setText(String.valueOf(this.mCurrentValue));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -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);
|
||||||
|
|||||||
@@ -20,16 +20,13 @@ 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.List;
|
||||||
import java.util.Locale;
|
|
||||||
|
|
||||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
|
|
||||||
import io.reactivex.rxjava3.schedulers.Schedulers;
|
|
||||||
|
|
||||||
public class DashboardFragment extends MCFragment {
|
public class DashboardFragment extends MCFragment {
|
||||||
private DashboardViewModel mViewModel;
|
private DashboardViewModel mViewModel;
|
||||||
private ViewHolder mHolder;
|
private ViewHolder mHolder;
|
||||||
private DashboardRecyclerViewAdapter mAdapter;
|
private DashboardRecyclerViewAdapter mAdapter;
|
||||||
|
|
||||||
|
@Override
|
||||||
public View onCreateView(@NonNull LayoutInflater inflater,
|
public View onCreateView(@NonNull LayoutInflater inflater,
|
||||||
ViewGroup container, Bundle savedInstanceState) {
|
ViewGroup container, Bundle savedInstanceState) {
|
||||||
mViewModel = new ViewModelProvider(this).get(DashboardViewModel.class);
|
mViewModel = new ViewModelProvider(this).get(DashboardViewModel.class);
|
||||||
@@ -38,18 +35,11 @@ public class DashboardFragment extends MCFragment {
|
|||||||
|
|
||||||
setupRecyclerView(mHolder.list);
|
setupRecyclerView(mHolder.list);
|
||||||
|
|
||||||
getMonsterRepository()
|
|
||||||
.getMonsters()
|
|
||||||
.subscribeOn(Schedulers.io())
|
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
|
||||||
.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, getResources().getConfiguration().screenWidthDp / 396);
|
||||||
Logger.logWTF(String.format(Locale.US, "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);
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import com.majinnaibu.monstercards.databinding.CardMonsterBinding;
|
|||||||
import com.majinnaibu.monstercards.helpers.CommonMarkHelper;
|
import com.majinnaibu.monstercards.helpers.CommonMarkHelper;
|
||||||
import com.majinnaibu.monstercards.models.Monster;
|
import com.majinnaibu.monstercards.models.Monster;
|
||||||
import com.majinnaibu.monstercards.models.Trait;
|
import com.majinnaibu.monstercards.models.Trait;
|
||||||
|
import com.majinnaibu.monstercards.utils.ItemCallback;
|
||||||
import com.majinnaibu.monstercards.utils.Logger;
|
import com.majinnaibu.monstercards.utils.Logger;
|
||||||
|
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
@@ -28,17 +29,17 @@ 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<Monster> mOnClick;
|
||||||
|
|
||||||
protected DashboardRecyclerViewAdapter(ItemCallback onClick) {
|
protected DashboardRecyclerViewAdapter(ItemCallback<Monster> onClick) {
|
||||||
super(DIFF_CALLBACK);
|
super(DIFF_CALLBACK);
|
||||||
mOnClick = onClick;
|
mOnClick = onClick;
|
||||||
}
|
}
|
||||||
@@ -51,7 +52,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);
|
||||||
@@ -120,15 +120,11 @@ public class DashboardRecyclerViewAdapter extends ListAdapter<Monster, Dashboard
|
|||||||
|
|
||||||
holder.itemView.setOnClickListener(v -> {
|
holder.itemView.setOnClickListener(v -> {
|
||||||
if (mOnClick != null) {
|
if (mOnClick != null) {
|
||||||
mOnClick.onItemCallback(holder.monster);
|
mOnClick.onItem(holder.monster);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface ItemCallback {
|
|
||||||
void onItemCallback(Monster monster);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class ViewHolder extends RecyclerView.ViewHolder {
|
public static class ViewHolder extends RecyclerView.ViewHolder {
|
||||||
public final TextView name;
|
public final TextView name;
|
||||||
public final TextView meta;
|
public final TextView meta;
|
||||||
@@ -242,7 +238,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 "*";
|
||||||
|
|||||||
@@ -1,26 +1,50 @@
|
|||||||
package com.majinnaibu.monstercards.ui.dashboard;
|
package com.majinnaibu.monstercards.ui.dashboard;
|
||||||
|
|
||||||
|
import android.app.Application;
|
||||||
|
|
||||||
|
import androidx.lifecycle.AndroidViewModel;
|
||||||
import androidx.lifecycle.LiveData;
|
import androidx.lifecycle.LiveData;
|
||||||
import androidx.lifecycle.MutableLiveData;
|
import androidx.lifecycle.MutableLiveData;
|
||||||
import androidx.lifecycle.ViewModel;
|
|
||||||
|
|
||||||
|
import com.majinnaibu.monstercards.AppDatabase;
|
||||||
import com.majinnaibu.monstercards.models.Monster;
|
import com.majinnaibu.monstercards.models.Monster;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class DashboardViewModel extends ViewModel {
|
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
|
||||||
|
import io.reactivex.rxjava3.schedulers.Schedulers;
|
||||||
|
import io.reactivex.rxjava3.subscribers.DisposableSubscriber;
|
||||||
|
|
||||||
|
public class DashboardViewModel extends AndroidViewModel {
|
||||||
|
private final AppDatabase mDB;
|
||||||
private final MutableLiveData<List<Monster>> mMonsters;
|
private final MutableLiveData<List<Monster>> mMonsters;
|
||||||
|
|
||||||
public DashboardViewModel() {
|
public DashboardViewModel(Application application) {
|
||||||
|
super(application);
|
||||||
|
mDB = AppDatabase.getInstance(application);
|
||||||
mMonsters = new MutableLiveData<>(new ArrayList<>());
|
mMonsters = new MutableLiveData<>(new ArrayList<>());
|
||||||
|
mDB.monsterDAO()
|
||||||
|
.getAll()
|
||||||
|
.subscribeOn(Schedulers.io())
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.subscribe(new DisposableSubscriber<List<Monster>>() {
|
||||||
|
@Override
|
||||||
|
public void onNext(List<Monster> monsters) {
|
||||||
|
mMonsters.setValue(monsters);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onError(Throwable t) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onComplete() {
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public LiveData<List<Monster>> getMonsters() {
|
public LiveData<List<Monster>> getMonsters() {
|
||||||
return mMonsters;
|
return mMonsters;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setMonsters(List<Monster> monsters) {
|
|
||||||
mMonsters.setValue(monsters);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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,10 +58,9 @@ 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;
|
||||||
return new Language(mName.getValue(), canSpeak);
|
return new Language(mName.getValue(), canSpeak);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,16 +10,16 @@ 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;
|
||||||
import com.majinnaibu.monstercards.databinding.FragmentEditLanguagesListItemBinding;
|
|
||||||
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 com.majinnaibu.monstercards.utils.ItemCallback;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
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;
|
||||||
private final ItemCallback mOnClick;
|
private final ItemCallback<Language> mOnClick;
|
||||||
private final int mTelepathyRange;
|
private final int mTelepathyRange;
|
||||||
private final String mUnderstandsBut;
|
private final String mUnderstandsBut;
|
||||||
private final Stepper.OnValueChangeListener mOnTelepathyRangeChanged;
|
private final Stepper.OnValueChangeListener mOnTelepathyRangeChanged;
|
||||||
@@ -29,7 +29,7 @@ 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<Language> onClick, int telepathyRange, Stepper.OnValueChangeListener telepathyRangeChangedListener, String understandsBut, TextWatcher understandsButChangedListener) {
|
||||||
mValues = items;
|
mValues = items;
|
||||||
mOnClick = onClick;
|
mOnClick = onClick;
|
||||||
mTelepathyRange = telepathyRange;
|
mTelepathyRange = telepathyRange;
|
||||||
@@ -44,7 +44,7 @@ public class EditLanguagesRecyclerViewAdapter extends RecyclerView.Adapter<Recyc
|
|||||||
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));
|
||||||
}
|
}
|
||||||
return new ItemViewHolder(FragmentEditLanguagesListItemBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false));
|
return new ItemViewHolder(com.majinnaibu.monstercards.databinding.SimpleListItemBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -62,7 +62,7 @@ public class EditLanguagesRecyclerViewAdapter extends RecyclerView.Adapter<Recyc
|
|||||||
itemViewHolder.mContentView.setText(itemViewHolder.mItem.getName());
|
itemViewHolder.mContentView.setText(itemViewHolder.mItem.getName());
|
||||||
itemViewHolder.itemView.setOnClickListener(view -> {
|
itemViewHolder.itemView.setOnClickListener(view -> {
|
||||||
if (mOnClick != null) {
|
if (mOnClick != null) {
|
||||||
mOnClick.onItemCallback(itemViewHolder.mItem);
|
mOnClick.onItem(itemViewHolder.mItem);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -81,10 +81,6 @@ public class EditLanguagesRecyclerViewAdapter extends RecyclerView.Adapter<Recyc
|
|||||||
return ITEM_VIEW_TYPE;
|
return ITEM_VIEW_TYPE;
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface ItemCallback {
|
|
||||||
void onItemCallback(Language language);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class HeaderViewHolder extends RecyclerView.ViewHolder {
|
public static class HeaderViewHolder extends RecyclerView.ViewHolder {
|
||||||
public final Stepper telepathy;
|
public final Stepper telepathy;
|
||||||
public final EditText understandsBut;
|
public final EditText understandsBut;
|
||||||
@@ -100,7 +96,7 @@ 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(@NonNull com.majinnaibu.monstercards.databinding.SimpleListItemBinding binding) {
|
||||||
super(binding.getRoot());
|
super(binding.getRoot());
|
||||||
mContentView = binding.content;
|
mContentView = binding.content;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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<>();
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ import android.widget.TextView;
|
|||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
import com.majinnaibu.monstercards.databinding.FragmentEditSkillsListItemBinding;
|
|
||||||
import com.majinnaibu.monstercards.models.Skill;
|
import com.majinnaibu.monstercards.models.Skill;
|
||||||
|
import com.majinnaibu.monstercards.utils.ItemCallback;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@@ -17,9 +17,9 @@ import java.util.List;
|
|||||||
*/
|
*/
|
||||||
public class EditSkillsRecyclerViewAdapter extends RecyclerView.Adapter<EditSkillsRecyclerViewAdapter.ViewHolder> {
|
public class EditSkillsRecyclerViewAdapter extends RecyclerView.Adapter<EditSkillsRecyclerViewAdapter.ViewHolder> {
|
||||||
private final List<Skill> mValues;
|
private final List<Skill> mValues;
|
||||||
private final ItemCallback mOnClick;
|
private final ItemCallback<Skill> mOnClick;
|
||||||
|
|
||||||
public EditSkillsRecyclerViewAdapter(List<Skill> items, ItemCallback onClick) {
|
public EditSkillsRecyclerViewAdapter(List<Skill> items, ItemCallback<Skill> onClick) {
|
||||||
mValues = items;
|
mValues = items;
|
||||||
mOnClick = onClick;
|
mOnClick = onClick;
|
||||||
}
|
}
|
||||||
@@ -27,7 +27,7 @@ public class EditSkillsRecyclerViewAdapter extends RecyclerView.Adapter<EditSkil
|
|||||||
@NonNull
|
@NonNull
|
||||||
@Override
|
@Override
|
||||||
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||||
return new ViewHolder(FragmentEditSkillsListItemBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false));
|
return new ViewHolder(com.majinnaibu.monstercards.databinding.SimpleListItemBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -36,7 +36,7 @@ public class EditSkillsRecyclerViewAdapter extends RecyclerView.Adapter<EditSkil
|
|||||||
holder.mContentView.setText(mValues.get(position).name);
|
holder.mContentView.setText(mValues.get(position).name);
|
||||||
holder.itemView.setOnClickListener(v -> {
|
holder.itemView.setOnClickListener(v -> {
|
||||||
if (mOnClick != null) {
|
if (mOnClick != null) {
|
||||||
mOnClick.onItemCallback(holder.mItem);
|
mOnClick.onItem(holder.mItem);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -46,15 +46,11 @@ public class EditSkillsRecyclerViewAdapter extends RecyclerView.Adapter<EditSkil
|
|||||||
return mValues.size();
|
return mValues.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface ItemCallback {
|
|
||||||
void onItemCallback(Skill skill);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class ViewHolder extends RecyclerView.ViewHolder {
|
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(@NonNull com.majinnaibu.monstercards.databinding.SimpleListItemBinding binding) {
|
||||||
super(binding.getRoot());
|
super(binding.getRoot());
|
||||||
mContentView = binding.content;
|
mContentView = binding.content;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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,9 +145,9 @@ 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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -7,15 +7,16 @@ import android.widget.TextView;
|
|||||||
import androidx.annotation.NonNull;
|
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.SimpleListItemBinding;
|
||||||
|
import com.majinnaibu.monstercards.utils.ItemCallback;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class EditStringsRecyclerViewAdapter extends RecyclerView.Adapter<EditStringsRecyclerViewAdapter.ViewHolder> {
|
public class EditStringsRecyclerViewAdapter extends RecyclerView.Adapter<EditStringsRecyclerViewAdapter.ViewHolder> {
|
||||||
private final List<String> mValues;
|
private final List<String> mValues;
|
||||||
private final ItemCallback mOnClick;
|
private final ItemCallback<String> mOnClick;
|
||||||
|
|
||||||
public EditStringsRecyclerViewAdapter(List<String> items, ItemCallback onClick) {
|
public EditStringsRecyclerViewAdapter(List<String> items, ItemCallback<String> onClick) {
|
||||||
mValues = items;
|
mValues = items;
|
||||||
mOnClick = onClick;
|
mOnClick = onClick;
|
||||||
}
|
}
|
||||||
@@ -23,7 +24,7 @@ public class EditStringsRecyclerViewAdapter extends RecyclerView.Adapter<EditStr
|
|||||||
@NonNull
|
@NonNull
|
||||||
@Override
|
@Override
|
||||||
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||||
return new ViewHolder(FragmentEditStringsListItemBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false));
|
return new ViewHolder(SimpleListItemBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -32,7 +33,7 @@ public class EditStringsRecyclerViewAdapter extends RecyclerView.Adapter<EditStr
|
|||||||
holder.mContentView.setText(mValues.get(position));
|
holder.mContentView.setText(mValues.get(position));
|
||||||
holder.itemView.setOnClickListener(v -> {
|
holder.itemView.setOnClickListener(v -> {
|
||||||
if (mOnClick != null) {
|
if (mOnClick != null) {
|
||||||
mOnClick.onItemCallback(holder.mItem);
|
mOnClick.onItem(holder.mItem);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -42,15 +43,11 @@ public class EditStringsRecyclerViewAdapter extends RecyclerView.Adapter<EditStr
|
|||||||
return mValues.size();
|
return mValues.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface ItemCallback {
|
|
||||||
void onItemCallback(String value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class ViewHolder extends RecyclerView.ViewHolder {
|
public static class ViewHolder extends RecyclerView.ViewHolder {
|
||||||
public final TextView mContentView;
|
public final TextView mContentView;
|
||||||
public String mItem;
|
public String mItem;
|
||||||
|
|
||||||
public ViewHolder(@NonNull FragmentEditStringsListItemBinding binding) {
|
public ViewHolder(@NonNull SimpleListItemBinding binding) {
|
||||||
super(binding.getRoot());
|
super(binding.getRoot());
|
||||||
mContentView = binding.content;
|
mContentView = binding.content;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -9,8 +9,9 @@ import androidx.recyclerview.widget.DiffUtil;
|
|||||||
import androidx.recyclerview.widget.ListAdapter;
|
import androidx.recyclerview.widget.ListAdapter;
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
import com.majinnaibu.monstercards.databinding.FragmentEditTraitsListItemBinding;
|
import com.majinnaibu.monstercards.databinding.SimpleListItemBinding;
|
||||||
import com.majinnaibu.monstercards.models.Trait;
|
import com.majinnaibu.monstercards.models.Trait;
|
||||||
|
import com.majinnaibu.monstercards.utils.ItemCallback;
|
||||||
|
|
||||||
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>() {
|
||||||
@@ -25,9 +26,9 @@ public class EditTraitsRecyclerViewAdapter extends ListAdapter<Trait, EditTraits
|
|||||||
return oldItem.equals(newItem);
|
return oldItem.equals(newItem);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
private final ItemCallback mOnClick;
|
private final ItemCallback<Trait> mOnClick;
|
||||||
|
|
||||||
protected EditTraitsRecyclerViewAdapter(ItemCallback onClick) {
|
protected EditTraitsRecyclerViewAdapter(ItemCallback<Trait> onClick) {
|
||||||
super(DIFF_CALLBACK);
|
super(DIFF_CALLBACK);
|
||||||
mOnClick = onClick;
|
mOnClick = onClick;
|
||||||
}
|
}
|
||||||
@@ -35,7 +36,7 @@ public class EditTraitsRecyclerViewAdapter extends ListAdapter<Trait, EditTraits
|
|||||||
@NonNull
|
@NonNull
|
||||||
@Override
|
@Override
|
||||||
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||||
return new ViewHolder(FragmentEditTraitsListItemBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false));
|
return new ViewHolder(SimpleListItemBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -44,20 +45,16 @@ public class EditTraitsRecyclerViewAdapter extends ListAdapter<Trait, EditTraits
|
|||||||
holder.mContentView.setText(holder.mItem.name);
|
holder.mContentView.setText(holder.mItem.name);
|
||||||
holder.itemView.setOnClickListener(v -> {
|
holder.itemView.setOnClickListener(v -> {
|
||||||
if (mOnClick != null) {
|
if (mOnClick != null) {
|
||||||
mOnClick.onItemCallback(holder.mItem);
|
mOnClick.onItem(holder.mItem);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface ItemCallback {
|
|
||||||
void onItemCallback(Trait trait);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class ViewHolder extends RecyclerView.ViewHolder {
|
public static class ViewHolder extends RecyclerView.ViewHolder {
|
||||||
public final TextView mContentView;
|
public final TextView mContentView;
|
||||||
public Trait mItem;
|
public Trait mItem;
|
||||||
|
|
||||||
public ViewHolder(@NonNull FragmentEditTraitsListItemBinding binding) {
|
public ViewHolder(@NonNull SimpleListItemBinding binding) {
|
||||||
super(binding.getRoot());
|
super(binding.getRoot());
|
||||||
mContentView = binding.content;
|
mContentView = binding.content;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ import android.view.View;
|
|||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.lifecycle.LiveData;
|
||||||
|
import androidx.lifecycle.ViewModelProvider;
|
||||||
import androidx.navigation.NavDirections;
|
import androidx.navigation.NavDirections;
|
||||||
import androidx.navigation.Navigation;
|
import androidx.navigation.Navigation;
|
||||||
import androidx.recyclerview.widget.DividerItemDecoration;
|
import androidx.recyclerview.widget.DividerItemDecoration;
|
||||||
@@ -18,65 +20,52 @@ import com.google.android.material.floatingactionbutton.FloatingActionButton;
|
|||||||
import com.google.android.material.snackbar.Snackbar;
|
import com.google.android.material.snackbar.Snackbar;
|
||||||
import com.majinnaibu.monstercards.R;
|
import com.majinnaibu.monstercards.R;
|
||||||
import com.majinnaibu.monstercards.data.MonsterRepository;
|
import com.majinnaibu.monstercards.data.MonsterRepository;
|
||||||
|
import com.majinnaibu.monstercards.databinding.FragmentLibraryBinding;
|
||||||
import com.majinnaibu.monstercards.models.Monster;
|
import com.majinnaibu.monstercards.models.Monster;
|
||||||
import com.majinnaibu.monstercards.ui.shared.MCFragment;
|
import com.majinnaibu.monstercards.ui.shared.MCFragment;
|
||||||
import com.majinnaibu.monstercards.ui.shared.SwipeToDeleteCallback;
|
import com.majinnaibu.monstercards.ui.shared.SwipeToDeleteCallback;
|
||||||
import com.majinnaibu.monstercards.utils.Logger;
|
import com.majinnaibu.monstercards.utils.Logger;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.List;
|
||||||
|
|
||||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
|
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
|
||||||
import io.reactivex.rxjava3.observers.DisposableCompletableObserver;
|
import io.reactivex.rxjava3.observers.DisposableCompletableObserver;
|
||||||
import io.reactivex.rxjava3.schedulers.Schedulers;
|
import io.reactivex.rxjava3.schedulers.Schedulers;
|
||||||
|
|
||||||
public class LibraryFragment extends MCFragment {
|
public class LibraryFragment extends MCFragment {
|
||||||
|
private LibraryViewModel mViewModel;
|
||||||
|
private ViewHolder mHolder;
|
||||||
|
private LibraryRecyclerViewAdapter mAdapter;
|
||||||
|
|
||||||
public View onCreateView(@NonNull LayoutInflater inflater,
|
@Override
|
||||||
ViewGroup container, Bundle savedInstanceState) {
|
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||||
View root = inflater.inflate(R.layout.fragment_library, container, false);
|
mViewModel = new ViewModelProvider(this).get(LibraryViewModel.class);
|
||||||
|
FragmentLibraryBinding binding = FragmentLibraryBinding.inflate(inflater, container, false);
|
||||||
FloatingActionButton fab = root.findViewById(R.id.fab);
|
mHolder = new ViewHolder(binding);
|
||||||
assert fab != null;
|
// TODO: set the title with setTitle(...)
|
||||||
setupAddMonsterButton(fab);
|
setupAddMonsterButton(mHolder.addButton);
|
||||||
|
setupMonsterList(mHolder.list);
|
||||||
final RecyclerView recyclerView = root.findViewById(R.id.monster_list);
|
return binding.getRoot();
|
||||||
assert recyclerView != null;
|
|
||||||
setupRecyclerView(recyclerView);
|
|
||||||
|
|
||||||
return root;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setupRecyclerView(@NonNull RecyclerView recyclerView) {
|
private void setupMonsterList(@NonNull RecyclerView recyclerView) {
|
||||||
Context context = requireContext();
|
Context context = requireContext();
|
||||||
MonsterRepository repository = this.getMonsterRepository();
|
|
||||||
|
|
||||||
LibraryRecyclerViewAdapter adapter = new LibraryRecyclerViewAdapter(
|
|
||||||
context,
|
|
||||||
repository.getMonsters(),
|
|
||||||
(monster) -> navigateToMonsterDetail(monster.id),
|
|
||||||
(monster) -> repository
|
|
||||||
.deleteMonster(monster)
|
|
||||||
.subscribeOn(Schedulers.io())
|
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
|
||||||
.subscribe(new DisposableCompletableObserver() {
|
|
||||||
@Override
|
|
||||||
public void onComplete() {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onError(@io.reactivex.rxjava3.annotations.NonNull Throwable e) {
|
|
||||||
Logger.logError(e);
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
recyclerView.setAdapter(adapter);
|
|
||||||
|
|
||||||
LinearLayoutManager layoutManager = new LinearLayoutManager(context);
|
LinearLayoutManager layoutManager = new LinearLayoutManager(context);
|
||||||
recyclerView.setLayoutManager(layoutManager);
|
recyclerView.setLayoutManager(layoutManager);
|
||||||
|
|
||||||
|
LiveData<List<Monster>> monsterData = mViewModel.getMonsters();
|
||||||
|
mAdapter = new LibraryRecyclerViewAdapter(this::navigateToMonsterDetail);
|
||||||
|
if (monsterData != null) {
|
||||||
|
monsterData.observe(getViewLifecycleOwner(), monsters -> mAdapter.submitList(monsters));
|
||||||
|
}
|
||||||
|
recyclerView.setAdapter(mAdapter);
|
||||||
DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(context, layoutManager.getOrientation());
|
DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(context, layoutManager.getOrientation());
|
||||||
recyclerView.addItemDecoration(dividerItemDecoration);
|
recyclerView.addItemDecoration(dividerItemDecoration);
|
||||||
|
|
||||||
ItemTouchHelper itemTouchHelper = new ItemTouchHelper(new SwipeToDeleteCallback(requireContext(), (position, direction) -> adapter.deleteItem(position), null));
|
ItemTouchHelper itemTouchHelper = new ItemTouchHelper(new SwipeToDeleteCallback(
|
||||||
|
requireContext(),
|
||||||
|
(position, direction) -> mViewModel.removeMonster(position),
|
||||||
|
null));
|
||||||
itemTouchHelper.attachToRecyclerView(recyclerView);
|
itemTouchHelper.attachToRecyclerView(recyclerView);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -98,7 +87,7 @@ public class LibraryFragment extends MCFragment {
|
|||||||
view,
|
view,
|
||||||
getString(R.string.snackbar_monster_created, monster.name),
|
getString(R.string.snackbar_monster_created, monster.name),
|
||||||
Snackbar.LENGTH_LONG)
|
Snackbar.LENGTH_LONG)
|
||||||
.setAction("Action", (_view) -> navigateToMonsterDetail(monster.id))
|
.setAction("Action", (_view) -> navigateToMonsterDetail(monster))
|
||||||
.show();
|
.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -114,8 +103,22 @@ public class LibraryFragment extends MCFragment {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void navigateToMonsterDetail(@NonNull UUID monsterId) {
|
protected void navigateToMonsterDetail(Monster monster) {
|
||||||
NavDirections action = LibraryFragmentDirections.actionNavigationLibraryToNavigationMonster(monsterId.toString());
|
if (monster != null) {
|
||||||
Navigation.findNavController(requireView()).navigate(action);
|
NavDirections action = LibraryFragmentDirections.actionNavigationLibraryToNavigationMonster(monster.id.toString());
|
||||||
|
Navigation.findNavController(requireView()).navigate(action);
|
||||||
|
} else {
|
||||||
|
Logger.logError("Can't navigate to MonsterDetail without a monster.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class ViewHolder {
|
||||||
|
final FloatingActionButton addButton;
|
||||||
|
final RecyclerView list;
|
||||||
|
|
||||||
|
public ViewHolder(FragmentLibraryBinding binding) {
|
||||||
|
addButton = binding.fab;
|
||||||
|
list = binding.monsterList;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,115 +1,53 @@
|
|||||||
package com.majinnaibu.monstercards.ui.library;
|
package com.majinnaibu.monstercards.ui.library;
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.TextView;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
import androidx.recyclerview.widget.DiffUtil;
|
||||||
|
import androidx.recyclerview.widget.ListAdapter;
|
||||||
|
|
||||||
import com.majinnaibu.monstercards.R;
|
import com.majinnaibu.monstercards.databinding.SimpleListItemBinding;
|
||||||
import com.majinnaibu.monstercards.models.Monster;
|
import com.majinnaibu.monstercards.models.Monster;
|
||||||
|
import com.majinnaibu.monstercards.ui.shared.SimpleListItemViewHolder;
|
||||||
|
import com.majinnaibu.monstercards.utils.ItemCallback;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
public class LibraryRecyclerViewAdapter extends ListAdapter<Monster, SimpleListItemViewHolder<Monster>> {
|
||||||
import java.util.List;
|
private static final DiffUtil.ItemCallback<Monster> DIFF_CALLBACK = new DiffUtil.ItemCallback<Monster>() {
|
||||||
|
|
||||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
|
|
||||||
import io.reactivex.rxjava3.core.Flowable;
|
|
||||||
import io.reactivex.rxjava3.disposables.Disposable;
|
|
||||||
import io.reactivex.rxjava3.schedulers.Schedulers;
|
|
||||||
|
|
||||||
public class LibraryRecyclerViewAdapter extends RecyclerView.Adapter<LibraryRecyclerViewAdapter.ViewHolder> {
|
|
||||||
private final Context mContext;
|
|
||||||
private final ItemCallback mOnDelete;
|
|
||||||
private final ItemCallback mOnClick;
|
|
||||||
private final Flowable<List<Monster>> mItemsObservable;
|
|
||||||
private final View.OnClickListener mOnClickListener = new View.OnClickListener() {
|
|
||||||
@Override
|
@Override
|
||||||
public void onClick(@NonNull View view) {
|
public boolean areItemsTheSame(@NonNull Monster oldItem, @NonNull Monster newItem) {
|
||||||
Monster monster = (Monster) view.getTag();
|
return Monster.areItemsTheSame(oldItem, newItem);
|
||||||
if (mOnClick != null) {
|
}
|
||||||
mOnClick.onItemCallback(monster);
|
|
||||||
}
|
@Override
|
||||||
|
public boolean areContentsTheSame(@NonNull Monster oldItem, @NonNull Monster newItem) {
|
||||||
|
return Monster.areContentsTheSame(oldItem, newItem);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
private List<Monster> mValues;
|
private final ItemCallback<Monster> mOnClick;
|
||||||
private Disposable mDisposable;
|
|
||||||
|
|
||||||
public LibraryRecyclerViewAdapter(Context context,
|
public LibraryRecyclerViewAdapter(ItemCallback<Monster> onClick) {
|
||||||
Flowable<List<Monster>> itemsObservable,
|
super(DIFF_CALLBACK);
|
||||||
ItemCallback onClick,
|
|
||||||
ItemCallback onDelete) {
|
|
||||||
mItemsObservable = itemsObservable;
|
|
||||||
mValues = new ArrayList<>();
|
|
||||||
mContext = context;
|
|
||||||
mOnDelete = onDelete;
|
|
||||||
mOnClick = onClick;
|
mOnClick = onClick;
|
||||||
mDisposable = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@NonNull
|
@NonNull
|
||||||
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
public SimpleListItemViewHolder<Monster> onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||||
View view = LayoutInflater.from(parent.getContext())
|
SimpleListItemBinding binding = SimpleListItemBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false);
|
||||||
.inflate(R.layout.monster_list_content, parent, false);
|
return new SimpleListItemViewHolder<>(binding);
|
||||||
return new ViewHolder(view);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBindViewHolder(final @NonNull ViewHolder holder, int position) {
|
public void onBindViewHolder(final @NonNull SimpleListItemViewHolder<Monster> holder, int position) {
|
||||||
Monster monster = mValues.get(position);
|
Monster monster = getItem(position);
|
||||||
holder.mContentView.setText(monster.name);
|
holder.item = monster;
|
||||||
|
holder.contentView.setText(monster.name);
|
||||||
holder.itemView.setTag(monster);
|
holder.itemView.setTag(monster);
|
||||||
holder.itemView.setOnClickListener(mOnClickListener);
|
holder.itemView.setOnClickListener(v -> {
|
||||||
}
|
if (mOnClick != null) {
|
||||||
|
mOnClick.onItem(holder.item);
|
||||||
@Override
|
}
|
||||||
public int getItemCount() {
|
});
|
||||||
return mValues.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Context getContext() {
|
|
||||||
return mContext;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onAttachedToRecyclerView(@NonNull RecyclerView recyclerView) {
|
|
||||||
super.onAttachedToRecyclerView(recyclerView);
|
|
||||||
// TODO: consider moving this subscription out of the adapter and make the subscriber call setItems on the adapter
|
|
||||||
mDisposable = mItemsObservable
|
|
||||||
.subscribeOn(Schedulers.io())
|
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
|
||||||
.subscribe(monsters -> {
|
|
||||||
mValues = monsters;
|
|
||||||
notifyDataSetChanged();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onDetachedFromRecyclerView(@NonNull RecyclerView recyclerView) {
|
|
||||||
super.onDetachedFromRecyclerView(recyclerView);
|
|
||||||
mDisposable.dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void deleteItem(int position) {
|
|
||||||
if (mOnDelete != null) {
|
|
||||||
Monster monster = mValues.get(position);
|
|
||||||
mOnDelete.onItemCallback(monster);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface ItemCallback {
|
|
||||||
void onItemCallback(Monster monster);
|
|
||||||
}
|
|
||||||
|
|
||||||
static class ViewHolder extends RecyclerView.ViewHolder {
|
|
||||||
final TextView mContentView;
|
|
||||||
|
|
||||||
ViewHolder(View view) {
|
|
||||||
super(view);
|
|
||||||
mContentView = view.findViewById(R.id.content);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,74 @@
|
|||||||
|
package com.majinnaibu.monstercards.ui.library;
|
||||||
|
|
||||||
|
import android.app.Application;
|
||||||
|
|
||||||
|
import androidx.lifecycle.AndroidViewModel;
|
||||||
|
import androidx.lifecycle.LiveData;
|
||||||
|
import androidx.lifecycle.MutableLiveData;
|
||||||
|
|
||||||
|
import com.majinnaibu.monstercards.AppDatabase;
|
||||||
|
import com.majinnaibu.monstercards.models.Monster;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
|
||||||
|
import io.reactivex.rxjava3.annotations.NonNull;
|
||||||
|
import io.reactivex.rxjava3.observers.DisposableCompletableObserver;
|
||||||
|
import io.reactivex.rxjava3.schedulers.Schedulers;
|
||||||
|
import io.reactivex.rxjava3.subscribers.DisposableSubscriber;
|
||||||
|
|
||||||
|
public class LibraryViewModel extends AndroidViewModel {
|
||||||
|
private final AppDatabase mDB;
|
||||||
|
private final MutableLiveData<List<Monster>> mMonsters;
|
||||||
|
|
||||||
|
public LibraryViewModel(Application application) {
|
||||||
|
super(application);
|
||||||
|
mDB = AppDatabase.getInstance(application);
|
||||||
|
mMonsters = new MutableLiveData<>(new ArrayList<>());
|
||||||
|
mDB.monsterDAO()
|
||||||
|
.getAll()
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.subscribeOn(Schedulers.io())
|
||||||
|
.subscribe(new DisposableSubscriber<List<Monster>>() {
|
||||||
|
@Override
|
||||||
|
public void onNext(List<Monster> monsters) {
|
||||||
|
mMonsters.setValue(monsters);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onError(Throwable t) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onComplete() {
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public LiveData<List<Monster>> getMonsters() {
|
||||||
|
return mMonsters;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeMonster(int position) {
|
||||||
|
Monster monster = mMonsters.getValue().get(position);
|
||||||
|
mDB.monsterDAO()
|
||||||
|
.delete(monster)
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.subscribeOn(Schedulers.io())
|
||||||
|
.subscribe(new DisposableCompletableObserver() {
|
||||||
|
@Override
|
||||||
|
public void onComplete() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onError(@NonNull Throwable e) {
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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,98 +63,177 @@ 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));
|
final TextView monsterSkills = root.findViewById(R.id.skills);
|
||||||
mViewModel.getHitPoints().observe(getViewLifecycleOwner(), hitPoints -> setupLabeledTextView(mHolder.hitPoints, hitPoints, R.string.label_hit_points));
|
monsterDetailViewModel.getSkills().observe(getViewLifecycleOwner(), skills -> {
|
||||||
mViewModel.getSpeed().observe(getViewLifecycleOwner(), speed -> setupLabeledTextView(mHolder.speed, speed, R.string.label_speed));
|
if (StringHelper.isNullOrEmpty(skills)) {
|
||||||
mViewModel.getStrength().observe(getViewLifecycleOwner(), mHolder.strength::setText);
|
monsterSkills.setVisibility(View.GONE);
|
||||||
mViewModel.getDexterity().observe(getViewLifecycleOwner(), mHolder.dexterity::setText);
|
} else {
|
||||||
mViewModel.getConstitution().observe(getViewLifecycleOwner(), mHolder.constitution::setText);
|
monsterSkills.setVisibility(View.VISIBLE);
|
||||||
mViewModel.getIntelligence().observe(getViewLifecycleOwner(), mHolder.intelligence::setText);
|
}
|
||||||
mViewModel.getWisdom().observe(getViewLifecycleOwner(), mHolder.wisdom::setText);
|
monsterSkills.setText(Html.fromHtml("<b>Skills</b> " + skills));
|
||||||
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));
|
final TextView monsterDamageVulnerabilities = root.findViewById(R.id.damage_vulnerabilities);
|
||||||
mViewModel.getDamageVulnerabilities().observe(getViewLifecycleOwner(), damageTypes -> setupOptionalTextView(mHolder.damageVulnerabilities, damageTypes, R.string.label_damage_vulnerabilities));
|
monsterDetailViewModel.getDamageVulnerabilities().observe(getViewLifecycleOwner(), damageType -> {
|
||||||
mViewModel.getDamageResistances().observe(getViewLifecycleOwner(), damageTypes -> setupOptionalTextView(mHolder.damageResistances, damageTypes, R.string.label_damage_resistances));
|
if (StringHelper.isNullOrEmpty(damageType)) {
|
||||||
mViewModel.getDamageImmunities().observe(getViewLifecycleOwner(), damageTypes -> setupOptionalTextView(mHolder.damageImmunities, damageTypes, R.string.label_damage_immunities));
|
monsterDamageVulnerabilities.setVisibility(View.GONE);
|
||||||
mViewModel.getConditionImmunities().observe(getViewLifecycleOwner(), conditionImmunities -> setupOptionalTextView(mHolder.conditionImmunities, conditionImmunities, R.string.label_condition_immunities));
|
} else {
|
||||||
mViewModel.getSenses().observe(getViewLifecycleOwner(), senses -> setupOptionalTextView(mHolder.senses, senses, R.string.label_senses));
|
monsterDamageVulnerabilities.setVisibility(View.VISIBLE);
|
||||||
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));
|
monsterDamageVulnerabilities.setText(Html.fromHtml("<b>Damage Vulnerabilities</b> " + damageType));
|
||||||
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));
|
final TextView monsterDamageResistances = root.findViewById(R.id.damage_resistances);
|
||||||
mViewModel.getRegionalEffects().observe(getViewLifecycleOwner(), regionalEffects -> setupTraitList(mHolder.regionalEffects, regionalEffects, mHolder.regionalEffects_label, mHolder.regionalEffects_divider));
|
monsterDetailViewModel.getDamageResistances().observe(getViewLifecycleOwner(), damageType -> {
|
||||||
mViewModel.getLairActions().observe(getViewLifecycleOwner(), lairActions -> setupTraitList(mHolder.lairActions, lairActions, mHolder.lairActions_label, mHolder.lairActions_divider));
|
if (StringHelper.isNullOrEmpty(damageType)) {
|
||||||
mViewModel.getLegendaryActions().observe(getViewLifecycleOwner(), legendaryActions -> setupTraitList(mHolder.legendaryActions, legendaryActions, mHolder.legendaryActions_label, mHolder.legendaryActions_divider));
|
monsterDamageResistances.setVisibility(View.GONE);
|
||||||
|
} else {
|
||||||
|
monsterDamageResistances.setVisibility(View.VISIBLE);
|
||||||
|
}
|
||||||
|
monsterDamageResistances.setText(Html.fromHtml("<b>Damage Resistances</b> " + damageType));
|
||||||
|
});
|
||||||
|
|
||||||
|
final TextView monsterDamageImmunities = root.findViewById(R.id.damage_immunities);
|
||||||
|
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();
|
||||||
|
DisplayMetrics displayMetrics = null;
|
||||||
|
if (context != null) {
|
||||||
|
Resources resources = context.getResources();
|
||||||
|
if (resources != null) {
|
||||||
|
displayMetrics = resources.getDisplayMetrics();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
monsterAbilities.removeAllViews();
|
||||||
|
if (abilities != null) {
|
||||||
|
for (String ability : abilities) {
|
||||||
|
TextView tvAbility = new TextView(context);
|
||||||
|
// 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
|
||||||
|
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)));
|
||||||
|
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
|
||||||
|
layoutParams.topMargin = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 8, displayMetrics);
|
||||||
|
tvAction.setLayoutParams(layoutParams);
|
||||||
|
monsterActions.addView(tvAction);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// TODO: add lair actions, legendary actions, reactions, and regional actions
|
||||||
|
|
||||||
return root;
|
return root;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setupLabeledTextView(@NonNull TextView view, String text, int titleId) {
|
|
||||||
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 {
|
|
||||||
root.setVisibility(View.VISIBLE);
|
|
||||||
}
|
|
||||||
Spanned formatted;
|
|
||||||
if (StringHelper.isNullOrEmpty(title)) {
|
|
||||||
formatted = Html.fromHtml(text);
|
|
||||||
} else {
|
|
||||||
formatted = Html.fromHtml(String.format("<b>%s</b> %s", title, text));
|
|
||||||
}
|
|
||||||
root.setText(formatted);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setupTraitList(@NonNull LinearLayout root, @NonNull List<String> traits) {
|
|
||||||
setupTraitList(root, traits, null, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setupTraitList(@NonNull LinearLayout root, @NonNull List<String> traits, View label, View divider) {
|
|
||||||
int visibility = traits.size() > 0 ? View.VISIBLE : View.GONE;
|
|
||||||
Context context = getContext();
|
|
||||||
DisplayMetrics displayMetrics = null;
|
|
||||||
if (context != null) {
|
|
||||||
Resources resources = context.getResources();
|
|
||||||
if (resources != null) {
|
|
||||||
displayMetrics = resources.getDisplayMetrics();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
root.removeAllViews();
|
|
||||||
for (String action : traits) {
|
|
||||||
TextView tvAction = new TextView(getContext());
|
|
||||||
// TODO: Handle multiline block quotes specially so they stay multiline.
|
|
||||||
// TODO: Replace QuoteSpans in the result of fromHtml with something like this https://stackoverflow.com/questions/7717567/how-to-style-blockquotes-in-android-textviews to make them indent as expected
|
|
||||||
tvAction.setText(Html.fromHtml(CommonMarkHelper.toHtml(action)));
|
|
||||||
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
|
|
||||||
layoutParams.topMargin = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 8, displayMetrics);
|
|
||||||
tvAction.setLayoutParams(layoutParams);
|
|
||||||
root.addView(tvAction);
|
|
||||||
}
|
|
||||||
root.setVisibility(visibility);
|
|
||||||
if (label != null) {
|
|
||||||
label.setVisibility(visibility);
|
|
||||||
}
|
|
||||||
if (divider != null) {
|
|
||||||
divider.setVisibility(visibility);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) {
|
public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) {
|
||||||
inflater.inflate(R.menu.monster_detail_menu, menu);
|
inflater.inflate(R.menu.monster_detail_menu, menu);
|
||||||
@@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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());
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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());
|
||||||
|
|||||||
@@ -1,34 +1,49 @@
|
|||||||
package com.majinnaibu.monstercards.ui.search;
|
package com.majinnaibu.monstercards.ui.search;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.text.Editable;
|
import android.text.Editable;
|
||||||
import android.text.TextWatcher;
|
import android.text.TextWatcher;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.EditText;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.lifecycle.LiveData;
|
||||||
|
import androidx.lifecycle.ViewModelProvider;
|
||||||
|
import androidx.navigation.NavDirections;
|
||||||
|
import androidx.navigation.Navigation;
|
||||||
|
import androidx.recyclerview.widget.DividerItemDecoration;
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
import com.majinnaibu.monstercards.R;
|
import com.majinnaibu.monstercards.databinding.FragmentSearchBinding;
|
||||||
import com.majinnaibu.monstercards.data.MonsterRepository;
|
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 java.util.List;
|
||||||
|
|
||||||
public class SearchFragment extends MCFragment {
|
public class SearchFragment extends MCFragment {
|
||||||
|
private SearchViewModel mViewModel;
|
||||||
|
private ViewHolder mHolder;
|
||||||
|
private SearchResultsRecyclerViewAdapter mAdapter;
|
||||||
|
|
||||||
public View onCreateView(@NonNull LayoutInflater inflater,
|
@Override
|
||||||
ViewGroup container, Bundle savedInstanceState) {
|
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||||
View root = inflater.inflate(R.layout.fragment_search, container, false);
|
mViewModel = new ViewModelProvider(this).get(SearchViewModel.class);
|
||||||
MonsterRepository repository = this.getMonsterRepository();
|
FragmentSearchBinding binding = FragmentSearchBinding.inflate(inflater, container, false);
|
||||||
SearchResultsRecyclerViewAdapter adapter = new SearchResultsRecyclerViewAdapter(repository, null);
|
mHolder = new ViewHolder(binding);
|
||||||
final RecyclerView recyclerView = root.findViewById(R.id.monster_list);
|
// TODO: set the title with setTitle(...)
|
||||||
assert recyclerView != null;
|
setupMonsterList(binding.monsterList);
|
||||||
setupRecyclerView(recyclerView, adapter);
|
setupFilterBox(binding.searchQuery);
|
||||||
|
return binding.getRoot();
|
||||||
|
}
|
||||||
|
|
||||||
final TextView textView = root.findViewById(R.id.search_query);
|
private void setupFilterBox(@NonNull TextView textBox) {
|
||||||
textView.addTextChangedListener(new TextWatcher() {
|
textBox.addTextChangedListener(new TextWatcher() {
|
||||||
@Override
|
@Override
|
||||||
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
|
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
|
||||||
}
|
}
|
||||||
@@ -39,15 +54,42 @@ public class SearchFragment extends MCFragment {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void afterTextChanged(Editable editable) {
|
public void afterTextChanged(Editable editable) {
|
||||||
adapter.doSearch(textView.getText().toString());
|
mViewModel.setFilterText(textBox.getText().toString());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return root;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setupRecyclerView(@NonNull RecyclerView recyclerView, @NonNull SearchResultsRecyclerViewAdapter adapter) {
|
private void setupMonsterList(@NonNull RecyclerView recyclerView) {
|
||||||
recyclerView.setAdapter(adapter);
|
Context context = requireContext();
|
||||||
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
|
LinearLayoutManager layoutManager = new LinearLayoutManager(context);
|
||||||
|
recyclerView.setLayoutManager(layoutManager);
|
||||||
|
|
||||||
|
LiveData<List<Monster>> monsterData = mViewModel.getMatchedMonsters();
|
||||||
|
mAdapter = new SearchResultsRecyclerViewAdapter(this::navigateToMonsterDetail);
|
||||||
|
if (monsterData != null) {
|
||||||
|
monsterData.observe(getViewLifecycleOwner(), monsters -> mAdapter.submitList(monsters));
|
||||||
|
}
|
||||||
|
recyclerView.setAdapter(mAdapter);
|
||||||
|
DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(context, layoutManager.getOrientation());
|
||||||
|
recyclerView.addItemDecoration(dividerItemDecoration);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void navigateToMonsterDetail(Monster monster) {
|
||||||
|
if (monster == null) {
|
||||||
|
NavDirections action = SearchFragmentDirections.actionNavigationSearchToNavigationMonster(monster.id.toString());
|
||||||
|
Navigation.findNavController(requireView()).navigate(action);
|
||||||
|
} else {
|
||||||
|
Logger.logError("Can't navigate to MonsterDetail without a monster.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class ViewHolder {
|
||||||
|
final RecyclerView monsterList;
|
||||||
|
final EditText filterQuery;
|
||||||
|
|
||||||
|
public ViewHolder(FragmentSearchBinding binding) {
|
||||||
|
monsterList = binding.monsterList;
|
||||||
|
filterQuery = binding.searchQuery;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,90 +1,52 @@
|
|||||||
package com.majinnaibu.monstercards.ui.search;
|
package com.majinnaibu.monstercards.ui.search;
|
||||||
|
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.TextView;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
import androidx.recyclerview.widget.DiffUtil;
|
||||||
|
import androidx.recyclerview.widget.ListAdapter;
|
||||||
|
|
||||||
import com.majinnaibu.monstercards.R;
|
import com.majinnaibu.monstercards.databinding.SimpleListItemBinding;
|
||||||
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.ui.shared.SimpleListItemViewHolder;
|
||||||
|
import com.majinnaibu.monstercards.utils.ItemCallback;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
public class SearchResultsRecyclerViewAdapter extends ListAdapter<Monster, SimpleListItemViewHolder<Monster>> {
|
||||||
import java.util.List;
|
private static final DiffUtil.ItemCallback<Monster> DIFF_CALLBACK = new DiffUtil.ItemCallback<Monster>() {
|
||||||
|
@Override
|
||||||
import io.reactivex.rxjava3.core.Flowable;
|
public boolean areItemsTheSame(@NonNull Monster oldItem, @NonNull Monster newItem) {
|
||||||
import io.reactivex.rxjava3.disposables.Disposable;
|
return Monster.areItemsTheSame(oldItem, newItem);
|
||||||
|
|
||||||
public class SearchResultsRecyclerViewAdapter extends RecyclerView.Adapter<SearchResultsRecyclerViewAdapter.ViewHolder> {
|
|
||||||
private final MonsterRepository mRepository;
|
|
||||||
private final ItemCallback mOnClickHandler;
|
|
||||||
private String mSearchText;
|
|
||||||
private List<Monster> mValues;
|
|
||||||
private Disposable mSubscriptionHandler;
|
|
||||||
|
|
||||||
public SearchResultsRecyclerViewAdapter(MonsterRepository repository,
|
|
||||||
ItemCallback onClick) {
|
|
||||||
mRepository = repository;
|
|
||||||
mSearchText = "";
|
|
||||||
mValues = new ArrayList<>();
|
|
||||||
mOnClickHandler = onClick;
|
|
||||||
mSubscriptionHandler = null;
|
|
||||||
|
|
||||||
doSearch(mSearchText);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void doSearch(String searchText) {
|
|
||||||
if (mSubscriptionHandler != null && !mSubscriptionHandler.isDisposed()) {
|
|
||||||
mSubscriptionHandler.dispose();
|
|
||||||
}
|
}
|
||||||
mSearchText = searchText;
|
|
||||||
Flowable<List<Monster>> foundMonsters = mRepository.searchMonsters(mSearchText);
|
@Override
|
||||||
mSubscriptionHandler = foundMonsters.subscribe(monsters -> {
|
public boolean areContentsTheSame(@NonNull Monster oldItem, @NonNull Monster newItem) {
|
||||||
mValues = monsters;
|
return Monster.areContentsTheSame(oldItem, newItem);
|
||||||
notifyDataSetChanged();
|
}
|
||||||
},
|
};
|
||||||
throwable -> Logger.logError("Error performing search", throwable));
|
private final ItemCallback<Monster> mOnClick;
|
||||||
|
|
||||||
|
public SearchResultsRecyclerViewAdapter(ItemCallback<Monster> onClick) {
|
||||||
|
super(DIFF_CALLBACK);
|
||||||
|
mOnClick = onClick;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
@Override
|
@Override
|
||||||
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
public SimpleListItemViewHolder<Monster> onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||||
View view = LayoutInflater.from(parent.getContext())
|
SimpleListItemBinding binding = SimpleListItemBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false);
|
||||||
.inflate(R.layout.monster_list_content, parent, false);
|
return new SimpleListItemViewHolder<>(binding);
|
||||||
return new ViewHolder(view);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBindViewHolder(@NonNull final ViewHolder holder, int position) {
|
public void onBindViewHolder(@NonNull final SimpleListItemViewHolder<Monster> holder, int position) {
|
||||||
Monster monster = mValues.get(position);
|
Monster monster = getItem(position);
|
||||||
holder.mContentView.setText(monster.name);
|
holder.item = monster;
|
||||||
holder.itemView.setTag(monster);
|
holder.contentView.setText(monster.name);
|
||||||
holder.itemView.setOnClickListener(view -> {
|
holder.itemView.setOnClickListener(view -> {
|
||||||
if (mOnClickHandler != null) {
|
if (mOnClick != null) {
|
||||||
mOnClickHandler.onItem(monster);
|
mOnClick.onItem(holder.item);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getItemCount() {
|
|
||||||
return mValues.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface ItemCallback {
|
|
||||||
void onItem(Monster monster);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class ViewHolder extends RecyclerView.ViewHolder {
|
|
||||||
final TextView mContentView;
|
|
||||||
|
|
||||||
ViewHolder(View view) {
|
|
||||||
super(view);
|
|
||||||
mContentView = view.findViewById(R.id.content);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,118 @@
|
|||||||
|
package com.majinnaibu.monstercards.ui.search;
|
||||||
|
|
||||||
|
import android.app.Application;
|
||||||
|
|
||||||
|
import androidx.lifecycle.AndroidViewModel;
|
||||||
|
import androidx.lifecycle.LiveData;
|
||||||
|
import androidx.lifecycle.MediatorLiveData;
|
||||||
|
import androidx.lifecycle.MutableLiveData;
|
||||||
|
|
||||||
|
import com.majinnaibu.monstercards.AppDatabase;
|
||||||
|
import com.majinnaibu.monstercards.helpers.StringHelper;
|
||||||
|
import com.majinnaibu.monstercards.models.Monster;
|
||||||
|
import com.majinnaibu.monstercards.utils.Logger;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
|
||||||
|
import io.reactivex.rxjava3.schedulers.Schedulers;
|
||||||
|
import io.reactivex.rxjava3.subscribers.DisposableSubscriber;
|
||||||
|
|
||||||
|
public class SearchViewModel extends AndroidViewModel {
|
||||||
|
private final MutableLiveData<List<Monster>> mAllMonsters;
|
||||||
|
private final MediatorLiveData<List<Monster>> mFilteredMonsters;
|
||||||
|
private final MutableLiveData<String> mFilterText;
|
||||||
|
private final AppDatabase mDB;
|
||||||
|
|
||||||
|
public SearchViewModel(Application application) {
|
||||||
|
super(application);
|
||||||
|
mDB = AppDatabase.getInstance(application);
|
||||||
|
mAllMonsters = new MutableLiveData<>(new ArrayList<>());
|
||||||
|
mFilterText = new MutableLiveData<>("");
|
||||||
|
mFilteredMonsters = new MediatorLiveData<>();
|
||||||
|
mFilteredMonsters.addSource(
|
||||||
|
mAllMonsters,
|
||||||
|
allMonsters -> mFilteredMonsters.setValue(
|
||||||
|
filterMonsters(allMonsters, mFilterText.getValue())));
|
||||||
|
mFilteredMonsters.addSource(
|
||||||
|
mFilterText,
|
||||||
|
filterText -> mFilteredMonsters.setValue(
|
||||||
|
filterMonsters(mAllMonsters.getValue(), filterText)));
|
||||||
|
mDB.monsterDAO()
|
||||||
|
.getAll()
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.subscribeOn(Schedulers.io())
|
||||||
|
.subscribe(new DisposableSubscriber<List<Monster>>() {
|
||||||
|
@Override
|
||||||
|
public void onNext(List<Monster> monsters) {
|
||||||
|
mAllMonsters.setValue(monsters);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onError(Throwable t) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onComplete() {
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean monsterMatchesFilter(Monster monster, String filterText) {
|
||||||
|
if (StringHelper.isNullOrEmpty(filterText)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (StringHelper.containsCaseInsensitive(monster.name, filterText)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (StringHelper.containsCaseInsensitive(monster.size, filterText)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (StringHelper.containsCaseInsensitive(monster.type, filterText)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (StringHelper.containsCaseInsensitive(monster.subtype, filterText)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (StringHelper.containsCaseInsensitive(monster.alignment, filterText)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<Monster> filterMonsters(List<Monster> allMonsters, String filterText) {
|
||||||
|
ArrayList<Monster> filteredMonsters = new ArrayList<>();
|
||||||
|
filterText = filterText.toLowerCase(Locale.ROOT);
|
||||||
|
if (allMonsters != null) {
|
||||||
|
for (Monster monster : allMonsters) {
|
||||||
|
// TODO: do the filtering like the iOS app does.
|
||||||
|
Logger.logUnimplementedFeature("do the filtering like the iOS app does");
|
||||||
|
// TODO: consider splitting search text into words and if each word appears in any of these fields return true e.g, "large demon" would match large in size and demon in type.
|
||||||
|
// TODO: add tags and search by tags
|
||||||
|
// TODO: add a display of what fields matched on each item in the results
|
||||||
|
// TODO: make the criteria configurable from this screen
|
||||||
|
// TODO: find a way to add challenge rating as a search criteria
|
||||||
|
if (monsterMatchesFilter(monster, filterText)) {
|
||||||
|
filteredMonsters.add(monster);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return filteredMonsters;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LiveData<List<Monster>> getMatchedMonsters() {
|
||||||
|
return mFilteredMonsters;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFilterText(String filterText) {
|
||||||
|
mFilterText.setValue(filterText);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package com.majinnaibu.monstercards.ui.shared;
|
||||||
|
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
|
import com.majinnaibu.monstercards.databinding.SimpleListItemBinding;
|
||||||
|
|
||||||
|
public class SimpleListItemViewHolder<T> extends RecyclerView.ViewHolder {
|
||||||
|
public final TextView contentView;
|
||||||
|
public T item;
|
||||||
|
|
||||||
|
public SimpleListItemViewHolder(SimpleListItemBinding binding) {
|
||||||
|
super(binding.getRoot());
|
||||||
|
contentView = binding.content;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
package com.majinnaibu.monstercards.utils;
|
||||||
|
|
||||||
|
public interface ItemCallback<T> {
|
||||||
|
void onItem(T item);
|
||||||
|
}
|
||||||
@@ -2,10 +2,9 @@ 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";
|
||||||
|
|
||||||
public static void logUnimplementedMethod() {
|
public static void logUnimplementedMethod() {
|
||||||
Exception ex = new Exception();
|
Exception ex = new Exception();
|
||||||
StackTraceElement[] stackTrace = ex.getStackTrace();
|
StackTraceElement[] stackTrace = ex.getStackTrace();
|
||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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"
|
||||||
@@ -31,5 +31,4 @@
|
|||||||
app:layout_constraintTop_toTopOf="parent"
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
app:layout_constraintVertical_bias="0.0"
|
app:layout_constraintVertical_bias="0.0"
|
||||||
app:navGraph="@navigation/mobile_navigation" />
|
app:navGraph="@navigation/mobile_navigation" />
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
@@ -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,12 +48,11 @@
|
|||||||
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"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
tools:text="+5" />
|
tools:text="+5" />
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|||||||
@@ -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,16 +25,14 @@
|
|||||||
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"
|
||||||
app:layout_constraintTop_toBottomOf="@id/name"
|
app:layout_constraintTop_toBottomOf="@id/name"
|
||||||
tools:text="Melee Weapon Attack: +8 to hit, reach 10 ft., one target. Hit: 14 (2d8 + 5) bludgeoning damage." />
|
tools:text="Melee Weapon Attack: +8 to hit, reach 10 ft., one target. Hit: 14 (2d8 + 5) bludgeoning damage." />
|
||||||
|
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|||||||
@@ -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,12 +24,11 @@
|
|||||||
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"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
tools:text="17" />
|
tools:text="17" />
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|||||||
@@ -2,34 +2,33 @@
|
|||||||
<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"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
tools:text="1/8" />
|
tools:text="1/8" />
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|||||||
@@ -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,12 +24,11 @@
|
|||||||
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"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
tools:text="367" />
|
tools:text="367" />
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|||||||
@@ -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,12 +24,11 @@
|
|||||||
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"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
tools:text="+2" />
|
tools:text="+2" />
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|||||||
@@ -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,26 +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>
|
||||||
|
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
@@ -1,78 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_margin="@dimen/text_margin"
|
|
||||||
tools:context=".ui.components.AdvantagePicker">
|
|
||||||
<!-- // TODO: style this control to look less awful by default -->
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/label"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginHorizontal="@dimen/padding_normal"
|
|
||||||
android:layout_marginTop="@dimen/padding_small"
|
|
||||||
android:text="@string/label_advantage"
|
|
||||||
android:textAppearance="@android:style/TextAppearance.Material.Body1"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
|
||||||
|
|
||||||
<RadioGroup
|
|
||||||
android:id="@+id/group"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:orientation="horizontal"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:layout_constraintTop_toBottomOf="@id/label">
|
|
||||||
|
|
||||||
<com.google.android.material.radiobutton.MaterialRadioButton
|
|
||||||
android:id="@+id/hasNoAdvantage"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginHorizontal="4dp"
|
|
||||||
android:layout_marginVertical="8dp"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:background="@drawable/radio_button_selector"
|
|
||||||
android:button="@android:color/transparent"
|
|
||||||
android:gravity="center"
|
|
||||||
android:padding="8dp"
|
|
||||||
android:text="@string/label_advantage_none"
|
|
||||||
android:textAppearance="@android:style/TextAppearance.Material.Button"
|
|
||||||
android:textColor="@color/radio_button_text"
|
|
||||||
tools:checked="true" />
|
|
||||||
|
|
||||||
<com.google.android.material.radiobutton.MaterialRadioButton
|
|
||||||
android:id="@+id/hasAdvantage"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginHorizontal="4dp"
|
|
||||||
android:layout_marginVertical="8dp"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:background="@drawable/radio_button_selector"
|
|
||||||
android:button="@android:color/transparent"
|
|
||||||
android:gravity="center"
|
|
||||||
android:padding="8dp"
|
|
||||||
android:text="@string/label_advantage_advantage"
|
|
||||||
android:textAppearance="@android:style/TextAppearance.Material.Button"
|
|
||||||
android:textColor="@color/radio_button_text"
|
|
||||||
tools:checked="false" />
|
|
||||||
|
|
||||||
<com.google.android.material.radiobutton.MaterialRadioButton
|
|
||||||
android:id="@+id/hasDisadvantage"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginHorizontal="4dp"
|
|
||||||
android:layout_marginVertical="8dp"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:background="@drawable/radio_button_selector"
|
|
||||||
android:button="@android:color/transparent"
|
|
||||||
android:gravity="center"
|
|
||||||
android:padding="8dp"
|
|
||||||
android:text="@string/label_advantage_disadvantage"
|
|
||||||
android:textAppearance="@android:style/TextAppearance.Material.Button"
|
|
||||||
android:textColor="@color/radio_button_text"
|
|
||||||
tools:checked="false" />
|
|
||||||
</RadioGroup>
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
||||||
@@ -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"
|
||||||
|
|||||||
@@ -1,42 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:orientation="horizontal">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/content"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_margin="@dimen/text_margin"
|
|
||||||
android:textAppearance="?attr/textAppearanceListItem" />
|
|
||||||
|
|
||||||
<!-- <include-->
|
|
||||||
<!-- layout="@layout/card_monster"-->
|
|
||||||
<!-- android:layout_width="0dp"-->
|
|
||||||
<!-- android:layout_height="wrap_content"-->
|
|
||||||
<!-- android:layout_columnWeight="1"-->
|
|
||||||
<!-- android:layout_marginVertical="8dp"/>-->
|
|
||||||
|
|
||||||
<!-- <include-->
|
|
||||||
<!-- layout="@layout/card_monster_short"-->
|
|
||||||
<!-- android:layout_width="0dp"-->
|
|
||||||
<!-- android:layout_height="wrap_content"-->
|
|
||||||
<!-- android:layout_columnWeight="1"-->
|
|
||||||
<!-- android:layout_marginVertical="8dp"/>-->
|
|
||||||
|
|
||||||
<!-- <include-->
|
|
||||||
<!-- layout="@layout/tile_monster"-->
|
|
||||||
<!-- android:layout_width="0dp"-->
|
|
||||||
<!-- android:layout_height="wrap_content"-->
|
|
||||||
<!-- android:layout_columnWeight="1"-->
|
|
||||||
<!-- android:layout_marginVertical="8dp"/>-->
|
|
||||||
|
|
||||||
<!-- <include-->
|
|
||||||
<!-- layout="@layout/tile_monster_short"-->
|
|
||||||
<!-- android:layout_width="0dp"-->
|
|
||||||
<!-- android:layout_height="wrap_content"-->
|
|
||||||
<!-- android:layout_columnWeight="1"-->
|
|
||||||
<!-- android:layout_marginVertical="8dp" />-->
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
@@ -17,7 +17,7 @@
|
|||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
tools:listitem="@layout/fragment_edit_languages_list_item" />
|
tools:listitem="@layout/simple_list_item" />
|
||||||
|
|
||||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||||
android:id="@+id/add_language"
|
android:id="@+id/add_language"
|
||||||
|
|||||||
@@ -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 -->
|
||||||
@@ -33,4 +33,4 @@
|
|||||||
app:maxValue="1000"
|
app:maxValue="1000"
|
||||||
app:minValue="0"
|
app:minValue="0"
|
||||||
app:stepAmount="5" />
|
app:stepAmount="5" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
@@ -181,9 +181,8 @@
|
|||||||
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" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
|
|||||||
@@ -167,5 +167,4 @@
|
|||||||
android:layout_height="wrap_content" />
|
android:layout_height="wrap_content" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
tools:listitem="@layout/fragment_edit_skills_list_item" />
|
tools:listitem="@layout/simple_list_item" />
|
||||||
|
|
||||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||||
android:id="@+id/add_skill"
|
android:id="@+id/add_skill"
|
||||||
|
|||||||
@@ -1,13 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:orientation="horizontal">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/content"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_margin="@dimen/text_margin"
|
|
||||||
android:textAppearance="?attr/textAppearanceListItem" />
|
|
||||||
</LinearLayout>
|
|
||||||
@@ -1,22 +1,18 @@
|
|||||||
<?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_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_margin="@dimen/text_margin"
|
||||||
tools:context=".ui.editmonster.EditStringFragment">
|
tools:context=".ui.editmonster.EditStringFragment">
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputLayout
|
<com.google.android.material.textfield.TextInputEditText
|
||||||
|
android:id="@+id/description"
|
||||||
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:hint="@string/label_description"
|
||||||
|
android:importantForAutofill="no"
|
||||||
|
android:inputType="text"
|
||||||
|
tools:text="blinded" />
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputEditText
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
android:id="@+id/description"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:hint="@string/label_description"
|
|
||||||
android:importantForAutofill="no"
|
|
||||||
android:inputType="text"
|
|
||||||
tools:text="blinded" />
|
|
||||||
</com.google.android.material.textfield.TextInputLayout>
|
|
||||||
</ScrollView>
|
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
tools:listitem="@layout/fragment_edit_traits_list_item" />
|
tools:listitem="@layout/simple_list_item" />
|
||||||
|
|
||||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||||
android:id="@+id/add_item"
|
android:id="@+id/add_item"
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user