diff --git a/Habitica/res/layout/dialog_purchase_customization.xml b/Habitica/res/layout/dialog_purchase_customization.xml index 26adb2384..c9c1ef4e0 100644 --- a/Habitica/res/layout/dialog_purchase_customization.xml +++ b/Habitica/res/layout/dialog_purchase_customization.xml @@ -1,44 +1,27 @@ - + - - - - - - - - - \ No newline at end of file + android:layout_height="wrap_content" + style="@style/Headline" + android:textColor="@color/text_primary" + tools:text="This is the Title" + android:gravity="center" + android:layout_marginTop="14dp" + android:layout_marginBottom="4dp"/> + \ No newline at end of file diff --git a/Habitica/res/layout/purchase_dialog_background.xml b/Habitica/res/layout/purchase_dialog_background.xml new file mode 100644 index 000000000..987007542 --- /dev/null +++ b/Habitica/res/layout/purchase_dialog_background.xml @@ -0,0 +1,35 @@ + + + + + + + \ No newline at end of file diff --git a/Habitica/res/values-zh-rTW/strings.xml b/Habitica/res/values-zh-rTW/strings.xml index 3a1c7dfbb..4c40fcd08 100644 --- a/Habitica/res/values-zh-rTW/strings.xml +++ b/Habitica/res/values-zh-rTW/strings.xml @@ -1044,7 +1044,7 @@ 取消裝備 你已經有得到所有%s寵物所需的一切物品。你確定你要買%2$d個%3$s? 買%d個 - 你只需要%d個%2$s即可孵化所有可得到的這種寵物。你確定你想要買%1$d個? + 你只需要%3$d個%2$s即可孵化所有可得到的這種寵物。你確定你想要買%1$d個? 完成任務有概率掉落寵物食品!這樣你就可以把寵物餵大長成坐騎啦! 多餘物品 你完成了新手任務! diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/UserRepository.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/data/UserRepository.kt index 6a2101bfa..7f8be410a 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/data/UserRepository.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/data/UserRepository.kt @@ -51,6 +51,7 @@ interface UserRepository : BaseRepository { fun changeClass(selectedClass: String): Flowable + fun unlockPath(user: User?, unlockPath: String?, type: String?, price: Int): Flowable fun unlockPath(user: User?, customization: Customization): Flowable fun unlockPath(set: CustomizationSet): Flowable diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/UserRepositoryImpl.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/UserRepositoryImpl.kt index f60500c31..7236c7e0e 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/UserRepositoryImpl.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/UserRepositoryImpl.kt @@ -162,9 +162,9 @@ class UserRepositoryImpl( override fun changeClass(selectedClass: String): Flowable = apiClient.changeClass(selectedClass) .flatMap { retrieveUser(false) } - override fun unlockPath(user: User?, customization: Customization): Flowable { - var path = customization.path - if (path.last() == '.' && customization.type == "background") { + override fun unlockPath(user: User?, unlockPath: String?, type: String?, price: Int): Flowable { + var path = unlockPath ?: return Flowable.empty() + if (path.last() == '.' && type == "background") { path += user?.preferences?.background } return zipWithLiveUser(apiClient.unlockPath(path)) { unlockResponse, copiedUser -> @@ -172,12 +172,16 @@ class UserRepositoryImpl( user.preferences = unlockResponse.preferences user.purchased = unlockResponse.purchased user.items = unlockResponse.items - user.balance = copiedUser.balance - (customization.price ?: 0) / 4.0 + user.balance = copiedUser.balance - (price / 4.0) localRepository.saveUser(copiedUser, false) unlockResponse } } + override fun unlockPath(user: User?, customization: Customization): Flowable { + return unlockPath(user, customization.path, customization.type, customization.price ?: 0) + } + override fun unlockPath(set: CustomizationSet): Flowable { var path = "" for (customization in set.customizations) { diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/models/shops/ShopItem.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/models/shops/ShopItem.kt index 1cca5db5c..200044c00 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/models/shops/ShopItem.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/models/shops/ShopItem.kt @@ -5,6 +5,7 @@ import android.content.res.Resources import com.google.gson.annotations.SerializedName import com.habitrpg.android.habitica.R import com.habitrpg.android.habitica.models.BaseObject +import com.habitrpg.android.habitica.models.inventory.Customization import com.habitrpg.android.habitica.models.inventory.ItemEvent import com.habitrpg.android.habitica.models.user.User import io.realm.RealmObject @@ -150,5 +151,18 @@ open class ShopItem : RealmObject(), BaseObject { item.purchaseType = "fortify" return item } + + fun fromCustomization(customization: Customization, userSize: String?, hairColor: String?): ShopItem { + val item = ShopItem() + item.key = customization.identifier ?: "" + item.text = customization.text + item.currency = "gems" + item.notes = customization.notes + item.value = customization.price ?: 0 + item.path = customization.path + item.purchaseType = if (customization.type == "background") "background" else "customization" + item.imageName = customization.getImageName(userSize, hairColor) + return item + } } } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/CustomizationRecyclerViewAdapter.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/CustomizationRecyclerViewAdapter.kt index a12e2f7a3..cca9f40b7 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/CustomizationRecyclerViewAdapter.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/CustomizationRecyclerViewAdapter.kt @@ -4,12 +4,12 @@ import android.content.Context import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import android.widget.ImageView import android.widget.LinearLayout import android.widget.TextView import androidx.core.content.ContextCompat import androidx.core.os.bundleOf import coil.load +import com.habitrpg.android.habitica.HabiticaBaseApplication import com.habitrpg.android.habitica.R import com.habitrpg.android.habitica.databinding.CustomizationGridItemBinding import com.habitrpg.android.habitica.databinding.CustomizationSectionFooterBinding @@ -17,9 +17,10 @@ import com.habitrpg.android.habitica.databinding.CustomizationSectionHeaderBindi import com.habitrpg.android.habitica.helpers.MainNavigationController import com.habitrpg.android.habitica.models.inventory.Customization import com.habitrpg.android.habitica.models.inventory.CustomizationSet +import com.habitrpg.android.habitica.models.shops.ShopItem import com.habitrpg.android.habitica.ui.helpers.DataBindingUtils -import com.habitrpg.android.habitica.ui.views.HabiticaIconsHelper import com.habitrpg.android.habitica.ui.views.dialogs.HabiticaAlertDialog +import com.habitrpg.android.habitica.ui.views.shops.PurchaseDialog import io.reactivex.rxjava3.core.BackpressureStrategy import io.reactivex.rxjava3.core.Flowable import io.reactivex.rxjava3.subjects.PublishSubject @@ -198,31 +199,10 @@ class CustomizationRecyclerViewAdapter() : androidx.recyclerview.widget.Recycler dialog.addButton(R.string.reward_dialog_dismiss, false) dialog.show() } else { - val dialogContent = LayoutInflater.from(itemView.context).inflate(R.layout.dialog_purchase_customization, null) as LinearLayout - - val imageView = dialogContent.findViewById(R.id.imageView) - DataBindingUtils.loadImage(imageView, customization?.getImageName(userSize, hairColor)) - - val priceLabel = dialogContent.findViewById(R.id.priceLabel) - priceLabel.text = customization?.price.toString() - - (dialogContent.findViewById(R.id.gem_icon) as? ImageView)?.setImageBitmap(HabiticaIconsHelper.imageOfGem()) - - val dialog = HabiticaAlertDialog(itemView.context) - dialog.addButton(R.string.purchase_button, true) { _, _ -> - if (customization?.price ?: 0 > gemBalance) { - MainNavigationController.navigate(R.id.gemPurchaseActivity, bundleOf(Pair("openSubscription", false))) - return@addButton - } - - customization?.let { - unlockCustomizationEvents.onNext(it) - } + customization?.let { + val dialog = PurchaseDialog(itemView.context, HabiticaBaseApplication.userComponent, ShopItem.fromCustomization(it, userSize, hairColor)) + dialog.show() } - dialog.setTitle(R.string.purchase_customization) - dialog.setAdditionalContentView(dialogContent) - dialog.addButton(R.string.reward_dialog_dismiss, false) - dialog.show() } return } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/dialogs/HabiticaAlertDialog.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/dialogs/HabiticaAlertDialog.kt index d400f29a1..2de98b3fc 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/dialogs/HabiticaAlertDialog.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/dialogs/HabiticaAlertDialog.kt @@ -47,7 +47,7 @@ open class HabiticaAlertDialog(context: Context) : AlertDialog(context, R.style. internal var contentView: FrameLayout private var scrollingSeparator: View internal var scrollView: LockableScrollView - private var buttonsWrapper: LinearLayout + protected var buttonsWrapper: LinearLayout private var noticeTextView: TextView private var closeButton: Button diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/shops/PurchaseDialog.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/shops/PurchaseDialog.kt index be0f8ae14..cf52fd1ba 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/shops/PurchaseDialog.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/shops/PurchaseDialog.kt @@ -27,7 +27,6 @@ import com.habitrpg.android.habitica.models.shops.Shop import com.habitrpg.android.habitica.models.shops.ShopItem import com.habitrpg.android.habitica.models.user.OwnedItem import com.habitrpg.android.habitica.models.user.User -import com.habitrpg.android.habitica.ui.activities.ArmoireActivityArgs import com.habitrpg.android.habitica.ui.activities.ArmoireActivityDirections import com.habitrpg.android.habitica.ui.views.CurrencyView import com.habitrpg.android.habitica.ui.views.CurrencyViews @@ -42,16 +41,16 @@ import com.habitrpg.android.habitica.ui.views.tasks.form.StepperValueFormView import io.reactivex.rxjava3.core.Flowable import io.reactivex.rxjava3.core.Maybe import io.reactivex.rxjava3.disposables.CompositeDisposable -import java.util.* -import javax.inject.Inject -import kotlin.math.max -import kotlin.time.Duration -import kotlin.time.ExperimentalTime import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.Job import kotlinx.coroutines.delay import kotlinx.coroutines.launch +import java.util.Date +import javax.inject.Inject +import kotlin.math.max +import kotlin.time.DurationUnit +import kotlin.time.toDuration class PurchaseDialog(context: Context, component: UserComponent?, val item: ShopItem) : HabiticaAlertDialog(context) { @@ -106,6 +105,8 @@ class PurchaseDialog(context: Context, component: UserComponent?, val item: Shop checkGearClass() } "gems" == shopItem.purchaseType -> contentView = PurchaseDialogGemsContent(context) + "background" == shopItem.purchaseType -> contentView = PurchaseDialogBackgroundContent(context) + "customization" == shopItem.purchaseType -> contentView = PurchaseDialogCustomizationContent(context) else -> contentView = PurchaseDialogBaseContent(context) } @@ -168,7 +169,6 @@ class PurchaseDialog(context: Context, component: UserComponent?, val item: Shop private var limitedTextViewJob: Job? = null - @OptIn(ExperimentalTime::class) private fun setLimitedTextView() { if (user == null) return if (shopItem.habitClass != null && shopItem.habitClass != "special" && shopItem.habitClass != "armoire" && user?.stats?.habitClass != shopItem.habitClass) { @@ -182,7 +182,7 @@ class PurchaseDialog(context: Context, component: UserComponent?, val item: Shop while (shopItem.event?.end?.after(Date()) == true) { limitedTextView.text = context.getString(R.string.available_for, shopItem.event?.end?.getShortRemainingString()) val diff = (shopItem.event?.end?.time ?: 0) - Date().time - delay(if (diff < (60 * 60 * 1000)) Duration.seconds(1) else Duration.minutes(1)) + delay(1.toDuration(if (diff < (60 * 60 * 1000)) DurationUnit.SECONDS else DurationUnit.MINUTES)) } if (shopItem.event?.end?.before(Date()) == true) { limitedTextView.text = context.getString(R.string.no_longer_available) @@ -239,10 +239,11 @@ class PurchaseDialog(context: Context, component: UserComponent?, val item: Shop pinTextView = customHeader.findViewById(R.id.pin_text) addCloseButton() - buyButton = addButton(layoutInflater.inflate(R.layout.dialog_purchase_shopitem_button, null), autoDismiss = false) { _, _ -> + buyButton = addButton(layoutInflater.inflate(R.layout.dialog_purchase_shopitem_button, buttonsWrapper, false), autoDismiss = false) { _, _ -> onBuyButtonClicked() } priceLabel = buyButton.findViewById(R.id.priceLabel) + priceLabel.animationDuration = 0L buyLabel = buyButton.findViewById(R.id.buy_label) pinButton.setOnClickListener { inventoryRepository.togglePinnedItem(shopItem).subscribe({ isPinned = !this.isPinned }, RxErrorHandler.handleEmptyError()) } @@ -353,6 +354,12 @@ class PurchaseDialog(context: Context, component: UserComponent?, val item: Shop observable = inventoryRepository.purchaseQuest(shopItem.key).cast(Any::class.java) } else if (shopItem.purchaseType == "debuffPotion") { observable = userRepository.useSkill(shopItem.key, null).cast(Any::class.java) + } else if (shopItem.purchaseType == "customization" || shopItem.purchaseType == "background") { + observable = userRepository.unlockPath(user, item.path, item.purchaseType, + item.value + ).cast(Any::class.java) + } else if (shopItem.purchaseType == "debuffPotion") { + observable = userRepository.useSkill(shopItem.key, null).cast(Any::class.java) } else if (shopItem.purchaseType == "card") { purchaseCardAction?.invoke(shopItem) dismiss() diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/shops/PurchaseDialogBackgroundContent.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/shops/PurchaseDialogBackgroundContent.kt new file mode 100644 index 000000000..22346a7cc --- /dev/null +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/shops/PurchaseDialogBackgroundContent.kt @@ -0,0 +1,21 @@ +package com.habitrpg.android.habitica.ui.views.shops + +import android.content.Context +import android.widget.ImageView +import android.widget.TextView +import com.habitrpg.android.habitica.databinding.PurchaseDialogBackgroundBinding +import com.habitrpg.android.habitica.extensions.layoutInflater +import com.habitrpg.android.habitica.models.shops.ShopItem + +class PurchaseDialogBackgroundContent(context: Context) : PurchaseDialogContent(context) { + val binding = PurchaseDialogBackgroundBinding.inflate(context.layoutInflater, this) + override val imageView: ImageView + get() = binding.imageView + override val titleTextView: TextView + get() = binding.titleTextView + + override fun setItem(item: ShopItem) { + super.setItem(item) + binding.notesTextView.text = item.notes + } +} \ No newline at end of file diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/shops/PurchaseDialogCustomizationContent.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/shops/PurchaseDialogCustomizationContent.kt new file mode 100644 index 000000000..4b761f067 --- /dev/null +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/shops/PurchaseDialogCustomizationContent.kt @@ -0,0 +1,15 @@ +package com.habitrpg.android.habitica.ui.views.shops + +import android.content.Context +import android.widget.ImageView +import android.widget.TextView +import com.habitrpg.android.habitica.databinding.DialogPurchaseCustomizationBinding +import com.habitrpg.android.habitica.extensions.layoutInflater + +class PurchaseDialogCustomizationContent(context: Context) : PurchaseDialogContent(context) { + val binding = DialogPurchaseCustomizationBinding.inflate(context.layoutInflater, this) + override val imageView: ImageView + get() = binding.imageView + override val titleTextView: TextView + get() = binding.titleTextView +} \ No newline at end of file