move more code to user viewmodel

This commit is contained in:
Phillip Thelen 2021-10-04 14:28:32 +02:00
parent 262e6252f6
commit 9e3ba67f13
12 changed files with 84 additions and 67 deletions

View file

@ -116,10 +116,12 @@ dependencies {
implementation 'com.nex3z:flow-layout:1.2.2'
implementation 'androidx.core:core-ktx:1.6.0'
implementation "androidx.lifecycle:lifecycle-extensions:2.2.0"
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1"
implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1"
implementation "androidx.lifecycle:lifecycle-common-java8:2.3.1"
implementation 'androidx.navigation:navigation-fragment-ktx:2.3.5'
implementation 'androidx.navigation:navigation-ui-ktx:2.3.5'
implementation "androidx.fragment:fragment-ktx:1.3.6"
implementation "androidx.paging:paging-runtime-ktx:3.0.1"
implementation 'com.plattysoft.leonids:LeonidsLib:1.3.2'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.2'

View file

@ -1183,4 +1183,5 @@
<string name="terms_of_service">Terms of Service</string>
<string name="damage_pending">%.01f dmg pending</string>
<string name="x_remaining">%s remaining</string>
<string name="sale_ends_in">Sale ends in %s</string>
</resources>

View file

@ -103,6 +103,7 @@ import com.habitrpg.android.habitica.ui.fragments.tasks.TeamBoardFragment;
import com.habitrpg.android.habitica.ui.viewmodels.GroupViewModel;
import com.habitrpg.android.habitica.ui.viewmodels.InboxViewModel;
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;
import com.habitrpg.android.habitica.ui.views.shops.PurchaseDialog;
import com.habitrpg.android.habitica.ui.views.social.ChatBarView;
@ -346,4 +347,6 @@ public interface UserComponent {
void inject(@NotNull PromoWebFragment promoWebFragment);
void inject(@NotNull ItemDialogFragment itemDialogFragment);
void inject(@NotNull EquipmentOverviewViewModel equipmentOverviewViewModel);
}

View file

@ -16,6 +16,7 @@ import androidx.core.os.bundleOf
import androidx.core.view.GravityCompat
import androidx.fragment.app.DialogFragment
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.SimpleItemAnimator
import com.habitrpg.android.habitica.HabiticaBaseApplication
import com.habitrpg.android.habitica.R
import com.habitrpg.android.habitica.data.ContentRepository
@ -181,6 +182,7 @@ class NavigationDrawerFragment : DialogFragment() {
binding?.recyclerView?.adapter = adapter
binding?.recyclerView?.layoutManager = androidx.recyclerview.widget.LinearLayoutManager(context)
(binding?.recyclerView?.itemAnimator as? SimpleItemAnimator)?.supportsChangeAnimations = false
initializeMenuItems()
subscriptions?.add(
@ -675,7 +677,7 @@ class NavigationDrawerFragment : DialogFragment() {
val diff = activePromo.endDate.time - Date().time
if (diff < (Duration.hours(1).inWholeMilliseconds)) Duration.seconds(1) else Duration.minutes(1)
}) {
promotedItem.subtitle = context?.getString(R.string.x_remaining, activePromo.endDate.getShortRemainingString())
promotedItem.subtitle = context?.getString(R.string.sale_ends_in, activePromo.endDate.getShortRemainingString())
updateItem(promotedItem)
}
} ?: run {

View file

@ -33,7 +33,6 @@ class EquipmentDetailFragment :
}
var type: String? = null
var typeText: String? = null
var equippedGear: String? = null
var isCostume: Boolean? = null

View file

@ -4,38 +4,25 @@ import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.viewModels
import com.habitrpg.android.habitica.components.UserComponent
import com.habitrpg.android.habitica.data.InventoryRepository
import com.habitrpg.android.habitica.databinding.FragmentEquipmentOverviewBinding
import com.habitrpg.android.habitica.helpers.MainNavigationController
import com.habitrpg.android.habitica.helpers.RxErrorHandler
import com.habitrpg.android.habitica.models.user.Gear
import com.habitrpg.android.habitica.models.user.User
import com.habitrpg.android.habitica.models.user.Outfit
import com.habitrpg.android.habitica.ui.fragments.BaseMainFragment
import javax.inject.Inject
import com.habitrpg.android.habitica.ui.viewmodels.inventory.equipment.EquipmentOverviewViewModel
class EquipmentOverviewFragment : BaseMainFragment<FragmentEquipmentOverviewBinding>() {
private val viewModel: EquipmentOverviewViewModel by viewModels()
override var binding: FragmentEquipmentOverviewBinding? = null
override fun createBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentEquipmentOverviewBinding {
return FragmentEquipmentOverviewBinding.inflate(inflater, container, false)
}
@Inject
lateinit var inventoryRepository: InventoryRepository
override var user: User?
get() = super.user
set(value) {
super.user = value
if (this::inventoryRepository.isInitialized) {
value?.items?.gear?.let {
updateGearData(it)
}
}
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
@ -46,22 +33,30 @@ class EquipmentOverviewFragment : BaseMainFragment<FragmentEquipmentOverviewBind
displayEquipmentDetailList(type, equipped, true)
}
binding?.autoEquipSwitch?.isChecked = user?.preferences?.autoEquip ?: false
binding?.costumeSwitch?.isChecked = user?.preferences?.costume ?: false
binding?.autoEquipSwitch?.setOnCheckedChangeListener { _, isChecked ->
if (isChecked == viewModel.user.value?.preferences?.autoEquip) return@setOnCheckedChangeListener
viewModel.updateUser("preferences.autoEquip", isChecked) }
binding?.costumeSwitch?.setOnCheckedChangeListener { _, isChecked ->
if (isChecked == viewModel.user.value?.preferences?.costume) return@setOnCheckedChangeListener
viewModel.updateUser("preferences.costume", isChecked) }
binding?.autoEquipSwitch?.setOnCheckedChangeListener { _, isChecked -> userRepository.updateUser("preferences.autoEquip", isChecked).subscribe({ }, RxErrorHandler.handleEmptyError()) }
binding?.costumeSwitch?.setOnCheckedChangeListener { _, isChecked -> userRepository.updateUser("preferences.costume", isChecked).subscribe({ }, RxErrorHandler.handleEmptyError()) }
viewModel.user.observe(viewLifecycleOwner) {
it?.items?.gear?.let {
updateGearData(it)
}
binding?.autoEquipSwitch?.isChecked = user?.preferences?.autoEquip ?: false
binding?.costumeSwitch?.isChecked = user?.preferences?.costume ?: false
user?.items?.gear?.let {
updateGearData(it)
if (user?.preferences?.costume == true) {
binding?.costumeView?.alpha = 1.0f
binding?.costumeView?.isEnabled = true
} else {
binding?.costumeView?.alpha = 0.6f
binding?.costumeView?.isEnabled = false
}
}
}
override fun onDestroy() {
inventoryRepository.close()
super.onDestroy()
}
override fun injectFragment(component: UserComponent) {
component.inject(this)
}
@ -71,31 +66,17 @@ class EquipmentOverviewFragment : BaseMainFragment<FragmentEquipmentOverviewBind
}
private fun updateGearData(gear: Gear) {
if (gear.equipped?.weapon?.isNotEmpty() == true) {
compositeSubscription.add(
inventoryRepository.getEquipment(gear.equipped?.weapon ?: "").firstElement()
.subscribe(
{
binding?.battlegearView?.updateData(gear.equipped, it.twoHanded)
},
RxErrorHandler.handleEmptyError()
)
)
updateOutfit(gear.equipped)
updateOutfit(gear.costume)
}
private fun updateOutfit(outfit: Outfit?) {
if (outfit?.weapon?.isNotEmpty() == true) {
viewModel.getGear(outfit.weapon) {
binding?.battlegearView?.updateData(outfit, it.twoHanded)
}
} else {
binding?.battlegearView?.updateData(gear.equipped)
}
if (gear.costume?.weapon?.isNotEmpty() == true) {
compositeSubscription.add(
inventoryRepository.getEquipment(gear.costume?.weapon ?: "").firstElement()
.subscribe(
{
binding?.costumeView?.updateData(gear.costume, it.twoHanded)
},
RxErrorHandler.handleEmptyError()
)
)
} else {
binding?.costumeView?.updateData(gear.costume)
binding?.battlegearView?.updateData(outfit)
}
}
}

View file

@ -101,7 +101,7 @@ class ChatFragment : BaseFragment<FragmentChatBinding>() {
viewModel?.updateUser("flags.communityGuidelinesAccepted", true)
}
viewModel?.getUserData()?.observe(
viewModel?.user?.observe(
viewLifecycleOwner,
{
chatAdapter?.user = it

View file

@ -111,7 +111,7 @@ class GuildDetailFragment : BaseFragment<FragmentGuildDetailBinding>() {
private val sendInvitesResult = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
if (it.resultCode == Activity.RESULT_OK) {
val inviteData = HashMap<String, Any>()
inviteData["inviter"] = viewModel?.getUserData()?.value?.profile?.name ?: ""
inviteData["inviter"] = viewModel?.user?.value?.profile?.name ?: ""
if (it.data?.getBooleanExtra(GroupInviteActivity.IS_EMAIL_KEY, false) == true) {
val emails = it.data?.getStringArrayExtra(GroupInviteActivity.EMAILS_KEY)
val invites = ArrayList<HashMap<String, String>>()

View file

@ -114,7 +114,7 @@ class PartyDetailFragment : BaseFragment<FragmentPartyDetailBinding>() {
}
viewModel?.getGroupData()?.observe(viewLifecycleOwner, { updateParty(it) })
viewModel?.getUserData()?.observe(viewLifecycleOwner, { updateUser(it) })
viewModel?.user?.observe(viewLifecycleOwner, { updateUser(it) })
viewModel?.getMembersData()?.observe(viewLifecycleOwner, { updateMembersList(it) })
}
@ -269,7 +269,7 @@ class PartyDetailFragment : BaseFragment<FragmentPartyDetailBinding>() {
}
) ?: return@forEachIndexed
val viewHolder = GroupMemberViewHolder(memberView)
viewHolder.bind(member, leaderID ?: "", viewModel?.getUserData()?.value?.id)
viewHolder.bind(member, leaderID ?: "", viewModel?.user?.value?.id)
viewHolder.onClickEvent = {
FullProfileActivity.open(member.id ?: "")
}

View file

@ -7,6 +7,7 @@ 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.inventory.Equipment
import com.habitrpg.android.habitica.models.user.User
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
import io.reactivex.rxjava3.disposables.CompositeDisposable
@ -17,10 +18,13 @@ abstract class BaseViewModel(initializeComponent: Boolean = true) : ViewModel()
@Inject
lateinit var userRepository: UserRepository
private val user: MutableLiveData<User?> by lazy {
private val _user: MutableLiveData<User?> by lazy {
loadUserFromLocal()
MutableLiveData<User?>()
}
val user: LiveData<User?> by lazy {
_user
}
init {
if (initializeComponent) {
@ -38,13 +42,13 @@ abstract class BaseViewModel(initializeComponent: Boolean = true) : ViewModel()
internal val disposable = CompositeDisposable()
fun getUserData(): LiveData<User?> = user
private fun loadUserFromLocal() {
disposable.add(userRepository.getUser().observeOn(AndroidSchedulers.mainThread()).subscribe({ user.value = it }, RxErrorHandler.handleEmptyError()))
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()))
disposable.add(userRepository.updateUser(path, value)
.subscribe({ }, RxErrorHandler.handleEmptyError()))
}
}

View file

@ -20,7 +20,7 @@ class PartyViewModel(initializeComponent: Boolean) : GroupViewModel(initializeCo
internal val isUserOnQuest: Boolean
get() = !(
getGroupData().value?.quest?.members?.none { it.key == getUserData().value?.id }
getGroupData().value?.quest?.members?.none { it.key == user.value?.id }
?: true
)
@ -88,7 +88,7 @@ class PartyViewModel(initializeComponent: Boolean) : GroupViewModel(initializeCo
}
fun showParticipantButtons(): Boolean {
val user = getUserData().value
val user = user.value
return !(user?.party == null || user.party?.quest == null) && !isQuestActive && user.party?.quest?.RSVPNeeded == true
}

View file

@ -0,0 +1,25 @@
package com.habitrpg.android.habitica.ui.viewmodels.inventory.equipment
import androidx.lifecycle.SavedStateHandle
import com.habitrpg.android.habitica.components.UserComponent
import com.habitrpg.android.habitica.data.InventoryRepository
import com.habitrpg.android.habitica.helpers.RxErrorHandler
import com.habitrpg.android.habitica.models.inventory.Equipment
import com.habitrpg.android.habitica.ui.viewmodels.BaseViewModel
import javax.inject.Inject
class EquipmentOverviewViewModel(savedStateHandle: SavedStateHandle): BaseViewModel() {
@Inject
lateinit var inventoryRepository: InventoryRepository
override fun inject(component: UserComponent) {
component.inject(this)
}
fun getGear(key: String, onSuccess: (Equipment) -> Unit) {
disposable.add(inventoryRepository.getEquipment(key).subscribe( {
onSuccess(it)
}, RxErrorHandler.handleEmptyError()))
}
}