Start using a central userViewModel

This commit is contained in:
Phillip Thelen 2022-01-31 15:58:15 +01:00
parent 2e654c9c63
commit 46caca91e2
32 changed files with 228 additions and 148 deletions

View file

@ -103,6 +103,7 @@ import com.habitrpg.android.habitica.ui.viewmodels.AuthenticationViewModel;
import com.habitrpg.android.habitica.ui.viewmodels.GroupViewModel;
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.inventory.equipment.EquipmentOverviewViewModel;
import com.habitrpg.android.habitica.ui.views.insufficientCurrency.InsufficientGemsDialog;
@ -352,4 +353,6 @@ public interface UserComponent {
void inject(@NotNull MainActivityViewModel mainActivityViewModel);
void inject(@NotNull GuidelinesActivity guidelinesActivity);
void inject(@NotNull MainUserViewModel mainUserViewModel);
}

View file

@ -4,8 +4,10 @@ import android.content.Context;
import android.content.SharedPreferences;
import com.habitrpg.android.habitica.data.TaskRepository;
import com.habitrpg.android.habitica.data.UserRepository;
import com.habitrpg.android.habitica.helpers.TaskAlarmManager;
import com.habitrpg.android.habitica.helpers.UserScope;
import com.habitrpg.android.habitica.ui.viewmodels.MainUserViewModel;
import javax.inject.Named;
@ -28,4 +30,10 @@ public class UserModule {
public String providesUserID(SharedPreferences sharedPreferences) {
return sharedPreferences.getString("UserID", "");
}
@Provides
@UserScope
MainUserViewModel providesUserViewModel(UserRepository userRepository) {
return new MainUserViewModel(userRepository);
}
}

View file

@ -273,7 +273,7 @@ open class MainActivity : BaseActivity(), TutorialView.OnTutorialReaction, Snack
navigationController.addOnDestinationChangedListener { _, destination, arguments -> updateToolbarTitle(destination, arguments) }
if (launchScreen == "/party") {
if (viewModel.isUserInParty) {
if (viewModel.userViewModel.isUserInParty) {
MainNavigationController.navigate(R.id.partyFragment)
}
}
@ -430,7 +430,7 @@ open class MainActivity : BaseActivity(), TutorialView.OnTutorialReaction, Snack
}
private fun displayDeathDialogIfNeeded() {
if (!viewModel.isUserFainted) {
if (!viewModel.userViewModel.isUserFainted) {
return
}

View file

@ -15,7 +15,11 @@ class MountDetailRecyclerAdapter : androidx.recyclerview.widget.RecyclerView.Ada
private var ownedMounts: Map<String, OwnedMount>? = null
private val equipEvents = PublishSubject.create<String>()
private var user: User? = null
var currentMount: String? = null
set(value) {
field = value
notifyDataSetChanged()
}
private var itemList: List<Any> = ArrayList()
@ -37,7 +41,7 @@ class MountDetailRecyclerAdapter : androidx.recyclerview.widget.RecyclerView.Ada
override fun onBindViewHolder(holder: androidx.recyclerview.widget.RecyclerView.ViewHolder, position: Int) {
when (val obj = this.itemList[position]) {
is StableSection -> (holder as? SectionViewHolder)?.bind(obj)
is Mount -> (holder as? MountViewHolder)?.bind(obj, ownedMounts?.get(obj.key ?: "")?.owned == true, user)
is Mount -> (holder as? MountViewHolder)?.bind(obj, ownedMounts?.get(obj.key ?: "")?.owned == true, currentMount)
}
}
@ -49,9 +53,4 @@ class MountDetailRecyclerAdapter : androidx.recyclerview.widget.RecyclerView.Ada
this.ownedMounts = ownedMounts
notifyDataSetChanged()
}
fun setUser(user: User) {
this.user = user
notifyDataSetChanged()
}
}

View file

@ -17,7 +17,11 @@ class PetDetailRecyclerAdapter : androidx.recyclerview.widget.RecyclerView.Adapt
private var ownedPets: Map<String, OwnedPet>? = null
private var ownedMounts: Map<String, OwnedMount>? = null
private var ownedItems: Map<String, OwnedItem>? = null
private var user: User? = null
var currentPet: String? = null
set(value) {
field = value
notifyDataSetChanged()
}
private val equipEvents = PublishSubject.create<String>()
private val feedEvents = PublishSubject.create<Pair<Pet, Food?>>()
private var ownsSaddles: Boolean = false
@ -29,11 +33,6 @@ class PetDetailRecyclerAdapter : androidx.recyclerview.widget.RecyclerView.Adapt
this.notifyDataSetChanged()
}
fun setUser(user: User) {
this.user = user
notifyDataSetChanged()
}
fun getEquipFlowable(): Flowable<String> {
return equipEvents.toFlowable(BackpressureStrategy.DROP)
}
@ -81,7 +80,7 @@ class PetDetailRecyclerAdapter : androidx.recyclerview.widget.RecyclerView.Adapt
ownedItems?.get(obj.animal + "-eggs") != null,
ownedItems?.get(obj.color + "-hatchingPotions") != null,
ownedMounts?.containsKey(obj.key) == true,
user
currentPet
)
}
}

View file

@ -31,7 +31,16 @@ class StableRecyclerAdapter : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
var animalIngredientsRetriever: ((Animal, ((Pair<Egg?, HatchingPotion?>) -> Unit)) -> Unit)? = null
private val feedEvents = PublishSubject.create<Pair<Pet, Food?>>()
var itemType: String? = null
private var user: User? = null
var currentPet: String? = null
set(value) {
field = value
notifyDataSetChanged()
}
var currentMount: String? = null
set(value) {
field = value
notifyDataSetChanged()
}
private val equipEvents = PublishSubject.create<String>()
private var existingMounts: List<Mount>? = null
private var ownedMounts: Map<String, OwnedMount>? = null
@ -43,11 +52,6 @@ class StableRecyclerAdapter : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
return equipEvents.toFlowable(BackpressureStrategy.DROP)
}
fun setUser(user: User) {
this.user = user
notifyDataSetChanged()
}
private fun canRaiseToMount(pet: Pet): Boolean {
if (pet.type == "special") return false
for (mount in existingMounts ?: emptyList()) {
@ -122,10 +126,10 @@ class StableRecyclerAdapter : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
hasUnlockedEgg = ownedItems?.get(item.animal + "-eggs") != null,
hasUnlockedPotion = ownedItems?.get(item.color + "-hatchingPotions") != null,
hasMount = ownedMounts?.containsKey(item.key) == true,
user = user
currentPet = currentPet
)
} else if (item is Mount) {
(holder as? MountViewHolder)?.bind(item, item.numberOwned > 0, user)
(holder as? MountViewHolder)?.bind(item, item.numberOwned > 0, currentMount)
}
return
}

View file

@ -14,6 +14,7 @@ import com.habitrpg.android.habitica.databinding.FragmentRefreshRecyclerviewBind
import com.habitrpg.android.habitica.helpers.RxErrorHandler
import com.habitrpg.android.habitica.ui.adapter.AchievementsAdapter
import com.habitrpg.android.habitica.ui.helpers.ToolbarColorHelper
import com.habitrpg.android.habitica.ui.viewmodels.MainUserViewModel
import io.reactivex.rxjava3.kotlin.Flowables
import io.reactivex.rxjava3.kotlin.combineLatest
import javax.inject.Inject
@ -22,6 +23,8 @@ class AchievementsFragment : BaseMainFragment<FragmentRefreshRecyclerviewBinding
@Inject
lateinit var inventoryRepository: InventoryRepository
@Inject
lateinit var userViewModel: MainUserViewModel
override var binding: FragmentRefreshRecyclerviewBinding? = null
@ -125,6 +128,7 @@ class AchievementsFragment : BaseMainFragment<FragmentRefreshRecyclerviewBinding
}
)
val user = userViewModel.user.value
val challengeAchievementCount = user?.challengeAchievements?.size ?: 0
if (challengeAchievementCount > 0) {
entries.add(Pair("Challenges won", challengeAchievementCount))

View file

@ -39,23 +39,12 @@ abstract class BaseMainFragment<VB : ViewBinding> : BaseFragment<VB>() {
var usesTabLayout: Boolean = false
var hidesToolbar: Boolean = false
var usesBottomNavigation = false
open var user: User? = null
override fun onAttach(context: Context) {
super.onAttach(context)
if (activity is MainActivity) {
user = activity?.viewModel?.user?.value
}
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
compositeSubscription.add(userRepository.getUser().subscribe({ user = it }, RxErrorHandler.handleEmptyError()))
if (this.usesBottomNavigation) {
bottomNavigation?.visibility = View.VISIBLE
} else {

View file

@ -18,6 +18,7 @@ import com.habitrpg.android.habitica.ui.adapter.CustomizationRecyclerViewAdapter
import com.habitrpg.android.habitica.ui.fragments.BaseMainFragment
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 javax.inject.Inject
class AvatarCustomizationFragment :
@ -34,6 +35,8 @@ class AvatarCustomizationFragment :
lateinit var customizationRepository: CustomizationRepository
@Inject
lateinit var inventoryRepository: InventoryRepository
@Inject
lateinit var userViewModel: MainUserViewModel
var type: String? = null
var category: String? = null
@ -52,7 +55,7 @@ class AvatarCustomizationFragment :
adapter.getSelectCustomizationEvents()
.flatMap { customization ->
if (customization.type == "background") {
userRepository.unlockPath(user, customization)
userRepository.unlockPath(userViewModel.user.value, customization)
.flatMap { userRepository.retrieveUser(false, true, true) }
} else {
userRepository.useCustomization(customization.type ?: "", customization.category, customization.identifier ?: "")
@ -63,7 +66,7 @@ class AvatarCustomizationFragment :
compositeSubscription.add(
adapter.getUnlockCustomizationEvents()
.flatMap { customization ->
userRepository.unlockPath(user, customization)
userRepository.unlockPath(userViewModel.user.value, customization)
}
.flatMap { userRepository.retrieveUser(withTasks = false, forced = true) }
.flatMap { inventoryRepository.retrieveInAppRewards() }
@ -112,11 +115,7 @@ class AvatarCustomizationFragment :
binding?.recyclerView?.itemAnimator = SafeDefaultItemAnimator()
this.loadCustomizations()
compositeSubscription.add(
userRepository.getUser().subscribeWithErrorHandler {
updateUser(it)
}
)
userViewModel.user.observe(viewLifecycleOwner) { updateUser(it) }
}
override fun onDestroy() {
@ -153,7 +152,8 @@ class AvatarCustomizationFragment :
layoutManager.spanCount = spanCount
}
fun updateUser(user: User) {
fun updateUser(user: User?) {
if (user == null) return
this.updateActiveCustomization(user)
if (adapter.customizationList.size != 0) {
val ownedCustomizations = ArrayList<String>()
@ -162,8 +162,8 @@ class AvatarCustomizationFragment :
} else {
this.loadCustomizations()
}
this.adapter.userSize = this.user?.preferences?.size
this.adapter.hairColor = this.user?.preferences?.hair?.color
this.adapter.userSize = user.preferences?.size
this.adapter.hairColor = user.preferences?.hair?.color
this.adapter.gemBalance = user.gemCount
adapter.notifyDataSetChanged()
}

View file

@ -18,6 +18,7 @@ import com.habitrpg.android.habitica.ui.adapter.CustomizationEquipmentRecyclerVi
import com.habitrpg.android.habitica.ui.fragments.BaseMainFragment
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 javax.inject.Inject
@ -27,6 +28,8 @@ class AvatarEquipmentFragment :
@Inject
lateinit var inventoryRepository: InventoryRepository
@Inject
lateinit var userViewModel: MainUserViewModel
override var binding: FragmentRefreshRecyclerviewBinding? = null
@ -51,7 +54,7 @@ class AvatarEquipmentFragment :
adapter.getSelectCustomizationEvents()
.flatMap { equipment ->
val key = (if (equipment.key?.isNotBlank() != true) activeEquipment else equipment.key) ?: ""
inventoryRepository.equip(user, if (user?.preferences?.costume == true) "costume" else "equipped", key)
inventoryRepository.equip(userViewModel.user.value, if (userViewModel.user.value?.preferences?.costume == true) "costume" else "equipped", key)
}
.subscribe({ }, RxErrorHandler.handleEmptyError())
)
@ -143,7 +146,7 @@ class AvatarEquipmentFragment :
if (this.type == null || user.preferences == null) {
return
}
val outfit = if (user.preferences?.costume == true) this.user?.items?.gear?.costume else this.user?.items?.gear?.equipped
val outfit = if (user.preferences?.costume == true) user.items?.gear?.costume else user.items?.gear?.equipped
val activeEquipment = when (this.type) {
"headAccessory" -> outfit?.headAccessory
"back" -> outfit?.back

View file

@ -44,7 +44,7 @@ class EquipmentDetailFragment :
savedInstanceState: Bundle?
): View? {
compositeSubscription.add(
this.adapter.equipEvents.flatMapMaybe { key -> inventoryRepository.equipGear(user, key, isCostume ?: false).firstElement() }
this.adapter.equipEvents.flatMapMaybe { key -> inventoryRepository.equipGear(null, key, isCostume ?: false).firstElement() }
.subscribe({ }, RxErrorHandler.handleEmptyError())
)
return super.onCreateView(inflater, container, savedInstanceState)

View file

@ -45,10 +45,10 @@ class EquipmentOverviewFragment : BaseMainFragment<FragmentEquipmentOverviewBind
it?.items?.gear?.let {
updateGearData(it)
}
binding?.autoEquipSwitch?.isChecked = user?.preferences?.autoEquip ?: false
binding?.costumeSwitch?.isChecked = user?.preferences?.costume ?: false
binding?.autoEquipSwitch?.isChecked = viewModel.usesAutoEquip
binding?.costumeSwitch?.isChecked = viewModel.usesCostume
binding?.costumeView?.isEnabled = user?.preferences?.costume == true
binding?.costumeView?.isEnabled = viewModel.usesCostume
}
}

View file

@ -27,6 +27,7 @@ import com.habitrpg.android.habitica.ui.fragments.BaseFragment
import com.habitrpg.android.habitica.ui.helpers.EmptyItem
import com.habitrpg.android.habitica.ui.helpers.SafeDefaultItemAnimator
import com.habitrpg.android.habitica.ui.helpers.loadImage
import com.habitrpg.android.habitica.ui.viewmodels.MainUserViewModel
import com.habitrpg.android.habitica.ui.views.dialogs.OpenedMysteryitemDialog
import javax.inject.Inject
@ -40,11 +41,12 @@ class ItemRecyclerFragment : BaseFragment<FragmentItemsBinding>(), SwipeRefreshL
lateinit var userRepository: UserRepository
@Inject
internal lateinit var hatchPetUseCase: HatchPetUseCase
@Inject
lateinit var userViewModel: MainUserViewModel
var adapter: ItemRecyclerAdapter? = null
var itemType: String? = null
var itemTypeText: String? = null
var user: User? = null
internal var layoutManager: androidx.recyclerview.widget.LinearLayoutManager? = null
override var binding: FragmentItemsBinding? = null
@ -111,7 +113,7 @@ class ItemRecyclerFragment : BaseFragment<FragmentItemsBinding>(), SwipeRefreshL
)
compositeSubscription.add(
adapter.getOpenMysteryItemFlowable()
.flatMap { inventoryRepository.openMysteryItem(user) }
.flatMap { inventoryRepository.openMysteryItem(userViewModel.user.value) }
.doOnNext {
val activity = activity as? MainActivity
if (activity != null) {
@ -122,7 +124,7 @@ class ItemRecyclerFragment : BaseFragment<FragmentItemsBinding>(), SwipeRefreshL
dialog.binding.titleView.text = it.text
dialog.binding.descriptionView.text = it.notes
dialog.addButton(R.string.equip, true) { _, _ ->
inventoryRepository.equip(user, "equipped", it.key ?: "").subscribe({}, RxErrorHandler.handleEmptyError())
inventoryRepository.equip(userViewModel.user.value, "equipped", it.key ?: "").subscribe({}, RxErrorHandler.handleEmptyError())
}
dialog.addCloseButton()
dialog.enqueue()

View file

@ -68,7 +68,6 @@ class ItemsFragment : BaseMainFragment<FragmentViewpagerBinding>() {
4 -> "special"
else -> ""
}
fragment.user = this@ItemsFragment.user
fragment.itemTypeText =
if (position == 4 && isAdded) getString(R.string.special_items)
else getPageTitle(position)

View file

@ -24,6 +24,7 @@ import com.habitrpg.android.habitica.ui.adapter.inventory.ShopRecyclerAdapter
import com.habitrpg.android.habitica.ui.fragments.BaseMainFragment
import com.habitrpg.android.habitica.ui.helpers.RecyclerViewState
import com.habitrpg.android.habitica.ui.helpers.SafeDefaultItemAnimator
import com.habitrpg.android.habitica.ui.viewmodels.MainUserViewModel
import com.habitrpg.android.habitica.ui.views.CurrencyViews
import com.habitrpg.android.habitica.ui.views.dialogs.HabiticaAlertDialog
import javax.inject.Inject
@ -44,6 +45,8 @@ open class ShopFragment : BaseMainFragment<FragmentRefreshRecyclerviewBinding>()
lateinit var socialRepository: SocialRepository
@Inject
lateinit var configManager: AppConfigManager
@Inject
lateinit var userViewModel: MainUserViewModel
private var layoutManager: GridLayoutManager? = null
@ -106,7 +109,7 @@ open class ShopFragment : BaseMainFragment<FragmentRefreshRecyclerviewBinding>()
this.shopIdentifier = savedInstanceState.getString(SHOP_IDENTIFIER_KEY, "")
}
adapter?.selectedGearCategory = user?.stats?.habitClass ?: ""
adapter?.selectedGearCategory = userViewModel.user.value?.stats?.habitClass ?: ""
if (shop != null) {
adapter?.setShop(shop)
@ -122,15 +125,10 @@ open class ShopFragment : BaseMainFragment<FragmentRefreshRecyclerviewBinding>()
}
}
compositeSubscription.add(
userRepository.getUser().subscribe(
{
adapter?.user = user
updateCurrencyView(it)
},
RxErrorHandler.handleEmptyError()
)
)
userViewModel.user.observe(viewLifecycleOwner) {
adapter?.user = it
updateCurrencyView(it)
}
compositeSubscription.add(
socialRepository.getGroup(Group.TAVERN_ID)
@ -183,7 +181,7 @@ open class ShopFragment : BaseMainFragment<FragmentRefreshRecyclerviewBinding>()
this.inventoryRepository.retrieveShopInventory(shopUrl)
.map { shop1 ->
if (shop1.identifier == Shop.MARKET) {
val user = user
val user = userViewModel.user.value
val specialCategory = ShopCategory()
specialCategory.text = getString(R.string.special)
if (user?.isValid == true && user.purchased?.plan?.isActive == true) {
@ -315,9 +313,9 @@ open class ShopFragment : BaseMainFragment<FragmentRefreshRecyclerviewBinding>()
private const val SHOP_IDENTIFIER_KEY = "SHOP_IDENTIFIER_KEY"
}
private fun updateCurrencyView(user: User) {
currencyView.gold = user.stats?.gp ?: 0.0
currencyView.gems = user.gemCount.toDouble()
currencyView.hourglasses = user.hourglassCount.toDouble()
private fun updateCurrencyView(user: User?) {
currencyView.gold = user?.stats?.gp ?: 0.0
currencyView.gems = user?.gemCount?.toDouble() ?: 0.0
currencyView.hourglasses = user?.hourglassCount?.toDouble() ?: 0.0
}
}

View file

@ -18,6 +18,7 @@ import com.habitrpg.android.habitica.ui.adapter.inventory.MountDetailRecyclerAda
import com.habitrpg.android.habitica.ui.fragments.BaseMainFragment
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 javax.inject.Inject
class MountDetailRecyclerFragment :
@ -26,6 +27,8 @@ class MountDetailRecyclerFragment :
@Inject
internal lateinit var inventoryRepository: InventoryRepository
@Inject
lateinit var userViewModel: MainUserViewModel
var adapter: MountDetailRecyclerAdapter? = null
var animalType: String? = null
@ -86,14 +89,15 @@ class MountDetailRecyclerFragment :
binding?.recyclerView?.itemAnimator = SafeDefaultItemAnimator()
this.loadItems()
adapter?.getEquipFlowable()?.flatMap { key -> inventoryRepository.equip(user, "mount", key) }
adapter?.getEquipFlowable()?.flatMap { key -> inventoryRepository.equip(null, "mount", key) }
?.subscribe(
{
user?.let { updatedUser -> adapter?.setUser(updatedUser) }
adapter?.currentMount = it.currentMount
},
RxErrorHandler.handleEmptyError()
)?.let { compositeSubscription.add(it) }
}
userViewModel.user.observe(viewLifecycleOwner) { adapter?.currentMount = it?.currentMount }
if (savedInstanceState != null) {
this.animalType = savedInstanceState.getString(ANIMAL_TYPE_KEY, "")
@ -134,7 +138,6 @@ class MountDetailRecyclerFragment :
return@map mountMap
}.doOnNext {
adapter?.setOwnedMounts(it)
user?.let { updatedUser -> adapter?.setUser(updatedUser) }
},
{ unsortedAnimals, ownedAnimals ->
val items = mutableListOf<Any>()

View file

@ -22,6 +22,7 @@ import com.habitrpg.android.habitica.ui.adapter.inventory.PetDetailRecyclerAdapt
import com.habitrpg.android.habitica.ui.fragments.BaseMainFragment
import com.habitrpg.android.habitica.ui.fragments.inventory.items.ItemDialogFragment
import com.habitrpg.android.habitica.ui.helpers.SafeDefaultItemAnimator
import com.habitrpg.android.habitica.ui.viewmodels.MainUserViewModel
import io.reactivex.rxjava3.core.Maybe
import io.reactivex.rxjava3.kotlin.Flowables
import javax.inject.Inject
@ -34,6 +35,8 @@ class PetDetailRecyclerFragment :
lateinit var inventoryRepository: InventoryRepository
@Inject
lateinit var feedPetUseCase: FeedPetUseCase
@Inject
lateinit var userViewModel: MainUserViewModel
var adapter: PetDetailRecyclerAdapter = PetDetailRecyclerAdapter()
private var animalType: String? = null
@ -109,14 +112,15 @@ class PetDetailRecyclerFragment :
compositeSubscription.add(
adapter.getEquipFlowable()
.flatMap { key -> inventoryRepository.equip(user, "pet", key) }
.flatMap { key -> inventoryRepository.equip(null, "pet", key) }
.subscribe(
{
user?.let { updatedUser -> adapter.setUser(updatedUser) }
adapter.currentPet = it.currentPet
},
RxErrorHandler.handleEmptyError()
)
)
userViewModel.user.observe(viewLifecycleOwner) { adapter.currentPet = it?.currentPet }
compositeSubscription.add(adapter.feedFlowable.subscribe({ showFeedingDialog(it.first, it.second) }, RxErrorHandler.handleEmptyError()))
view.post { setGridSpanCount(view.width) }
@ -168,7 +172,6 @@ class PetDetailRecyclerFragment :
return@map petMap
}.doOnNext {
adapter.setOwnedPets(it)
user?.let { updatedUser -> adapter.setUser(updatedUser) }
}
).map {
val items = mutableListOf<Any>()

View file

@ -56,8 +56,7 @@ class StableFragment : BaseMainFragment<FragmentViewpagerBinding>() {
fragment.itemType = "mounts"
}
}
fragment.user = this@StableFragment.user
fragment.itemTypeText = getPageTitle(position).toString()
fragment.itemTypeText = getPageTitle(position)
return fragment
}

View file

@ -23,6 +23,7 @@ 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 io.reactivex.rxjava3.core.Maybe
import io.reactivex.rxjava3.kotlin.combineLatest
@ -39,11 +40,12 @@ class StableRecyclerFragment :
lateinit var userRepository: UserRepository
@Inject
lateinit var configManager: AppConfigManager
@Inject
lateinit var userViewModel: MainUserViewModel
var adapter: StableRecyclerAdapter? = null
var itemType: String? = null
var itemTypeText: String? = null
var user: User? = null
internal var layoutManager: androidx.recyclerview.widget.GridLayoutManager? = null
override var binding: FragmentRefreshRecyclerviewBinding? = null
@ -96,7 +98,6 @@ class StableRecyclerFragment :
adapter = binding?.recyclerView?.adapter as? StableRecyclerAdapter
if (adapter == null) {
adapter = StableRecyclerAdapter()
user?.let { adapter?.setUser(it) }
adapter?.animalIngredientsRetriever = { animal, callback ->
Maybe.zip(
inventoryRepository.getItems(Egg::class.java, arrayOf(animal.animal)).firstElement(),
@ -119,11 +120,15 @@ class StableRecyclerFragment :
adapter?.let {
compositeSubscription.add(
it.getEquipFlowable()
.flatMap { key -> inventoryRepository.equip(user, if (itemType == "pets") "pet" else "mount", key) }
.flatMap { key -> inventoryRepository.equip(null, if (itemType == "pets") "pet" else "mount", key) }
.subscribe({ }, RxErrorHandler.handleEmptyError())
)
}
}
userViewModel.user.observe(viewLifecycleOwner) {
adapter?.currentPet = it?.currentPet
adapter?.currentMount = it?.currentMount
}
this.loadItems()
view.post { setGridSpanCount(view.width) }

View file

@ -23,12 +23,14 @@ import com.habitrpg.android.habitica.ui.activities.SkillTasksActivity
import com.habitrpg.android.habitica.ui.adapter.SkillsRecyclerViewAdapter
import com.habitrpg.android.habitica.ui.fragments.BaseMainFragment
import com.habitrpg.android.habitica.ui.helpers.SafeDefaultItemAnimator
import com.habitrpg.android.habitica.ui.viewmodels.MainUserViewModel
import com.habitrpg.android.habitica.ui.views.HabiticaIconsHelper
import com.habitrpg.android.habitica.ui.views.HabiticaSnackbar
import com.habitrpg.android.habitica.ui.views.HabiticaSnackbar.Companion.showSnackbar
import io.reactivex.rxjava3.core.Flowable
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import javax.inject.Inject
class SkillsFragment : BaseMainFragment<FragmentSkillsBinding>() {
internal var adapter: SkillsRecyclerViewAdapter? = null
@ -36,20 +38,16 @@ class SkillsFragment : BaseMainFragment<FragmentSkillsBinding>() {
override var binding: FragmentSkillsBinding? = null
@Inject
lateinit var userViewModel: MainUserViewModel
override fun createBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentSkillsBinding {
return FragmentSkillsBinding.inflate(inflater, container, false)
}
override var user: User? = null
set(value) {
field = value
checkUserLoadSkills()
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
adapter = SkillsRecyclerViewAdapter()
adapter?.useSkillEvents?.subscribeWithErrorHandler { onSkillSelected(it) }?.let { compositeSubscription.add(it) }
checkUserLoadSkills()
this.tutorialStepIdentifier = "skills"
this.tutorialText = getString(R.string.tutorial_skills)
@ -63,19 +61,22 @@ class SkillsFragment : BaseMainFragment<FragmentSkillsBinding>() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
userViewModel.user.observe(viewLifecycleOwner) { user ->
user?.let { checkUserLoadSkills(it) }
}
binding?.recyclerView?.layoutManager = androidx.recyclerview.widget.LinearLayoutManager(activity)
binding?.recyclerView?.adapter = adapter
binding?.recyclerView?.itemAnimator = SafeDefaultItemAnimator()
}
private fun checkUserLoadSkills() {
if (user == null || adapter == null) {
private fun checkUserLoadSkills(user: User) {
if (adapter == null) {
return
}
adapter?.mana = this.user?.stats?.mp ?: 0.0
adapter?.level = this.user?.stats?.lvl ?: 0
adapter?.specialItems = this.user?.items?.special
user?.let { user ->
adapter?.mana = user.stats?.mp ?: 0.0
adapter?.level = user.stats?.lvl ?: 0
adapter?.specialItems = user.items?.special
Flowable.combineLatest(
userRepository.getSkills(user),
userRepository.getSpecialItems(user),
@ -89,9 +90,7 @@ class SkillsFragment : BaseMainFragment<FragmentSkillsBinding>() {
}
return@combineLatest allEntries
}
)
.subscribe({ skills -> adapter?.setSkillList(skills) }, RxErrorHandler.handleEmptyError())
}
).subscribe({ skills -> adapter?.setSkillList(skills) }, RxErrorHandler.handleEmptyError())
}
private fun onSkillSelected(skill: Skill) {

View file

@ -88,7 +88,7 @@ class InboxMessageListFragment : BaseMainFragment<FragmentInboxMessageListBindin
{ member ->
setReceivingUser(member.username, member.id)
activity?.title = member.displayName
chatAdapter = InboxAdapter(user, member)
chatAdapter = InboxAdapter(viewModel.user.value, member)
viewModel.messages.observe(this.viewLifecycleOwner) {
markMessagesAsRead(it)
chatAdapter?.submitList(it)
@ -170,7 +170,7 @@ class InboxMessageListFragment : BaseMainFragment<FragmentInboxMessageListBindin
}
private fun markMessagesAsRead(messages: List<ChatMessage>) {
socialRepository.markSomePrivateMessagesAsRead(user, messages)
socialRepository.markSomePrivateMessagesAsRead(viewModel.user.value, messages)
}
private fun startAutoRefreshing() {

View file

@ -41,7 +41,7 @@ class InboxOverviewFragment : BaseMainFragment<FragmentInboxBinding>(), androidx
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
this.hidesToolbar = true
compositeSubscription.add(this.socialRepository.markPrivateMessagesRead(user).subscribe({ }, RxErrorHandler.handleEmptyError()))
compositeSubscription.add(this.socialRepository.markPrivateMessagesRead(null).subscribe({ }, RxErrorHandler.handleEmptyError()))
return super.onCreateView(inflater, container, savedInstanceState)
}

View file

@ -26,6 +26,7 @@ import com.habitrpg.android.habitica.modules.AppModule
import com.habitrpg.android.habitica.ui.fragments.BaseMainFragment
import com.habitrpg.android.habitica.ui.helpers.DataBindingUtils
import com.habitrpg.android.habitica.ui.helpers.MarkdownParser
import com.habitrpg.android.habitica.ui.viewmodels.MainUserViewModel
import com.habitrpg.android.habitica.ui.views.dialogs.HabiticaAlertDialog
import javax.inject.Inject
import javax.inject.Named
@ -38,6 +39,8 @@ class QuestDetailFragment : BaseMainFragment<FragmentQuestDetailBinding>() {
lateinit var inventoryRepository: InventoryRepository
@field:[Inject Named(AppModule.NAMED_USER_ID)]
lateinit var userId: String
@Inject
lateinit var userViewModel: MainUserViewModel
override var binding: FragmentQuestDetailBinding? = null
@ -101,7 +104,7 @@ class QuestDetailFragment : BaseMainFragment<FragmentQuestDetailBinding>() {
compositeSubscription.add(
socialRepository.getMember(quest?.leader).subscribe(
{ member ->
if (context != null && binding?.questLeaderView != null && member != null) {
if (context != null && binding?.questLeaderView != null) {
binding?.questLeaderView?.text = context?.getString(R.string.quest_leader_header, member.displayName)
}
},
@ -109,6 +112,7 @@ class QuestDetailFragment : BaseMainFragment<FragmentQuestDetailBinding>() {
)
)
val user = userViewModel.user.value
if (binding?.questResponseWrapper != null) {
if (userId != party?.quest?.leader && user?.party?.quest?.key == group.quest?.key && user?.party?.quest?.RSVPNeeded == false) {
binding?.questLeaveButton?.visibility = View.VISIBLE

View file

@ -29,6 +29,7 @@ import com.habitrpg.android.habitica.ui.viewHolders.tasks.DailyViewHolder
import com.habitrpg.android.habitica.ui.viewHolders.tasks.HabitViewHolder
import com.habitrpg.android.habitica.ui.viewHolders.tasks.RewardViewHolder
import com.habitrpg.android.habitica.ui.viewHolders.tasks.TodoViewHolder
import com.habitrpg.android.habitica.ui.viewmodels.MainUserViewModel
import com.habitrpg.android.habitica.ui.views.HabiticaIconsHelper
import com.habitrpg.android.habitica.ui.views.dialogs.HabiticaAlertDialog
import retrofit2.HttpException
@ -41,6 +42,9 @@ class ChallengeDetailFragment : BaseMainFragment<FragmentChallengeDetailBinding>
lateinit var challengeRepository: ChallengeRepository
@Inject
lateinit var socialRepository: SocialRepository
@Inject
lateinit var userViewModel: MainUserViewModel
override var binding: FragmentChallengeDetailBinding? = null
@ -236,7 +240,7 @@ class ChallengeDetailFragment : BaseMainFragment<FragmentChallengeDetailBinding>
binding?.creatorAvatarview?.setAvatar(creator)
binding?.creatorLabel?.tier = creator.contributor?.level ?: 0
binding?.creatorLabel?.username = creator.displayName
isCreator = creator.id == user?.id
isCreator = creator.id == userViewModel.userID
this.activity?.invalidateOptionsMenu()
}

View file

@ -30,6 +30,7 @@ import com.habitrpg.android.habitica.ui.activities.GroupFormActivity
import com.habitrpg.android.habitica.ui.fragments.BaseMainFragment
import com.habitrpg.android.habitica.ui.helpers.DataBindingUtils
import com.habitrpg.android.habitica.ui.helpers.setMarkdown
import com.habitrpg.android.habitica.ui.viewmodels.MainUserViewModel
import com.habitrpg.android.habitica.ui.views.HabiticaSnackbar
import javax.inject.Inject
import kotlin.math.roundToInt
@ -40,6 +41,8 @@ class NoPartyFragmentFragment : BaseMainFragment<FragmentNoPartyBinding>() {
lateinit var socialRepository: SocialRepository
@Inject
lateinit var configManager: AppConfigManager
@Inject
lateinit var userViewModel: MainUserViewModel
override var binding: FragmentNoPartyBinding? = null
@ -65,7 +68,7 @@ class NoPartyFragmentFragment : BaseMainFragment<FragmentNoPartyBinding>() {
parentFragmentManager.popBackStack()
MainNavigationController.navigate(
R.id.partyFragment,
bundleOf(Pair("partyID", user?.party?.id))
bundleOf(Pair("partyID", userViewModel.partyID))
)
},
RxErrorHandler.handleEmptyError()
@ -92,7 +95,7 @@ class NoPartyFragmentFragment : BaseMainFragment<FragmentNoPartyBinding>() {
binding?.usernameTextview?.setOnClickListener {
val clipboard = context?.getSystemService(Context.CLIPBOARD_SERVICE) as? ClipboardManager
val clip = ClipData.newPlainText(context?.getString(R.string.username), user?.username)
val clip = ClipData.newPlainText(context?.getString(R.string.username), userViewModel.username)
clipboard?.setPrimaryClip(clip)
val activity = activity
if (activity != null) {
@ -103,7 +106,7 @@ class NoPartyFragmentFragment : BaseMainFragment<FragmentNoPartyBinding>() {
binding?.createPartyButton?.setOnClickListener {
val bundle = Bundle()
bundle.putString("groupType", "party")
bundle.putString("leader", user?.id)
bundle.putString("leader", userViewModel.userID)
val intent = Intent(activity, GroupFormActivity::class.java)
intent.putExtras(bundle)
intent.flags = Intent.FLAG_ACTIVITY_REORDER_TO_FRONT
@ -132,14 +135,15 @@ class NoPartyFragmentFragment : BaseMainFragment<FragmentNoPartyBinding>() {
}
}
if ((user?.invitations?.parties?.count() ?: 0) > 0) {
val partyInvitations = userViewModel.partyInvitations
if (partyInvitations.size > 0) {
binding?.invitationWrapper?.visibility = View.VISIBLE
user?.invitations?.parties?.let { binding?.invitationsView?.setInvitations(it) }
binding?.invitationsView?.setInvitations(partyInvitations)
} else {
binding?.invitationWrapper?.visibility = View.GONE
}
binding?.usernameTextview?.text = user?.formattedUsername
binding?.usernameTextview?.text = userViewModel.formattedUsername
}
private val groupFormResult = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
@ -164,7 +168,7 @@ class NoPartyFragmentFragment : BaseMainFragment<FragmentNoPartyBinding>() {
}
MainNavigationController.navigate(
R.id.partyFragment,
bundleOf(Pair("partyID", user?.party?.id))
bundleOf(Pair("partyID", userViewModel.partyID))
)
},
RxErrorHandler.handleEmptyError()
@ -196,12 +200,11 @@ class NoPartyFragmentFragment : BaseMainFragment<FragmentNoPartyBinding>() {
companion object {
fun newInstance(user: User?): NoPartyFragmentFragment {
fun newInstance(): NoPartyFragmentFragment {
val args = Bundle()
val fragment = NoPartyFragmentFragment()
fragment.arguments = args
fragment.user = user
return fragment
}
}

View file

@ -96,15 +96,11 @@ class PartyFragment : BaseMainFragment<FragmentViewpagerBinding>() {
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
val group = viewModel.getGroupData().value
if (group != null && this.user != null) {
if (group.leaderID == this.user?.id) {
inflater.inflate(R.menu.menu_party_admin, menu)
if (group.memberCount > 1) {
menu.findItem(R.id.menu_guild_leave).isVisible = false
}
} else {
inflater.inflate(R.menu.menu_party, menu)
}
if (viewModel.isLeader) {
inflater.inflate(R.menu.menu_party_admin, menu)
menu.findItem(R.id.menu_guild_leave).isVisible = group?.memberCount != 1
} else {
inflater.inflate(R.menu.menu_party, menu)
}
}
@ -159,7 +155,7 @@ class PartyFragment : BaseMainFragment<FragmentViewpagerBinding>() {
private val sendInvitesResult = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
if (it.resultCode == Activity.RESULT_OK) {
val inviteData = HashMap<String, Any>()
inviteData["inviter"] = user?.profile?.name ?: ""
inviteData["inviter"] = viewModel.user.value?.profile?.name ?: ""
val emails = it.data?.getStringArrayExtra(GroupInviteActivity.EMAILS_KEY)
if (emails != null && emails.isNotEmpty()) {
val invites = ArrayList<HashMap<String, String>>()

View file

@ -20,6 +20,7 @@ import com.habitrpg.android.habitica.helpers.DeviceName
import com.habitrpg.android.habitica.helpers.MainNavigationController
import com.habitrpg.android.habitica.modules.AppModule
import com.habitrpg.android.habitica.ui.fragments.BaseMainFragment
import com.habitrpg.android.habitica.ui.viewmodels.MainUserViewModel
import io.reactivex.rxjava3.core.Completable
import io.reactivex.rxjava3.schedulers.Schedulers
import javax.inject.Inject
@ -42,6 +43,8 @@ class BugFixFragment : BaseMainFragment<FragmentSupportBugFixBinding>() {
@Inject
lateinit var appConfigManager: AppConfigManager
@Inject
lateinit var userViewModel: MainUserViewModel
override fun injectFragment(component: UserComponent) {
component.inject(this)
@ -124,8 +127,7 @@ class BugFixFragment : BaseMainFragment<FragmentSupportBugFixBinding>() {
}
bodyOfEmail += newLine + Uri.encode("User ID: $userId")
val user = this.user
if (user != null) {
userViewModel.user.value?.let { user ->
bodyOfEmail += newLine + Uri.encode("Level: " + (user.stats?.lvl ?: 0)) +
newLine + Uri.encode(
"Class: " + (if (user.preferences?.disableClasses == true) "Disabled" else (user.stats?.habitClass

View file

@ -19,7 +19,7 @@ class MountViewHolder(parent: ViewGroup, private val equipEvents: PublishSubject
private var binding: MountOverviewItemBinding = MountOverviewItemBinding.bind(itemView)
private var owned: Boolean = false
var animal: Mount? = null
private var user: User? = null
private var currentMount: String? = null
var resources: Resources = itemView.resources
@ -27,10 +27,10 @@ class MountViewHolder(parent: ViewGroup, private val equipEvents: PublishSubject
itemView.setOnClickListener(this)
}
fun bind(item: Mount, owned: Boolean, user: User?) {
fun bind(item: Mount, owned: Boolean, currentMount: String?) {
animal = item
this.owned = owned
this.user = user
this.currentMount = currentMount
binding.titleTextView.visibility = View.GONE
binding.ownedTextView.visibility = View.GONE
val imageName = "stable_Mount_Icon_" + item.animal + "-" + item.color
@ -39,7 +39,7 @@ class MountViewHolder(parent: ViewGroup, private val equipEvents: PublishSubject
binding.imageView.alpha = 0.2f
}
binding.imageView.background = null
binding.activeIndicator.visibility = if (user?.currentMount.equals(animal?.key)) View.VISIBLE else View.GONE
binding.activeIndicator.visibility = if (currentMount.equals(animal?.key)) View.VISIBLE else View.GONE
DataBindingUtils.loadImage(itemView.context, imageName) {
val drawable = if (owned) it else BitmapDrawable(itemView.context.resources, it.toBitmap().extractAlpha())
binding.imageView.background = drawable
@ -53,7 +53,7 @@ class MountViewHolder(parent: ViewGroup, private val equipEvents: PublishSubject
val menu = BottomSheetMenu(itemView.context)
menu.setTitle(animal?.text)
val hasCurrentMount = user?.currentMount.equals(animal?.key)
val hasCurrentMount = currentMount.equals(animal?.key)
val labelId = if (hasCurrentMount) R.string.unequip else R.string.equip
menu.addMenuItem(BottomSheetMenuItem(resources.getString(labelId)))
menu.setSelectionRunnable {

View file

@ -24,7 +24,7 @@ class PetViewHolder(parent: ViewGroup, private val equipEvents: PublishSubject<S
private var potionCount: Int = 0
private var ownsSaddles = false
private var animal: Pet? = null
private var user: User? = null
private var currentPet: String? = null
private var binding: PetDetailItemBinding = PetDetailItemBinding.bind(itemView)
@ -49,7 +49,7 @@ class PetViewHolder(parent: ViewGroup, private val equipEvents: PublishSubject<S
hasUnlockedEgg: Boolean,
hasUnlockedPotion: Boolean,
hasMount: Boolean,
user: User?
currentPet: String?
) {
this.animal = item
isOwned = trained > 0
@ -61,7 +61,7 @@ class PetViewHolder(parent: ViewGroup, private val equipEvents: PublishSubject<S
this.hasUnlockedEgg = hasUnlockedEgg
this.hasUnlockedPotion = hasUnlockedPotion
this.hasMount = hasMount
this.user = user
this.currentPet = currentPet
binding.imageView.visibility = View.VISIBLE
binding.itemWrapper.visibility = View.GONE
binding.checkmarkView.visibility = View.GONE
@ -93,7 +93,7 @@ class PetViewHolder(parent: ViewGroup, private val equipEvents: PublishSubject<S
binding.trainedProgressBar.progressBackgroundTintMode = PorterDuff.Mode.SRC_OVER
}
binding.imageView.background = null
binding.activeIndicator.visibility = if (user?.currentPet.equals(animal?.key)) View.VISIBLE else View.GONE
binding.activeIndicator.visibility = if (currentPet.equals(animal?.key)) View.VISIBLE else View.GONE
DataBindingUtils.loadImage(itemView.context, imageName) {
val resources = itemView.context.resources ?: return@loadImage
val drawable = if (trained == 0) BitmapDrawable(resources, it.toBitmap().extractAlpha()) else it
@ -110,7 +110,7 @@ class PetViewHolder(parent: ViewGroup, private val equipEvents: PublishSubject<S
val menu = BottomSheetMenu(context)
menu.setTitle(animal?.text)
val hasCurrentPet = user?.currentPet.equals(animal?.key)
val hasCurrentPet = currentPet.equals(animal?.key)
val labelId = if (hasCurrentPet) R.string.unequip else R.string.equip
menu.addMenuItem(BottomSheetMenuItem(itemView.resources.getString(labelId)))

View file

@ -15,20 +15,13 @@ import javax.inject.Inject
abstract class BaseViewModel(initializeComponent: Boolean = true) : ViewModel() {
val isUserFainted: Boolean
get() = (user.value?.stats?.hp ?: 1.0) == 0.0
val isUserInParty: Boolean
get() = user.value?.hasParty == true
@Inject
lateinit var userRepository: UserRepository
@Inject
lateinit var userViewModel: MainUserViewModel
private val _user: MutableLiveData<User?> by lazy {
loadUserFromLocal()
MutableLiveData<User?>()
}
val user: LiveData<User?> by lazy {
_user
userViewModel.user
}
init {
@ -47,11 +40,6 @@ abstract class BaseViewModel(initializeComponent: Boolean = true) : ViewModel()
internal val disposable = CompositeDisposable()
internal fun loadUserFromLocal() {
disposable.add(userRepository.getUser().observeOn(AndroidSchedulers.mainThread())
.subscribe({ _user.value = it }, RxErrorHandler.handleEmptyError()))
}
fun updateUser(path: String, value: Any) {
disposable.add(userRepository.updateUser(path, value)
.subscribe({ }, RxErrorHandler.handleEmptyError()))

View file

@ -0,0 +1,62 @@
package com.habitrpg.android.habitica.ui.viewmodels
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import com.habitrpg.android.habitica.HabiticaBaseApplication
import com.habitrpg.android.habitica.components.UserComponent
import com.habitrpg.android.habitica.data.UserRepository
import com.habitrpg.android.habitica.helpers.RxErrorHandler
import com.habitrpg.android.habitica.models.invitations.GenericInvitation
import com.habitrpg.android.habitica.models.invitations.PartyInvite
import com.habitrpg.android.habitica.models.user.User
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
import io.reactivex.rxjava3.disposables.CompositeDisposable
import javax.inject.Inject
class MainUserViewModel(val userRepository: UserRepository) {
val formattedUsername: CharSequence?
get() = user.value?.formattedUsername
val partyInvitations: List<PartyInvite>
get() = user.value?.invitations?.parties ?: emptyList()
val userID: String?
get() = user.value?.id
val username: CharSequence
get() = user.value?.username ?: ""
val partyID: String?
get() = user.value?.party?.id
val isUserFainted: Boolean
get() = (user.value?.stats?.hp ?: 1.0) == 0.0
val isUserInParty: Boolean
get() = user.value?.hasParty == true
private val _user: MutableLiveData<User?> by lazy {
loadUserFromLocal()
MutableLiveData<User?>()
}
val user: LiveData<User?> by lazy {
_user
}
init {
HabiticaBaseApplication.userComponent?.inject(this)
}
fun onCleared() {
userRepository.close()
disposable.clear()
}
internal val disposable = CompositeDisposable()
internal fun loadUserFromLocal() {
disposable.add(userRepository.getUser().observeOn(AndroidSchedulers.mainThread())
.subscribe({ _user.value = it }, RxErrorHandler.handleEmptyError()))
}
fun updateUser(path: String, value: Any) {
disposable.add(userRepository.updateUser(path, value)
.subscribe({ }, RxErrorHandler.handleEmptyError()))
}
}

View file

@ -9,6 +9,10 @@ import com.habitrpg.android.habitica.ui.viewmodels.BaseViewModel
import javax.inject.Inject
class EquipmentOverviewViewModel(savedStateHandle: SavedStateHandle): BaseViewModel() {
val usesAutoEquip: Boolean
get() = user.value?.preferences?.autoEquip == true
val usesCostume: Boolean
get() = user.value?.preferences?.costume == true
@Inject
lateinit var inventoryRepository: InventoryRepository