Many Many more pet hatch modal states. Fixes #1342

This commit is contained in:
Phillip Thelen 2020-07-21 14:38:42 +02:00
parent a5ce77ff72
commit 2fdf81583d
10 changed files with 147 additions and 44 deletions

View file

@ -163,7 +163,7 @@ android {
resConfigs "en", "bg", "de", "en-rGB", "es", "fr", "hr-rHR", "in", "it", "iw", "ja", "ko", "lt", "nl", "pl", "pt-rBR", "pt-rPT", "ru", "tr", "zh", "zh-rTW"
versionCode 2485
versionName "2.7.1"
versionName "2.8"
}
viewBinding {

View file

@ -22,6 +22,8 @@
android:progressTint="@color/green_100"
android:progressBackgroundTint="@color/gray_600"
android:layout_marginTop="4dp"
android:layout_marginStart="9dp"
android:layout_marginEnd="9dp"
android:max="50" />
<LinearLayout
android:id="@+id/items_available_wrapper"
@ -42,7 +44,7 @@
</LinearLayout>
<RelativeLayout
android:id="@+id/item_wrapper"
android:layout_width="85dp"
android:layout_width="86dp"
android:layout_height="70dp"
android:layout_gravity="center">
<com.facebook.drawee.view.SimpleDraweeView

View file

@ -1058,11 +1058,19 @@
<string name="excessItemsNoneLeft">You already have everything you need for all %s pets. Are you sure you want to purchase %d %ss?</string>
<string name="equip">Equip</string>
<string name="view_onboarding_tasks">View Onboarding Tasks</string>
<string name="suggest_pet_hatch">You\'ll need a %s Egg and %s Potion to hatch this pet</string>
<string name="can_hatch_pet">You can use a %s Egg and a %s Potion to hatch this pet</string>
<string name="suggest_pet_hatch_missing_egg">You still need a %s Egg to hatch this pet</string>
<string name="suggest_pet_hatch_missing_potion">You still need a %s Potion to hatch this pet</string>
<string name="suggest_pet_hatch_missing_both">You need a %s and %s Potion to hatch this pet</string>
<string name="suggest_pet_hatch_again_missing_egg">You still need a %s Egg to hatch this pet again</string>
<string name="suggest_pet_hatch_again_missing_potion">You still need a %s Potion to hatch this pet again</string>
<string name="suggest_pet_hatch_again_missing_both">You need a %s and %s Potion to hatch this pet again</string>
<string name="can_hatch_pet">Combine your %s Egg and %s Potion to hatch this pet!</string>
<string name="hatch_pet">Hatch Pet</string>
<string name="unhatched_pet">Unhatched Pet</string>
<string name="hatch_pet_again">Hatch Pet again</string>
<string name="magic_potions">Magic Potions</string>
<string name="magic_potion">Magic Potion</string>
<string name="use_saddle">Use Saddle</string>
<string name="hatch_your_pet">Hatch your Pet</string>
<string name="hatch">Hatch</string>
</resources>

View file

@ -33,8 +33,8 @@ interface InventoryRepository : BaseRepository {
fun getOwnedEquipment(type: String): Flowable<RealmResults<Equipment>>
fun getEquipmentType(type: String, set: String): Flowable<RealmResults<Equipment>>
fun getOwnedItems(itemType: String): Flowable<RealmResults<OwnedItem>>
fun getOwnedItems(): Flowable<Map<String, OwnedItem>>
fun getOwnedItems(itemType: String, includeZero: Boolean = false): Flowable<RealmResults<OwnedItem>>
fun getOwnedItems(includeZero: Boolean = false): Flowable<Map<String, OwnedItem>>
fun getEquipment(key: String): Flowable<Equipment>

View file

@ -50,12 +50,12 @@ class InventoryRepositoryImpl(localRepository: InventoryLocalRepository, apiClie
return localRepository.getEquipmentType(type, set)
}
override fun getOwnedItems(itemType: String): Flowable<RealmResults<OwnedItem>> {
return localRepository.getOwnedItems(itemType, userID)
override fun getOwnedItems(itemType: String, includeZero: Boolean): Flowable<RealmResults<OwnedItem>> {
return localRepository.getOwnedItems(itemType, userID, includeZero)
}
override fun getOwnedItems(): Flowable<Map<String, OwnedItem>> {
return localRepository.getOwnedItems(userID)
override fun getOwnedItems(includeZero: Boolean): Flowable<Map<String, OwnedItem>> {
return localRepository.getOwnedItems(userID, includeZero)
}
override fun getItems(itemClass: Class<out Item>, keys: Array<String>, user: User?): Flowable<out RealmResults<out Item>> {
@ -111,7 +111,7 @@ class InventoryRepositoryImpl(localRepository: InventoryLocalRepository, apiClie
}
override fun sellItem(user: User?, type: String, key: String): Flowable<User> {
return localRepository.getOwnedItem(userID, type, key)
return localRepository.getOwnedItem(userID, type, key, true)
.flatMap { item -> sellItem(user, item) }
}

View file

@ -31,8 +31,8 @@ interface InventoryLocalRepository : ContentLocalRepository {
fun getOwnedEquipment(type: String): Flowable<RealmResults<Equipment>>
fun getItems(itemClass: Class<out Item>, keys: Array<String>, user: User?): Flowable<out RealmResults<out Item>>
fun getOwnedItems(itemType: String, userID: String): Flowable<RealmResults<OwnedItem>>
fun getOwnedItems(userID: String): Flowable<Map<String, OwnedItem>>
fun getOwnedItems(itemType: String, userID: String, includeZero: Boolean): Flowable<RealmResults<OwnedItem>>
fun getOwnedItems(userID: String, includeZero: Boolean): Flowable<Map<String, OwnedItem>>
fun getEquipmentType(type: String, set: String): Flowable<RealmResults<Equipment>>
fun getEquipment(key: String): Flowable<Equipment>
@ -45,7 +45,7 @@ interface InventoryLocalRepository : ContentLocalRepository {
fun changeOwnedCount(item: OwnedItem, amountToAdd: Int?)
fun getItem(type: String, key: String): Flowable<Item>
fun getOwnedItem(userID: String, type: String, key: String): Flowable<OwnedItem>
fun getOwnedItem(userID: String, type: String, key: String, includeZero: Boolean): Flowable<OwnedItem>
fun decrementMysteryItemCount(user: User?)
fun saveInAppRewards(onlineItems: List<ShopItem>)

View file

@ -79,10 +79,12 @@ class RealmInventoryLocalRepository(realm: Realm, private val context: Context)
.filter { it.isLoaded }
}
override fun getOwnedItems(itemType: String, userID: String): Flowable<RealmResults<OwnedItem>> {
return realm.where(OwnedItem::class.java)
.greaterThan("numberOwned", 0)
.equalTo("itemType", itemType)
override fun getOwnedItems(itemType: String, userID: String, includeZero: Boolean): Flowable<RealmResults<OwnedItem>> {
var query = realm.where(OwnedItem::class.java)
if (!includeZero) {
query = query.greaterThan("numberOwned", 0)
}
return query.equalTo("itemType", itemType)
.equalTo("userID", userID)
.sort("key")
.findAll()
@ -95,10 +97,12 @@ class RealmInventoryLocalRepository(realm: Realm, private val context: Context)
.filter { it.isLoaded }
}
override fun getOwnedItems(userID: String): Flowable<Map<String, OwnedItem>> {
return realm.where(OwnedItem::class.java)
.greaterThan("numberOwned", 0)
.equalTo("userID", userID)
override fun getOwnedItems(userID: String, includeZero: Boolean): Flowable<Map<String, OwnedItem>> {
var query = realm.where(OwnedItem::class.java)
if (!includeZero) {
query = query.greaterThan("numberOwned", 0)
}
return query.equalTo("userID", userID)
.findAll()
.asFlowable()
.map {
@ -185,7 +189,7 @@ class RealmInventoryLocalRepository(realm: Realm, private val context: Context)
}
override fun changeOwnedCount(type: String, key: String, userID: String, amountToAdd: Int) {
getOwnedItem(userID, type, key).firstElement().subscribe( Consumer { changeOwnedCount(it, amountToAdd)}, RxErrorHandler.handleEmptyError())
getOwnedItem(userID, type, key, true).firstElement().subscribe( Consumer { changeOwnedCount(it, amountToAdd)}, RxErrorHandler.handleEmptyError())
}
override fun changeOwnedCount(item: OwnedItem, amountToAdd: Int?) {
@ -194,13 +198,15 @@ class RealmInventoryLocalRepository(realm: Realm, private val context: Context)
}
}
override fun getOwnedItem(userID: String, type: String, key: String): Flowable<OwnedItem> {
return realm.where(OwnedItem::class.java)
override fun getOwnedItem(userID: String, type: String, key: String, includeZero: Boolean): Flowable<OwnedItem> {
var query = realm.where(OwnedItem::class.java)
.equalTo("itemType", type)
.equalTo("key", key)
.equalTo("userID", userID)
.greaterThan("numberOwned", 0)
.findFirstAsync()
if (!includeZero) {
query = query.greaterThan("numberOwned", 0)
}
return query.findFirstAsync()
.asFlowable<OwnedItem>()
.filter { realmObject -> realmObject.isLoaded }
}

View file

@ -114,11 +114,11 @@ class PetDetailRecyclerAdapter(data: OrderedRealmCollection<Pet>?, autoUpdate: B
private val hasEgg: Boolean
get() {
return ownedItems?.get(animal?.animal + "-eggs") != null
return ownedItems?.get(animal?.animal + "-eggs")?.numberOwned ?: 0 > 0
}
private val hasPotion: Boolean
get() {
return ownedItems?.get(animal?.color + "-hatchingPotions") != null
return ownedItems?.get(animal?.color + "-hatchingPotions")?.numberOwned ?: 0 > 0
}
private val canHatch: Boolean
@ -223,7 +223,14 @@ class PetDetailRecyclerAdapter(data: OrderedRealmCollection<Pet>?, autoUpdate: B
val dialog = PetSuggestHatchDialog(context)
animal?.let {
val ingredients = animalIngredientsRetriever?.invoke(it)
dialog.configure(it, ingredients?.first, ingredients?.second, canHatch)
dialog.configure(it,
ingredients?.first,
ingredients?.second,
hasEgg,
hasPotion,
ownedItems?.get(animal?.animal + "-eggs") != null,
ownedItems?.get(animal?.color + "-hatchingPotions") != null,
ownedMounts?.containsKey(it.key) == true)
}
dialog.show()
}

View file

@ -129,7 +129,7 @@ class PetDetailRecyclerFragment : BaseMainFragment() {
return@map mountMap
}
.subscribe(Consumer { adapter.setOwnedMounts(it) }, RxErrorHandler.handleEmptyError()))
compositeSubscription.add(inventoryRepository.getOwnedItems().subscribe(Consumer { adapter.setOwnedItems(it) }, RxErrorHandler.handleEmptyError()))
compositeSubscription.add(inventoryRepository.getOwnedItems(true).subscribe(Consumer { adapter.setOwnedItems(it) }, RxErrorHandler.handleEmptyError()))
compositeSubscription.add(inventoryRepository.getPets(animalType, animalGroup, animalColor).firstElement().subscribe(Consumer<RealmResults<Pet>> { adapter.updateData(it) }, RxErrorHandler.handleEmptyError()))
compositeSubscription.add(inventoryRepository.getMounts(animalType, animalGroup, animalColor).subscribe(Consumer<RealmResults<Mount>> { adapter.setExistingMounts(it) }, RxErrorHandler.handleEmptyError()))
}

View file

@ -3,20 +3,27 @@ package com.habitrpg.android.habitica.ui.views.dialogs
import android.content.Context
import android.graphics.drawable.BitmapDrawable
import android.view.LayoutInflater
import com.facebook.drawee.view.SimpleDraweeView
import android.widget.FrameLayout
import android.widget.LinearLayout
import android.widget.TextView
import androidx.core.content.ContextCompat
import com.habitrpg.android.habitica.R
import com.habitrpg.android.habitica.databinding.DialogPetSuggestHatchBinding
import com.habitrpg.android.habitica.helpers.MainNavigationController
import com.habitrpg.android.habitica.extensions.dpToPx
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.Item
import com.habitrpg.android.habitica.ui.activities.MainActivity
import com.habitrpg.android.habitica.ui.helpers.DataBindingUtils
import com.habitrpg.android.habitica.ui.views.CurrencyView
import io.reactivex.Flowable
import io.reactivex.Observable
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.functions.Consumer
class PetSuggestHatchDialog(context: Context) : HabiticaAlertDialog(context) {
@ -28,35 +35,101 @@ class PetSuggestHatchDialog(context: Context) : HabiticaAlertDialog(context) {
setAdditionalContentView(binding.root)
}
fun configure(pet: Animal, egg: Egg?, potion: HatchingPotion?, canHatch: Boolean) {
fun configure(pet: Animal, egg: Egg?, potion: HatchingPotion?, hasEgg: Boolean, hasPotion: Boolean, hasUnlockedEgg: Boolean, hasUnlockedPotion: Boolean, hasMount: Boolean) {
DataBindingUtils.loadImage(binding.eggView, "Pet_Egg_${pet.animal}")
DataBindingUtils.loadImage(binding.hatchingPotionView, "Pet_HatchingPotion_${pet.color}")
binding.petTitleView.text = pet.text
binding.eggView.alpha = if (hasEgg) 1.0f else 0.5f
binding.hatchingPotionView.alpha = if (hasPotion) 1.0f else 0.5f
if (canHatch) {
val eggName = egg?.text ?: pet.animal.capitalize()
val potionName = potion?.text ?: pet.color.capitalize()
if (hasEgg && hasPotion) {
binding.descriptionView.text = context.getString(R.string.can_hatch_pet,
egg?.text ?: pet.animal.capitalize(),
potion?.text ?: pet.color.capitalize())
addButton(R.string.hatch_pet, true, false) { _, _ ->
eggName,
potionName)
addButton(R.string.hatch, true, false) { _, _ ->
val thisPotion = potion ?: return@addButton
val thisEgg = egg ?: return@addButton
(getActivity() as? MainActivity)?.hatchPet(thisPotion, thisEgg)
}
setTitle(R.string.hatch_pet_title)
if (hasMount) {
setTitle(R.string.hatch_your_pet)
} else {
setTitle(R.string.hatch_pet_title)
}
addButton(R.string.close, false)
} else {
binding.descriptionView.text = context.getString(R.string.suggest_pet_hatch,
egg?.text ?: pet.animal.capitalize(),
potion?.text ?: pet.color.capitalize())
if (hasMount) {
if (!hasEgg && !hasPotion) {
binding.descriptionView.text = context.getString(R.string.suggest_pet_hatch_again_missing_both, eggName, potionName)
} else if (!hasEgg) {
binding.descriptionView.text = context.getString(R.string.suggest_pet_hatch_again_missing_egg, eggName)
} else {
binding.descriptionView.text = context.getString(R.string.suggest_pet_hatch_again_missing_potion, potionName)
}
} else {
if (!hasEgg && !hasPotion) {
binding.descriptionView.text = context.getString(R.string.suggest_pet_hatch_missing_both, eggName, potionName)
} else if (!hasEgg) {
binding.descriptionView.text = context.getString(R.string.suggest_pet_hatch_missing_egg, eggName)
} else {
binding.descriptionView.text = context.getString(R.string.suggest_pet_hatch_missing_potion, potionName)
}
}
var hatchPrice = 0
if (!hasEgg) {
hatchPrice = getItemPrice(pet, egg, hasUnlockedEgg)
}
if (!hasPotion) {
hatchPrice = getItemPrice(pet, potion, hasUnlockedPotion)
}
addButton(R.string.close, true)
if (hatchPrice > 0) {
val linearLayout = LinearLayout(context)
val label = TextView(context)
label.setText(R.string.hatch)
label.setTextColor(ContextCompat.getColor(context, R.color.colorPrimary))
linearLayout.addView(label)
val layoutParams: LinearLayout.LayoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT)
layoutParams.setMargins(0, 0, 4.dpToPx(context), 0)
label.layoutParams = layoutParams
val priceView = CurrencyView(context, "gems", true)
priceView.value = hatchPrice.toDouble()
linearLayout.addView(priceView)
addButton(linearLayout, true) { _, _ ->
val activity = (getActivity() as? MainActivity) ?: return@addButton
val thisPotion = potion ?: return@addButton
val thisEgg = egg ?: return@addButton
var observable: Flowable<Any> = Flowable.just("")
if (!hasEgg) {
observable = observable.flatMap { activity.inventoryRepository.purchaseItem("eggs", thisEgg.key, 1) }
}
if (!hasPotion) {
observable = observable.flatMap { activity.inventoryRepository.purchaseItem("hatchingPotions", thisPotion.key, 1) }
}
observable.subscribe(Consumer {
(getActivity() as? MainActivity)?.hatchPet(thisPotion, thisEgg)
}, RxErrorHandler.handleEmptyError())
}
}
setTitle(R.string.unhatched_pet)
}
addButton(R.string.close, !canHatch)
val imageName = "social_Pet-${pet.animal}-${pet.color}"
DataBindingUtils.loadImage(imageName) {
val resources = context.resources ?: return@loadImage
val drawable = BitmapDrawable(resources, it.extractAlpha())
val drawable = BitmapDrawable(resources, if (hasMount) it else it.extractAlpha())
Observable.just(drawable)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(Consumer {
@ -64,4 +137,11 @@ class PetSuggestHatchDialog(context: Context) : HabiticaAlertDialog(context) {
}, RxErrorHandler.handleEmptyError())
}
}
private fun getItemPrice(pet: Animal, item: Item?, hasUnlocked: Boolean): Int {
if (pet.type == "drop" || (pet.type == "quest" && hasUnlocked)) {
return item?.value ?: 0
}
return 0
}
}