diff --git a/Habitica/AndroidManifest.xml b/Habitica/AndroidManifest.xml
index 373ce4980..68b34144c 100644
--- a/Habitica/AndroidManifest.xml
+++ b/Habitica/AndroidManifest.xml
@@ -71,6 +71,13 @@
android:screenOrientation="unspecified"
tools:ignore="UnusedAttribute">
+
+
+
+ -
+
+
+
+
+
+
+ -
+
+
+
+
+
+
+
diff --git a/Habitica/res/drawable/death_ghost.png b/Habitica/res/drawable/death_ghost.png
new file mode 100644
index 000000000..bfa6b0130
Binary files /dev/null and b/Habitica/res/drawable/death_ghost.png differ
diff --git a/Habitica/res/drawable/ic_broken_heart.xml b/Habitica/res/drawable/ic_broken_heart.xml
new file mode 100644
index 000000000..65960dbcb
--- /dev/null
+++ b/Habitica/res/drawable/ic_broken_heart.xml
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Habitica/res/layout/activity_death.xml b/Habitica/res/layout/activity_death.xml
new file mode 100644
index 000000000..f9d8b86c3
--- /dev/null
+++ b/Habitica/res/layout/activity_death.xml
@@ -0,0 +1,84 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Habitica/res/layout/habit_item_card.xml b/Habitica/res/layout/habit_item_card.xml
index 6b14d2b7c..fc02e2e01 100644
--- a/Habitica/res/layout/habit_item_card.xml
+++ b/Habitica/res/layout/habit_item_card.xml
@@ -82,6 +82,7 @@
style="@style/HabitButton"
android:layout_width="match_parent"
android:layout_height="match_parent"
+ android:background="@drawable/selection_highlight"
android:contentDescription="@string/negative_habit_form" />
diff --git a/Habitica/res/navigation/navigation.xml b/Habitica/res/navigation/navigation.xml
index e46484e02..d192e2c80 100644
--- a/Habitica/res/navigation/navigation.xml
+++ b/Habitica/res/navigation/navigation.xml
@@ -164,6 +164,11 @@
android:name="value"
app:argType="string" />
+
+
+
+
diff --git a/Habitica/res/values/strings.xml b/Habitica/res/values/strings.xml
index 91d728e28..cedd13451 100644
--- a/Habitica/res/values/strings.xml
+++ b/Habitica/res/values/strings.xml
@@ -1256,7 +1256,7 @@
Oldest
Sort By
January
- Febuary
+ February
March
April
May
@@ -1270,4 +1270,8 @@
Adjust when your day switches over past the default time of midnight.
Buy Set
Your Tutorials were reset
+ You ran out of Health!
+ But you can get them all back with hard work! Good luck—you’ll do great.
+ Broken equipment can be repurchased from Rewards
+ %d, lose %d Gold, and break a piece of gear…]]>
diff --git a/Habitica/res/values/styles.xml b/Habitica/res/values/styles.xml
index 8cba64b23..e8a61e244 100644
--- a/Habitica/res/values/styles.xml
+++ b/Habitica/res/values/styles.xml
@@ -692,6 +692,14 @@
- @color/red_100
+
+
+
+
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/components/UserComponent.java b/Habitica/src/main/java/com/habitrpg/android/habitica/components/UserComponent.java
index fa88402d2..dbff176df 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/components/UserComponent.java
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/components/UserComponent.java
@@ -16,6 +16,7 @@ import com.habitrpg.android.habitica.ui.activities.AdventureGuideActivity;
import com.habitrpg.android.habitica.ui.activities.ArmoireActivity;
import com.habitrpg.android.habitica.ui.activities.ChallengeFormActivity;
import com.habitrpg.android.habitica.ui.activities.ClassSelectionActivity;
+import com.habitrpg.android.habitica.ui.activities.DeathActivity;
import com.habitrpg.android.habitica.ui.activities.FixCharacterValuesActivity;
import com.habitrpg.android.habitica.ui.activities.FullProfileActivity;
import com.habitrpg.android.habitica.ui.activities.GemPurchaseActivity;
@@ -105,6 +106,7 @@ import com.habitrpg.android.habitica.ui.viewmodels.InboxViewModel;
import com.habitrpg.android.habitica.ui.viewmodels.MainActivityViewModel;
import com.habitrpg.android.habitica.ui.viewmodels.MainUserViewModel;
import com.habitrpg.android.habitica.ui.viewmodels.NotificationsViewModel;
+import com.habitrpg.android.habitica.ui.viewmodels.StableViewModel;
import com.habitrpg.android.habitica.ui.viewmodels.TasksViewModel;
import com.habitrpg.android.habitica.ui.viewmodels.inventory.equipment.EquipmentOverviewViewModel;
import com.habitrpg.android.habitica.ui.views.dialogs.PetSuggestHatchDialog;
@@ -361,4 +363,8 @@ public interface UserComponent {
void inject(@NotNull ArmoireActivity armoireActivity);
void inject(@NotNull TasksViewModel tasksViewModel);
+
+ void inject(@NotNull StableViewModel stableViewModel);
+
+ void inject(@NotNull DeathActivity deathActivity);
}
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/DeathActivity.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/DeathActivity.kt
new file mode 100644
index 000000000..653030b0d
--- /dev/null
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/DeathActivity.kt
@@ -0,0 +1,86 @@
+package com.habitrpg.android.habitica.ui.activities
+
+import android.os.Bundle
+import android.util.Log
+import android.view.View
+import androidx.lifecycle.lifecycleScope
+import com.habitrpg.android.habitica.R
+import com.habitrpg.android.habitica.components.UserComponent
+import com.habitrpg.android.habitica.data.InventoryRepository
+import com.habitrpg.android.habitica.databinding.ActivityDeathBinding
+import com.habitrpg.android.habitica.extensions.fromHtml
+import com.habitrpg.android.habitica.extensions.observeOnce
+import com.habitrpg.android.habitica.helpers.AdHandler
+import com.habitrpg.android.habitica.helpers.AdType
+import com.habitrpg.android.habitica.helpers.Animations
+import com.habitrpg.android.habitica.helpers.AppConfigManager
+import com.habitrpg.android.habitica.helpers.RxErrorHandler
+import com.habitrpg.android.habitica.ui.viewmodels.MainUserViewModel
+import com.habitrpg.android.habitica.ui.views.ads.AdButton
+import javax.inject.Inject
+
+class DeathActivity: BaseActivity() {
+ private lateinit var binding: ActivityDeathBinding
+
+ @Inject
+ internal lateinit var inventoryRepository: InventoryRepository
+ @Inject
+ internal lateinit var appConfigManager: AppConfigManager
+ @Inject
+ lateinit var userViewModel: MainUserViewModel
+
+ override fun getLayoutResId(): Int = R.layout.activity_armoire
+
+ override fun injectActivity(component: UserComponent?) {
+ component?.inject(this)
+ }
+
+ override fun getContentView(): View {
+ binding = ActivityDeathBinding.inflate(layoutInflater)
+ return binding.root
+ }
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ binding.ghostView.startAnimation(Animations.bobbingAnimation())
+
+ userViewModel.user.observeOnce(this) { user ->
+ binding.lossDescription.text = getString(R.string.faint_loss_description, (user?.stats?.lvl ?: 2).toInt() - 1, user?.stats?.gp?.toInt()).fromHtml()
+ }
+
+ if (appConfigManager.enableArmoireAds()) {
+ val handler = AdHandler(this, AdType.FAINT) {
+ if (!it) {
+ return@AdHandler
+ }
+ Log.d("AdHandler", "Reviving user")
+ compositeSubscription.add(
+ userRepository.updateUser("stats.hp", 1).subscribe({
+ finish()
+ }, RxErrorHandler.handleEmptyError())
+ )
+ }
+ handler.prepare {
+ if (it && binding.adButton.state == AdButton.State.LOADING) {
+ binding.adButton.state = AdButton.State.READY
+ } else if (!it) {
+ binding.adButton.visibility = View.INVISIBLE
+ }
+ }
+ binding.adButton.updateForAdType(AdType.ARMOIRE, lifecycleScope)
+ binding.adButton.setOnClickListener {
+ binding.adButton.state = AdButton.State.LOADING
+ handler.show()
+ }
+ } else {
+ binding.adButton.visibility = View.GONE
+ }
+
+ binding.restartButton.setOnClickListener {
+ binding.restartButton.isEnabled = false
+ userRepository.revive().subscribe({
+ finish()
+ }, RxErrorHandler.handleEmptyError())
+ }
+ }
+}
\ No newline at end of file
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/MainActivity.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/MainActivity.kt
index c724c36c1..ff44fedd1 100755
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/MainActivity.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/MainActivity.kt
@@ -9,7 +9,6 @@ import android.content.pm.PackageManager
import android.content.res.Configuration
import android.os.Build
import android.os.Bundle
-import android.util.Log
import android.view.KeyEvent
import android.view.MenuItem
import android.view.View
@@ -30,7 +29,6 @@ import com.habitrpg.android.habitica.data.InventoryRepository
import com.habitrpg.android.habitica.data.TaskRepository
import com.habitrpg.android.habitica.data.local.UserQuestStatus
import com.habitrpg.android.habitica.databinding.ActivityMainBinding
-import com.habitrpg.android.habitica.databinding.DialogFaintBinding
import com.habitrpg.android.habitica.extensions.dpToPx
import com.habitrpg.android.habitica.extensions.getThemeColor
import com.habitrpg.android.habitica.extensions.hideKeyboard
@@ -38,8 +36,6 @@ import com.habitrpg.android.habitica.extensions.isUsingNightModeResources
import com.habitrpg.android.habitica.extensions.observeOnce
import com.habitrpg.android.habitica.extensions.subscribeWithErrorHandler
import com.habitrpg.android.habitica.extensions.updateStatusBarColor
-import com.habitrpg.android.habitica.helpers.AdHandler
-import com.habitrpg.android.habitica.helpers.AdType
import com.habitrpg.android.habitica.helpers.AmplitudeManager
import com.habitrpg.android.habitica.helpers.AppConfigManager
import com.habitrpg.android.habitica.helpers.MainNavigationController
@@ -59,22 +55,20 @@ import com.habitrpg.android.habitica.ui.TutorialView
import com.habitrpg.android.habitica.ui.fragments.NavigationDrawerFragment
import com.habitrpg.android.habitica.ui.viewmodels.MainActivityViewModel
import com.habitrpg.android.habitica.ui.viewmodels.NotificationsViewModel
-import com.habitrpg.android.habitica.ui.views.HabiticaIconsHelper
import com.habitrpg.android.habitica.ui.views.SnackbarActivity
-import com.habitrpg.android.habitica.ui.views.dialogs.HabiticaAlertDialog
import com.habitrpg.android.habitica.ui.views.dialogs.QuestCompletedDialog
import com.habitrpg.android.habitica.ui.views.yesterdailies.YesterdailyDialog
import com.habitrpg.android.habitica.widget.AvatarStatsWidgetProvider
import com.habitrpg.android.habitica.widget.DailiesWidgetProvider
import com.habitrpg.android.habitica.widget.HabitButtonWidgetProvider
import com.habitrpg.android.habitica.widget.TodoListWidgetProvider
-import javax.inject.Inject
-import kotlin.time.DurationUnit
-import kotlin.time.toDuration
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
+import javax.inject.Inject
+import kotlin.time.DurationUnit
+import kotlin.time.toDuration
open class MainActivity : BaseActivity(), SnackbarActivity {
private var launchScreen: String? = null
@@ -104,7 +98,6 @@ open class MainActivity : BaseActivity(), SnackbarActivity {
private var avatarInHeader: AvatarWithBarsViewModel? = null
val notificationsViewModel: NotificationsViewModel by viewModels()
val viewModel: MainActivityViewModel by viewModels()
- private var faintDialog: HabiticaAlertDialog? = null
private var sideAvatarView: AvatarView? = null
private var drawerFragment: NavigationDrawerFragment? = null
var drawerToggle: ActionBarDrawerToggle? = null
@@ -456,36 +449,8 @@ open class MainActivity : BaseActivity(), SnackbarActivity {
return
}
- if (this.faintDialog == null && !this.isFinishing) {
-
- val binding = DialogFaintBinding.inflate(this.layoutInflater)
- binding.hpBar.setLightBackground(true)
- binding.hpBar.setIcon(HabiticaIconsHelper.imageOfHeartLightBg())
- viewModel.user.value?.let { binding.avatarView.setAvatar(it) }
-
- this.faintDialog = HabiticaAlertDialog(this)
- faintDialog?.setTitle(R.string.faint_header)
- faintDialog?.setAdditionalContentView(binding.root)
- faintDialog?.addButton(R.string.faint_button, true) { _, _ ->
- faintDialog = null
- userRepository.revive().subscribe({ }, RxErrorHandler.handleEmptyError())
- }
- if (AdHandler.isAllowed(AdType.FAINT)) {
- val handler = AdHandler(this, AdType.FAINT) {
- Log.d("AdHandler", "Reviving user")
- compositeSubscription.add(
- userRepository.updateUser("stats.hp", 50)
- .subscribe({}, RxErrorHandler.handleEmptyError())
- )
- }
- handler.prepare()
- faintDialog?.addButton(R.string.watch_ad_to_revive, true) { _, _ ->
- faintDialog = null
- handler.show()
- }
- }
- soundManager.loadAndPlayAudio(SoundManager.SoundDeath)
- this.faintDialog?.enqueue()
+ if (!this.isFinishing) {
+ MainNavigationController.navigate(R.id.deathActivity)
}
}
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/inventory/stable/StableFragment.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/inventory/stable/StableFragment.kt
index ee8fff172..f90a0b7c1 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/inventory/stable/StableFragment.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/inventory/stable/StableFragment.kt
@@ -4,17 +4,21 @@ import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
+import androidx.fragment.app.viewModels
import androidx.viewpager2.adapter.FragmentStateAdapter
import com.google.android.material.tabs.TabLayoutMediator
import com.habitrpg.android.habitica.R
import com.habitrpg.android.habitica.components.UserComponent
import com.habitrpg.android.habitica.databinding.FragmentViewpagerBinding
import com.habitrpg.android.habitica.ui.fragments.BaseMainFragment
+import com.habitrpg.android.habitica.ui.viewmodels.StableViewModel
class StableFragment : BaseMainFragment() {
override var binding: FragmentViewpagerBinding? = null
+ private val viewModel: StableViewModel by viewModels()
+
override fun createBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentViewpagerBinding {
return FragmentViewpagerBinding.inflate(inflater, container, false)
}
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/inventory/stable/StableRecyclerFragment.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/inventory/stable/StableRecyclerFragment.kt
index 392611941..800c70f66 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/inventory/stable/StableRecyclerFragment.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/inventory/stable/StableRecyclerFragment.kt
@@ -1,40 +1,40 @@
package com.habitrpg.android.habitica.ui.fragments.inventory.stable
+import android.app.Application
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
+import androidx.fragment.app.viewModels
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
import com.habitrpg.android.habitica.R
import com.habitrpg.android.habitica.components.UserComponent
import com.habitrpg.android.habitica.data.InventoryRepository
import com.habitrpg.android.habitica.data.UserRepository
import com.habitrpg.android.habitica.databinding.FragmentRefreshRecyclerviewBinding
-import com.habitrpg.android.habitica.extensions.getTranslatedType
import com.habitrpg.android.habitica.helpers.AppConfigManager
import com.habitrpg.android.habitica.helpers.RxErrorHandler
-import com.habitrpg.android.habitica.models.inventory.Animal
import com.habitrpg.android.habitica.models.inventory.Egg
import com.habitrpg.android.habitica.models.inventory.HatchingPotion
-import com.habitrpg.android.habitica.models.inventory.StableSection
-import com.habitrpg.android.habitica.models.user.OwnedMount
-import com.habitrpg.android.habitica.models.user.OwnedObject
-import com.habitrpg.android.habitica.models.user.OwnedPet
import com.habitrpg.android.habitica.ui.adapter.inventory.StableRecyclerAdapter
import com.habitrpg.android.habitica.ui.fragments.BaseFragment
import com.habitrpg.android.habitica.ui.helpers.EmptyItem
import com.habitrpg.android.habitica.ui.helpers.MarginDecoration
import com.habitrpg.android.habitica.ui.helpers.SafeDefaultItemAnimator
import com.habitrpg.android.habitica.ui.viewmodels.MainUserViewModel
-import io.reactivex.rxjava3.core.Flowable
+import com.habitrpg.android.habitica.ui.viewmodels.StableViewModel
+import com.habitrpg.android.habitica.ui.viewmodels.StableViewModelFactory
import io.reactivex.rxjava3.core.Maybe
-import io.reactivex.rxjava3.kotlin.combineLatest
import javax.inject.Inject
class StableRecyclerFragment :
BaseFragment(),
SwipeRefreshLayout.OnRefreshListener {
+ private val viewModel: StableViewModel by viewModels(factoryProducer = {
+ StableViewModelFactory(context?.applicationContext as? Application, itemType)
+ })
+
@Inject
lateinit var inventoryRepository: InventoryRepository
@Inject
@@ -106,11 +106,10 @@ class StableRecyclerFragment :
adapter?.animalIngredientsRetriever = { animal, callback ->
Maybe.zip(
inventoryRepository.getItems(Egg::class.java, arrayOf(animal.animal)).firstElement(),
- inventoryRepository.getItems(HatchingPotion::class.java, arrayOf(animal.color)).firstElement(),
- { eggs, potions ->
- Pair(eggs.first() as? Egg, potions.first() as? HatchingPotion)
- }
- ).subscribe(
+ inventoryRepository.getItems(HatchingPotion::class.java, arrayOf(animal.color)).firstElement()
+ ) { eggs, potions ->
+ Pair(eggs.first() as? Egg, potions.first() as? HatchingPotion)
+ }.subscribe(
{
callback(it)
},
@@ -159,118 +158,24 @@ class StableRecyclerFragment :
}
private fun loadItems() {
- val observable: Maybe> = if ("pets" == itemType) {
- inventoryRepository.getPets().firstElement()
- } else {
- inventoryRepository.getMounts().firstElement()
+ viewModel.items.observe(viewLifecycleOwner) {
+ adapter?.setItemList(it)
}
- val ownedObservable: Flowable> = if ("pets" == itemType) {
- inventoryRepository.getOwnedPets()
- } else {
- inventoryRepository.getOwnedMounts()
- }.map {
- val animalMap = mutableMapOf()
- it.forEach { animal ->
- val castedAnimal = animal as? OwnedObject ?: return@forEach
- animalMap[castedAnimal.key ?: ""] = castedAnimal
- }
- animalMap
+ viewModel.eggs.observe(viewLifecycleOwner) {
+ adapter?.setEggs(it)
+ }
+ viewModel.ownedItems.observe(viewLifecycleOwner) {
+ adapter?.setOwnedItems(it)
+ }
+ viewModel.mounts.observe(viewLifecycleOwner) {
+ adapter?.setExistingMounts(it)
+ }
+ viewModel.ownedMounts.observe(viewLifecycleOwner) {
+ adapter?.setOwnedMounts(it)
}
-
- compositeSubscription.add(
- inventoryRepository.getItems(Egg::class.java)
- .map {
- val eggMap = mutableMapOf()
- it.forEach { egg ->
- eggMap[egg.key] = egg as Egg
- }
- eggMap
- }
- .subscribe(
- {
- adapter?.setEggs(it)
- },
- RxErrorHandler.handleEmptyError()
- )
- )
- compositeSubscription.add(
- ownedObservable.combineLatest(observable.toFlowable())
- .map { (ownedAnimals, unsortedAnimals) ->
- mapAnimals(unsortedAnimals, ownedAnimals)
- }
- .subscribe({ items -> adapter?.setItemList(items) }, RxErrorHandler.handleEmptyError())
- )
- compositeSubscription.add(inventoryRepository.getOwnedItems(true).subscribe({ adapter?.setOwnedItems(it) }, RxErrorHandler.handleEmptyError()))
- compositeSubscription.add(inventoryRepository.getMounts().subscribe({ adapter?.setExistingMounts(it) }, RxErrorHandler.handleEmptyError()))
- compositeSubscription.add(
- inventoryRepository.getOwnedMounts()
- .map { ownedMounts ->
- val mountMap = mutableMapOf()
- ownedMounts.forEach { mountMap[it.key ?: ""] = it }
- return@map mountMap
- }
- .subscribe({ adapter?.setOwnedMounts(it) }, RxErrorHandler.handleEmptyError())
- )
}
- private fun mapAnimals(unsortedAnimals: List, ownedAnimals: Map): ArrayList {
- val items = ArrayList()
- var lastAnimal: Animal = unsortedAnimals.firstOrNull() ?: return items
- var lastSection: StableSection? = null
- for (animal in unsortedAnimals) {
- val identifier = if (animal.animal.isNotEmpty() && (animal.type != "special" && animal.type != "wacky")) animal.animal else animal.key
- val lastIdentifier = if (lastAnimal.animal.isNotEmpty()) lastAnimal.animal else lastAnimal.key
- if (animal.type == "premium") {
- if (!items.contains(lastAnimal)) {
- items.add(lastAnimal)
- }
- lastAnimal = items.first { (it as? Animal)?.animal == animal.animal } as Animal
- } else if (identifier != lastIdentifier || animal === unsortedAnimals[unsortedAnimals.size - 1]) {
- if (!((lastAnimal.type == "special") && lastAnimal.numberOwned == 0) && !items.contains(lastAnimal)) {
- items.add(lastAnimal)
- }
- lastAnimal = animal
- }
- if (animal.type != lastSection?.key && animal.type != "premium") {
- if (items.size > 0 && items[items.size - 1].javaClass == StableSection::class.java) {
- items.removeAt(items.size - 1)
- }
- val title = if (itemType == "pets") {
- context?.getString(R.string.pet_category, animal.getTranslatedType(context))
- } else {
- context?.getString(R.string.mount_category, animal.getTranslatedType(context))
- }
- val section = StableSection(animal.type, title ?: "")
- items.add(section)
- lastSection = section
- }
- val isOwned = when (itemType) {
- "pets" -> {
- val ownedPet = ownedAnimals[animal.key] as? OwnedPet
- ownedPet?.trained ?: 0 > 0
- }
- "mounts" -> {
- val ownedMount = ownedAnimals[animal.key] as? OwnedMount
- ownedMount?.owned == true
- }
- else -> false
- }
- lastAnimal.totalNumber += 1
- lastSection?.totalCount = (lastSection?.totalCount ?: 0) + 1
- if (isOwned) {
- lastAnimal.numberOwned += 1
- lastSection?.ownedCount = (lastSection?.ownedCount ?: 0) + 1
- }
- }
- if (!((lastAnimal.type == "premium" || lastAnimal.type == "special") && lastAnimal.numberOwned == 0)) {
- items.add(lastAnimal)
- }
-
- items.add(0, "header")
- items.removeAll { it is StableSection && (it.key as? String) == "special" && it.ownedCount == 0 }
- return items
- }
companion object {
private const val ITEM_TYPE_KEY = "CLASS_TYPE_KEY"
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewmodels/StableViewModel.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewmodels/StableViewModel.kt
new file mode 100644
index 000000000..256bf1a22
--- /dev/null
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewmodels/StableViewModel.kt
@@ -0,0 +1,173 @@
+package com.habitrpg.android.habitica.ui.viewmodels
+
+import android.app.Application
+import androidx.lifecycle.LiveData
+import androidx.lifecycle.MutableLiveData
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.ViewModelProvider
+import com.habitrpg.android.habitica.R
+import com.habitrpg.android.habitica.components.UserComponent
+import com.habitrpg.android.habitica.data.InventoryRepository
+import com.habitrpg.android.habitica.extensions.getTranslatedType
+import com.habitrpg.android.habitica.helpers.RxErrorHandler
+import com.habitrpg.android.habitica.models.inventory.Animal
+import com.habitrpg.android.habitica.models.inventory.Egg
+import com.habitrpg.android.habitica.models.inventory.Mount
+import com.habitrpg.android.habitica.models.inventory.StableSection
+import com.habitrpg.android.habitica.models.user.OwnedItem
+import com.habitrpg.android.habitica.models.user.OwnedMount
+import com.habitrpg.android.habitica.models.user.OwnedObject
+import com.habitrpg.android.habitica.models.user.OwnedPet
+import io.reactivex.rxjava3.core.Flowable
+import io.reactivex.rxjava3.core.Maybe
+import io.reactivex.rxjava3.kotlin.combineLatest
+import javax.inject.Inject
+
+class StableViewModel(private val application: Application?, private val itemType: String?): BaseViewModel() {
+
+ @Inject
+ lateinit var inventoryRepository: InventoryRepository
+
+ override fun inject(component: UserComponent) {
+ component.inject(this)
+ }
+
+ init {
+ loadItems()
+ }
+
+ private val _items: MutableLiveData> = MutableLiveData()
+ val items: LiveData> = _items
+ private val _eggs: MutableLiveData