mirror of
https://github.com/sudoxnym/habitica-android.git
synced 2026-05-18 19:59:00 +00:00
Ability to use special items from Items added
This commit is contained in:
parent
741b59b46b
commit
dfbcdc7125
8 changed files with 181 additions and 44 deletions
|
|
@ -466,6 +466,7 @@
|
|||
<string name="myster_item_notes">Each month, subscribers will receive a mystery item. This is usually released about one week before the end of the month.</string>
|
||||
<string name="open">Open</string>>
|
||||
<string name="is_open">Open</string>
|
||||
<string name="use_item">Use Item on party member</string>>
|
||||
<string name="checkInRewardEarned">You earned a %1$s as a reward for your devotion to improving your life.</string>
|
||||
<string name="nextPrizeUnlocks" tools:ignore="PluralsCandidate">Next prize in %1$d Check-Ins</string>
|
||||
<string name="pending_approval">pending approval</string>
|
||||
|
|
|
|||
|
|
@ -24,7 +24,6 @@ class ContentRepositoryImpl<T : ContentLocalRepository>(localRepository: T, apiC
|
|||
return if (forced || now - this.lastContentSync > 300000) {
|
||||
lastContentSync = now
|
||||
apiClient.content.doOnNext {
|
||||
it.special = RealmList()
|
||||
it.special.add(mysteryItem)
|
||||
localRepository.saveContent(it)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ open class RealmContentLocalRepository(realm: Realm) : RealmBaseLocalRepository(
|
|||
realm1.insertOrUpdate(contentResult.mounts)
|
||||
|
||||
realm1.insertOrUpdate(contentResult.spells)
|
||||
realm1.insertOrUpdate(contentResult.special)
|
||||
realm1.insertOrUpdate(contentResult.appearances)
|
||||
realm1.insertOrUpdate(contentResult.backgrounds)
|
||||
realm1.insertOrUpdate(contentResult.faq)
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ open class SpecialItem : RealmObject(), Item {
|
|||
internal var notes: String = ""
|
||||
override var value: Int = 0
|
||||
override var event: ItemEvent? = null
|
||||
var target: String? = null
|
||||
var isMysteryItem: Boolean = false
|
||||
|
||||
companion object {
|
||||
|
|
|
|||
|
|
@ -17,4 +17,19 @@ open class SpecialItems : RealmObject(), BaseObject {
|
|||
get() {
|
||||
return seafoam > 0 || shinySeed > 0 || snowball > 0 || spookySparkles > 0
|
||||
}
|
||||
|
||||
fun getSpecialItemCount(key: String): Int{
|
||||
var inventoryPresent: OwnedItem = ownedItems?.filter { it.key == "inventory_present" }?.single() ?: OwnedItem()
|
||||
|
||||
var count = 0
|
||||
when(key){
|
||||
"seafoam" -> count = seafoam
|
||||
"shinySeed" -> count = shinySeed
|
||||
"snowball" -> count = snowball
|
||||
"spookySparkles" -> count = spookySparkles
|
||||
"inventory_present" -> count = inventoryPresent.numberOwned
|
||||
}
|
||||
return count
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ import com.habitrpg.android.habitica.models.Skill
|
|||
import com.habitrpg.android.habitica.models.inventory.*
|
||||
import com.habitrpg.android.habitica.models.user.OwnedItem
|
||||
import com.habitrpg.android.habitica.models.user.OwnedPet
|
||||
import com.habitrpg.android.habitica.models.user.SpecialItems
|
||||
import com.habitrpg.android.habitica.ui.adapter.BaseRecyclerViewAdapter
|
||||
import com.habitrpg.android.habitica.ui.helpers.DataBindingUtils
|
||||
import com.habitrpg.android.habitica.ui.menu.BottomSheetMenu
|
||||
|
|
@ -38,6 +39,11 @@ class ItemRecyclerAdapter(val context: Context) : BaseRecyclerViewAdapter<OwnedI
|
|||
field = value
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
var specialItems: SpecialItems? = null
|
||||
set(value) {
|
||||
field = value
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
|
||||
private val sellItemEvents = PublishSubject.create<OwnedItem>()
|
||||
private val questInvitationEvents = PublishSubject.create<QuestContent>()
|
||||
|
|
@ -45,6 +51,8 @@ class ItemRecyclerAdapter(val context: Context) : BaseRecyclerViewAdapter<OwnedI
|
|||
private val startHatchingSubject = PublishSubject.create<Item>()
|
||||
private val hatchPetSubject = PublishSubject.create<Pair<HatchingPotion, Egg>>()
|
||||
private val feedPetSubject = PublishSubject.create<Food>()
|
||||
private val useSpecialSubject = PublishSubject.create<SpecialItem>()
|
||||
|
||||
|
||||
fun getSellItemFlowable(): Flowable<OwnedItem> {
|
||||
return sellItemEvents.toFlowable(BackpressureStrategy.DROP)
|
||||
|
|
@ -60,6 +68,7 @@ class ItemRecyclerAdapter(val context: Context) : BaseRecyclerViewAdapter<OwnedI
|
|||
val startHatchingEvents: Flowable<Item> = startHatchingSubject.toFlowable(BackpressureStrategy.DROP)
|
||||
val hatchPetEvents: Flowable<Pair<HatchingPotion, Egg>> = hatchPetSubject.toFlowable(BackpressureStrategy.DROP)
|
||||
val feedPetEvents: Flowable<Food> = feedPetSubject.toFlowable(BackpressureStrategy.DROP)
|
||||
val useSpecialEvents: Flowable<SpecialItem> = useSpecialSubject.toFlowable(BackpressureStrategy.DROP)
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder {
|
||||
return ItemViewHolder(ItemItemBinding.inflate(context.layoutInflater, parent, false))
|
||||
|
|
@ -111,14 +120,15 @@ class ItemRecyclerAdapter(val context: Context) : BaseRecyclerViewAdapter<OwnedI
|
|||
val imageName: String?
|
||||
if (item is QuestContent) {
|
||||
imageName = "inventory_quest_scroll_" + ownedItem.key
|
||||
} else if (ownedItem.itemType == "special") {
|
||||
if (item is SpecialItem){
|
||||
} else if (item is SpecialItem) {
|
||||
if (item.key == "inventory_present") {
|
||||
val sdf = SimpleDateFormat("MM", Locale.getDefault())
|
||||
val month = sdf.format(Date())
|
||||
imageName = "inventory_present_$month"
|
||||
}else{
|
||||
} else {
|
||||
imageName = "shop_" + ownedItem.key
|
||||
}
|
||||
|
||||
} else {
|
||||
val type = when (ownedItem.itemType) {
|
||||
"eggs" -> "Egg"
|
||||
|
|
@ -161,7 +171,10 @@ class ItemRecyclerAdapter(val context: Context) : BaseRecyclerViewAdapter<OwnedI
|
|||
val specialItem = item as SpecialItem
|
||||
if (specialItem.isMysteryItem && ownedItem?.numberOwned ?: 0 > 0) {
|
||||
menu.addMenuItem(BottomSheetMenuItem(resources.getString(R.string.open)))
|
||||
} else if (ownedItem?.numberOwned ?: 0 > 0){
|
||||
menu.addMenuItem(BottomSheetMenuItem(resources.getString(R.string.use_item)))
|
||||
}
|
||||
|
||||
}
|
||||
menu.setSelectionRunnable { index ->
|
||||
item?.let { selectedItem ->
|
||||
|
|
@ -181,7 +194,7 @@ class ItemRecyclerAdapter(val context: Context) : BaseRecyclerViewAdapter<OwnedI
|
|||
questInvitationEvents.onNext(selectedItem)
|
||||
}
|
||||
}
|
||||
is SpecialItem -> openMysteryItemEvents.onNext(selectedItem)
|
||||
is SpecialItem -> useSpecialSubject.onNext(selectedItem)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -209,16 +222,16 @@ class ItemRecyclerAdapter(val context: Context) : BaseRecyclerViewAdapter<OwnedI
|
|||
}
|
||||
}
|
||||
|
||||
fun setSpecialItems(skillItems: List<Skill>, ownedItems: MutableList<OwnedItem>){
|
||||
fun setSpecialItems(skillItems: List<Item>){
|
||||
val transformationItems: MutableList<OwnedItem> = mutableListOf()
|
||||
for (item in skillItems){
|
||||
val ownedTransformationItem = OwnedItem()
|
||||
ownedTransformationItem.key = item.key
|
||||
ownedTransformationItem.itemType = item.habitClass
|
||||
ownedTransformationItem.numberOwned = 5 //Test
|
||||
ownedTransformationItem.itemType = "special"
|
||||
ownedTransformationItem.numberOwned = specialItems?.getSpecialItemCount(item.key) ?: 0
|
||||
transformationItems.add(ownedTransformationItem)
|
||||
}
|
||||
data = ownedItems + transformationItems
|
||||
data = transformationItems
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,15 @@
|
|||
package com.habitrpg.android.habitica.ui.fragments.inventory.items
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Intent
|
||||
import android.graphics.drawable.BitmapDrawable
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||
import com.habitrpg.android.habitica.R
|
||||
import com.habitrpg.android.habitica.components.UserComponent
|
||||
|
|
@ -16,18 +22,28 @@ import com.habitrpg.android.habitica.extensions.subscribeWithErrorHandler
|
|||
import com.habitrpg.android.habitica.helpers.MainNavigationController
|
||||
import com.habitrpg.android.habitica.helpers.RxErrorHandler
|
||||
import com.habitrpg.android.habitica.interactors.HatchPetUseCase
|
||||
import com.habitrpg.android.habitica.models.Skill
|
||||
import com.habitrpg.android.habitica.models.inventory.*
|
||||
import com.habitrpg.android.habitica.models.responses.SkillResponse
|
||||
import com.habitrpg.android.habitica.models.user.OwnedItem
|
||||
import com.habitrpg.android.habitica.models.user.OwnedPet
|
||||
import com.habitrpg.android.habitica.models.user.User
|
||||
import com.habitrpg.android.habitica.ui.activities.BaseActivity
|
||||
import com.habitrpg.android.habitica.ui.activities.MainActivity
|
||||
import com.habitrpg.android.habitica.ui.activities.SkillMemberActivity
|
||||
import com.habitrpg.android.habitica.ui.activities.SkillTasksActivity
|
||||
import com.habitrpg.android.habitica.ui.adapter.inventory.ItemRecyclerAdapter
|
||||
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.views.HabiticaIconsHelper
|
||||
import com.habitrpg.android.habitica.ui.views.HabiticaSnackbar
|
||||
import com.habitrpg.android.habitica.ui.views.dialogs.OpenedMysteryitemDialog
|
||||
import io.reactivex.rxjava3.core.Flowable
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import java.util.ArrayList
|
||||
import javax.inject.Inject
|
||||
|
||||
class ItemRecyclerFragment : BaseFragment<FragmentItemsBinding>(), SwipeRefreshLayout.OnRefreshListener {
|
||||
|
|
@ -46,6 +62,7 @@ class ItemRecyclerFragment : BaseFragment<FragmentItemsBinding>(), SwipeRefreshL
|
|||
var transformationItems: MutableList<OwnedItem> = mutableListOf()
|
||||
var itemTypeText: String? = null
|
||||
var user: User? = null
|
||||
private var selectedSpecialItem: SpecialItem? = null
|
||||
internal var layoutManager: androidx.recyclerview.widget.LinearLayoutManager? = null
|
||||
|
||||
override var binding: FragmentItemsBinding? = null
|
||||
|
|
@ -91,7 +108,8 @@ class ItemRecyclerFragment : BaseFragment<FragmentItemsBinding>(), SwipeRefreshL
|
|||
adapter = ItemRecyclerAdapter(context)
|
||||
}
|
||||
binding?.recyclerView?.adapter = adapter
|
||||
|
||||
adapter?.specialItems = this.user?.items?.special
|
||||
adapter?.useSpecialEvents?.subscribeWithErrorHandler { onSpecialItemSelected(it) }?.let { compositeSubscription.add(it) }
|
||||
adapter?.let { adapter ->
|
||||
compositeSubscription.add(
|
||||
adapter.getSellItemFlowable()
|
||||
|
|
@ -204,35 +222,72 @@ class ItemRecyclerFragment : BaseFragment<FragmentItemsBinding>(), SwipeRefreshL
|
|||
else -> Egg::class.java
|
||||
}
|
||||
itemType?.let { type ->
|
||||
compositeSubscription.add(
|
||||
inventoryRepository.getOwnedItems(type)
|
||||
.map { it.distinctBy { it.key } }
|
||||
.doOnNext { items ->
|
||||
adapter?.data = items
|
||||
if (itemType == "special") {
|
||||
transformationItems = items.toMutableList()
|
||||
userRepository.getTransformationItems()
|
||||
.subscribe { skillItems -> adapter?.setSpecialItems(skillItems, transformationItems) }
|
||||
if (type != "special"){
|
||||
compositeSubscription.add(
|
||||
inventoryRepository.getOwnedItems(type)
|
||||
.map { it.distinctBy { it.key } }
|
||||
.doOnNext { items ->
|
||||
adapter?.data = items
|
||||
// if (itemType == "special") {
|
||||
// transformationItems = items.toMutableList()
|
||||
// userRepository.getTransformationItems() //Get from RealmInventoryLocalRepository
|
||||
// .subscribe { skillItems -> adapter?.setSpecialItems(skillItems, transformationItems) }
|
||||
// }
|
||||
}
|
||||
}
|
||||
.map { items -> items.mapNotNull { it.key } }
|
||||
.flatMap {
|
||||
inventoryRepository.getItems(itemClass, it.toTypedArray())
|
||||
}
|
||||
.map {
|
||||
val itemMap = mutableMapOf<String, Item>()
|
||||
for (item in it) {
|
||||
itemMap[item.key] = item
|
||||
.map { items -> items.mapNotNull { it.key } }
|
||||
.flatMap {
|
||||
inventoryRepository.getItems(itemClass, it.toTypedArray())
|
||||
}
|
||||
itemMap
|
||||
.map {
|
||||
val itemMap = mutableMapOf<String, Item>()
|
||||
for (item in it) {
|
||||
itemMap[item.key] = item
|
||||
}
|
||||
itemMap
|
||||
}
|
||||
.subscribe(
|
||||
{ items ->
|
||||
adapter?.items = items
|
||||
},
|
||||
RxErrorHandler.handleEmptyError()
|
||||
)
|
||||
)
|
||||
} else {
|
||||
val specialItems = user?.items?.special
|
||||
val ownedItems = ArrayList<String>()
|
||||
if (specialItems != null) {
|
||||
ownedItems.add("inventory_present")
|
||||
if (specialItems.snowball > 0) {
|
||||
ownedItems.add("snowball")
|
||||
}
|
||||
.subscribe(
|
||||
{ items ->
|
||||
adapter?.items = items
|
||||
},
|
||||
RxErrorHandler.handleEmptyError()
|
||||
)
|
||||
)
|
||||
if (specialItems.shinySeed > 0) {
|
||||
ownedItems.add("shinySeed")
|
||||
}
|
||||
if (specialItems.seafoam > 0) {
|
||||
ownedItems.add("seafoam")
|
||||
}
|
||||
if (specialItems.spookySparkles > 0) {
|
||||
ownedItems.add("spookySparkles")
|
||||
}
|
||||
}
|
||||
if (ownedItems.size == 0) {
|
||||
ownedItems.add("")
|
||||
}
|
||||
compositeSubscription.add(
|
||||
inventoryRepository.getItems(SpecialItem::class.java, ownedItems.toTypedArray())
|
||||
.map { it.distinctBy { it.key } }
|
||||
.doOnNext { items ->
|
||||
adapter?.setSpecialItems(items)
|
||||
val itemMap = mutableMapOf<String, Item>()
|
||||
for (item in items) {
|
||||
itemMap[item.key] = item
|
||||
}
|
||||
adapter?.items = itemMap
|
||||
}
|
||||
.subscribe()
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
compositeSubscription.add(inventoryRepository.getPets().subscribe({ adapter?.setExistingPets(it) }, RxErrorHandler.handleEmptyError()))
|
||||
|
|
@ -251,6 +306,51 @@ class ItemRecyclerFragment : BaseFragment<FragmentItemsBinding>(), SwipeRefreshL
|
|||
MainNavigationController.navigate(R.id.marketFragment)
|
||||
}
|
||||
|
||||
private fun onSpecialItemSelected(specialItem: SpecialItem) {
|
||||
selectedSpecialItem = specialItem
|
||||
val intent = Intent(activity, SkillMemberActivity::class.java)
|
||||
memberSelectionResult.launch(intent)
|
||||
|
||||
}
|
||||
|
||||
private val memberSelectionResult = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
|
||||
if (it.resultCode == Activity.RESULT_OK) {
|
||||
useSpecialItem(selectedSpecialItem, it.data?.getStringExtra("member_id"))
|
||||
}
|
||||
}
|
||||
|
||||
private fun useSpecialItem(specialItem: SpecialItem?, memberID: String? = null) {
|
||||
if (specialItem == null || memberID == null) {
|
||||
return
|
||||
}
|
||||
|
||||
val observable: Flowable<SkillResponse> = userRepository.useSkill(specialItem.key, specialItem.target, memberID)
|
||||
|
||||
compositeSubscription.add(
|
||||
observable.subscribe(
|
||||
{ skillResponse -> this.displaySkillResult(specialItem) },
|
||||
RxErrorHandler.handleEmptyError()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
private fun displaySkillResult(specialItem: SpecialItem?) {
|
||||
if (!isAdded) return
|
||||
|
||||
val activity = activity as? MainActivity
|
||||
activity?.let {
|
||||
HabiticaSnackbar.showSnackbar(
|
||||
it.snackbarContainer,
|
||||
context?.getString(R.string.used_skill_without_mana, specialItem?.text),
|
||||
HabiticaSnackbar.SnackbarDisplayType.BLUE
|
||||
)
|
||||
}
|
||||
|
||||
compositeSubscription.add(
|
||||
userRepository.retrieveUser(false).subscribe({ }, RxErrorHandler.handleEmptyError())
|
||||
)
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
private const val ITEM_TYPE_KEY = "CLASS_TYPE_KEY"
|
||||
|
|
|
|||
|
|
@ -11,14 +11,7 @@ import com.habitrpg.android.habitica.models.ContentGear
|
|||
import com.habitrpg.android.habitica.models.ContentResult
|
||||
import com.habitrpg.android.habitica.models.FAQArticle
|
||||
import com.habitrpg.android.habitica.models.Skill
|
||||
import com.habitrpg.android.habitica.models.inventory.Customization
|
||||
import com.habitrpg.android.habitica.models.inventory.Egg
|
||||
import com.habitrpg.android.habitica.models.inventory.Equipment
|
||||
import com.habitrpg.android.habitica.models.inventory.Food
|
||||
import com.habitrpg.android.habitica.models.inventory.HatchingPotion
|
||||
import com.habitrpg.android.habitica.models.inventory.Mount
|
||||
import com.habitrpg.android.habitica.models.inventory.Pet
|
||||
import com.habitrpg.android.habitica.models.inventory.QuestContent
|
||||
import com.habitrpg.android.habitica.models.inventory.*
|
||||
import io.realm.RealmList
|
||||
import java.lang.reflect.Type
|
||||
|
||||
|
|
@ -101,6 +94,20 @@ class ContentDeserializer : JsonDeserializer<ContentResult> {
|
|||
result.spells.add(skill)
|
||||
}
|
||||
}
|
||||
|
||||
if (obj.has("special")) {//ToDo add special
|
||||
for ((classname, value) in obj.getAsJsonObject("special").entrySet()) {
|
||||
val skillItem = value.asJsonObject
|
||||
val special = SpecialItem()
|
||||
special.key = skillItem.get("key").asString
|
||||
special.text = skillItem.get("text").asString
|
||||
special.notes = skillItem.get("notes").asString
|
||||
special.target = skillItem.get("target").asString
|
||||
special.value = skillItem.get("value").asInt
|
||||
result.special.add(special)
|
||||
}
|
||||
}
|
||||
|
||||
result.appearances = context.deserialize(obj.get("appearances"), object : TypeToken<RealmList<Customization>>() {}.type)
|
||||
result.backgrounds = context.deserialize(obj.get("backgrounds"), object : TypeToken<RealmList<Customization>>() {}.type)
|
||||
val noBackground = Customization()
|
||||
|
|
|
|||
Loading…
Reference in a new issue