diff --git a/Habitica/res/drawable-hdpi/icon_eggs.png b/Habitica/res/drawable-hdpi/icon_eggs.png
new file mode 100644
index 0000000000..b2fd0cb575
Binary files /dev/null and b/Habitica/res/drawable-hdpi/icon_eggs.png differ
diff --git a/Habitica/res/drawable-hdpi/icon_food.png b/Habitica/res/drawable-hdpi/icon_food.png
new file mode 100644
index 0000000000..d4ad2f7e55
Binary files /dev/null and b/Habitica/res/drawable-hdpi/icon_food.png differ
diff --git a/Habitica/res/drawable-hdpi/icon_hatchingpotions.png b/Habitica/res/drawable-hdpi/icon_hatchingpotions.png
new file mode 100644
index 0000000000..cac75518b2
Binary files /dev/null and b/Habitica/res/drawable-hdpi/icon_hatchingpotions.png differ
diff --git a/Habitica/res/drawable-hdpi/icon_quests.png b/Habitica/res/drawable-hdpi/icon_quests.png
new file mode 100644
index 0000000000..f8dfab6ab1
Binary files /dev/null and b/Habitica/res/drawable-hdpi/icon_quests.png differ
diff --git a/Habitica/res/drawable-hdpi/icon_shops.png b/Habitica/res/drawable-hdpi/icon_shops.png
new file mode 100644
index 0000000000..26cd85f342
Binary files /dev/null and b/Habitica/res/drawable-hdpi/icon_shops.png differ
diff --git a/Habitica/res/drawable-hdpi/icon_special.png b/Habitica/res/drawable-hdpi/icon_special.png
new file mode 100644
index 0000000000..98021f474f
Binary files /dev/null and b/Habitica/res/drawable-hdpi/icon_special.png differ
diff --git a/Habitica/res/drawable-mdpi/icon_eggs.png b/Habitica/res/drawable-mdpi/icon_eggs.png
new file mode 100644
index 0000000000..1a3a58ebb3
Binary files /dev/null and b/Habitica/res/drawable-mdpi/icon_eggs.png differ
diff --git a/Habitica/res/drawable-mdpi/icon_food.png b/Habitica/res/drawable-mdpi/icon_food.png
new file mode 100644
index 0000000000..cd8b8fc38b
Binary files /dev/null and b/Habitica/res/drawable-mdpi/icon_food.png differ
diff --git a/Habitica/res/drawable-mdpi/icon_hatchingpotions.png b/Habitica/res/drawable-mdpi/icon_hatchingpotions.png
new file mode 100644
index 0000000000..1483a1693e
Binary files /dev/null and b/Habitica/res/drawable-mdpi/icon_hatchingpotions.png differ
diff --git a/Habitica/res/drawable-mdpi/icon_quests.png b/Habitica/res/drawable-mdpi/icon_quests.png
new file mode 100644
index 0000000000..9e18dae9c9
Binary files /dev/null and b/Habitica/res/drawable-mdpi/icon_quests.png differ
diff --git a/Habitica/res/drawable-mdpi/icon_shops.png b/Habitica/res/drawable-mdpi/icon_shops.png
new file mode 100644
index 0000000000..7ae1882c11
Binary files /dev/null and b/Habitica/res/drawable-mdpi/icon_shops.png differ
diff --git a/Habitica/res/drawable-mdpi/icon_special.png b/Habitica/res/drawable-mdpi/icon_special.png
new file mode 100644
index 0000000000..191f7ecdd2
Binary files /dev/null and b/Habitica/res/drawable-mdpi/icon_special.png differ
diff --git a/Habitica/res/drawable-xhdpi/icon_eggs.png b/Habitica/res/drawable-xhdpi/icon_eggs.png
new file mode 100644
index 0000000000..9eef23c5bc
Binary files /dev/null and b/Habitica/res/drawable-xhdpi/icon_eggs.png differ
diff --git a/Habitica/res/drawable-xhdpi/icon_food.png b/Habitica/res/drawable-xhdpi/icon_food.png
new file mode 100644
index 0000000000..21850ec289
Binary files /dev/null and b/Habitica/res/drawable-xhdpi/icon_food.png differ
diff --git a/Habitica/res/drawable-xhdpi/icon_hatchingpotions.png b/Habitica/res/drawable-xhdpi/icon_hatchingpotions.png
new file mode 100644
index 0000000000..6bf2d0e5cf
Binary files /dev/null and b/Habitica/res/drawable-xhdpi/icon_hatchingpotions.png differ
diff --git a/Habitica/res/drawable-xhdpi/icon_quests.png b/Habitica/res/drawable-xhdpi/icon_quests.png
new file mode 100644
index 0000000000..e09b5fd395
Binary files /dev/null and b/Habitica/res/drawable-xhdpi/icon_quests.png differ
diff --git a/Habitica/res/drawable-xhdpi/icon_shops.png b/Habitica/res/drawable-xhdpi/icon_shops.png
new file mode 100644
index 0000000000..c9cc3e58ae
Binary files /dev/null and b/Habitica/res/drawable-xhdpi/icon_shops.png differ
diff --git a/Habitica/res/drawable-xhdpi/icon_special.png b/Habitica/res/drawable-xhdpi/icon_special.png
new file mode 100644
index 0000000000..9f4b7f26c2
Binary files /dev/null and b/Habitica/res/drawable-xhdpi/icon_special.png differ
diff --git a/Habitica/res/drawable-xxhdpi/icon_eggs.png b/Habitica/res/drawable-xxhdpi/icon_eggs.png
new file mode 100644
index 0000000000..15a83f6df2
Binary files /dev/null and b/Habitica/res/drawable-xxhdpi/icon_eggs.png differ
diff --git a/Habitica/res/drawable-xxhdpi/icon_food.png b/Habitica/res/drawable-xxhdpi/icon_food.png
new file mode 100644
index 0000000000..1100d90c02
Binary files /dev/null and b/Habitica/res/drawable-xxhdpi/icon_food.png differ
diff --git a/Habitica/res/drawable-xxhdpi/icon_hatchingpotions.png b/Habitica/res/drawable-xxhdpi/icon_hatchingpotions.png
new file mode 100644
index 0000000000..f0527ce5bd
Binary files /dev/null and b/Habitica/res/drawable-xxhdpi/icon_hatchingpotions.png differ
diff --git a/Habitica/res/drawable-xxhdpi/icon_quests.png b/Habitica/res/drawable-xxhdpi/icon_quests.png
new file mode 100644
index 0000000000..a17600b059
Binary files /dev/null and b/Habitica/res/drawable-xxhdpi/icon_quests.png differ
diff --git a/Habitica/res/drawable-xxhdpi/icon_shops.png b/Habitica/res/drawable-xxhdpi/icon_shops.png
new file mode 100644
index 0000000000..e510983438
Binary files /dev/null and b/Habitica/res/drawable-xxhdpi/icon_shops.png differ
diff --git a/Habitica/res/drawable-xxhdpi/icon_special.png b/Habitica/res/drawable-xxhdpi/icon_special.png
new file mode 100644
index 0000000000..5802414e6b
Binary files /dev/null and b/Habitica/res/drawable-xxhdpi/icon_special.png differ
diff --git a/Habitica/res/layout/fragment_items.xml b/Habitica/res/layout/fragment_items.xml
index e09f6dd3dc..7f1ba89df3 100644
--- a/Habitica/res/layout/fragment_items.xml
+++ b/Habitica/res/layout/fragment_items.xml
@@ -26,19 +26,4 @@
android:scrollbarThumbVertical="@color/scrollbarThumb"
android:scrollbars="vertical" />
-
-
diff --git a/Habitica/res/layout/shop_ad.xml b/Habitica/res/layout/shop_ad.xml
new file mode 100644
index 0000000000..6ed8c13137
--- /dev/null
+++ b/Habitica/res/layout/shop_ad.xml
@@ -0,0 +1,33 @@
+
+
+
+
+
+
diff --git a/Habitica/res/values/strings.xml b/Habitica/res/values/strings.xml
index 576615ad2d..3c05ca7fc6 100644
--- a/Habitica/res/values/strings.xml
+++ b/Habitica/res/values/strings.xml
@@ -1399,6 +1399,19 @@
Contributor Tiers
If you see an account with a colored display name and an icon, that’s a contributor tier! Tiers are given to people who help around Habitica, whether it be for translation, coding, or just being helpful. The higher the tier, the more the player has contributed.
Visit FAQ
+ No %s
+ Get Quests from leveling up, log in bonuses, or the [Quest Shop](/shops/quests)!
+ Get transformation items during Seasonal Galas and mystery boxes of subscriber gear are delivered at the start of each month!
+ Complete tasks, buy an Armoire, or head over to the [Market](/shops/market) to stock up!
+ Complete tasks, Potion Quests, or head over to the [Market](/shops/market) to stock up!
+ Not getting the right %s from tasks?
+ Check out the [Market](/shops/market) to buy just the things you need!
+ Check out the [Quest Shop](/shops/quests) to see what’s available!
+ Want more Quests?
+ potions
+ Check out the [Market](/shops/market) to buy just the eggs you need!
+ Check out the [Market](/shops/market) to buy food or a Saddle to instantly raise your Pet!
+ Check out the [Market](/shops/market) to buy standard and seasonal Hatching Potions!
- You
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/inventory/ItemRecyclerAdapter.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/inventory/ItemRecyclerAdapter.kt
index fdf3d72bc0..cb7b715507 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/inventory/ItemRecyclerAdapter.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/inventory/ItemRecyclerAdapter.kt
@@ -6,8 +6,11 @@ import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.DialogFragment
import androidx.recyclerview.widget.RecyclerView
+import androidx.recyclerview.widget.RecyclerView.ViewHolder
import com.habitrpg.android.habitica.R
import com.habitrpg.android.habitica.databinding.ItemItemBinding
+import com.habitrpg.android.habitica.databinding.ShopAdBinding
+import com.habitrpg.android.habitica.models.BaseMainObject
import com.habitrpg.android.habitica.models.inventory.Egg
import com.habitrpg.android.habitica.models.inventory.Food
import com.habitrpg.android.habitica.models.inventory.HatchingPotion
@@ -25,17 +28,20 @@ import com.habitrpg.android.habitica.ui.views.dialogs.DetailDialog
import com.habitrpg.common.habitica.extensions.layoutInflater
import com.habitrpg.common.habitica.extensions.loadImage
import com.habitrpg.common.habitica.extensions.localizedCapitalizeWithSpaces
+import com.habitrpg.common.habitica.helpers.setMarkdown
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale
-class ItemRecyclerAdapter(val context: Context) : BaseRecyclerViewAdapter() {
+class ItemRecyclerAdapter(val context: Context) : BaseRecyclerViewAdapter() {
var user: User? = null
var isHatching: Boolean = false
var isFeeding: Boolean = false
var hatchingItem: Item? = null
var feedingPet: Pet? = null
var fragment: DialogFragment? = null
+ var itemType = ""
+ var itemText = ""
private var existingPets: List? = null
private var ownedPets: Map? = null
var items: Map? = null
@@ -52,14 +58,53 @@ class ItemRecyclerAdapter(val context: Context) : BaseRecyclerViewAdapter Unit)? = null
var onCreateNewParty: (() -> Unit)? = null
var onUseSpecialItem: ((SpecialItem) -> Unit)? = null
+ var onOpenShop: (() -> Unit)? = null
- override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder {
- return ItemViewHolder(ItemItemBinding.inflate(context.layoutInflater, parent, false))
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
+ return if (viewType == 0) {
+ ItemViewHolder(ItemItemBinding.inflate(context.layoutInflater, parent, false))
+ } else {
+ ShopAdViewHolder(ShopAdBinding.inflate(context.layoutInflater, parent, false))
+ }
}
- override fun onBindViewHolder(holder: ItemViewHolder, position: Int) {
- val ownedItem = data[position]
- holder.bind(ownedItem, items?.get(ownedItem.key))
+ override fun onBindViewHolder(holder: ViewHolder, position: Int) {
+ if (position < data.size) {
+ val ownedItem = data[position] as OwnedItem
+ (holder as? ItemViewHolder)?.bind(ownedItem, items?.get(ownedItem.key))
+ } else {
+ val typedHolder = (holder as? ShopAdViewHolder) ?: return
+ if (itemType == "quests") {
+ typedHolder.binding.imageView.setImageResource(R.drawable.icon_quests)
+ typedHolder.binding.titleView.text = context.getString(R.string.quests_footer_title)
+ typedHolder.binding.descriptionView.setMarkdown(context.getString(R.string.quests_footer_description))
+ } else {
+ typedHolder.binding.imageView.setImageResource(R.drawable.icon_shops)
+ typedHolder.binding.titleView.text = context.getString(R.string.item_footer_title, itemText)
+ typedHolder.binding.descriptionView.setMarkdown(when (itemType) {
+ "eggs" -> context.getString(R.string.eggs_footer_description)
+ "food" -> context.getString(R.string.food_footer_description)
+ "hatchingPotions" -> context.getString(R.string.hatchingPotions_footer_description)
+ else -> ""
+ })
+ }
+ typedHolder.itemView.setOnClickListener {
+ onOpenShop?.invoke()
+ }
+ }
+ }
+
+ override fun getItemCount(): Int {
+ val actualCount = super.getItemCount()
+ return actualCount + if (itemType == "special" || actualCount == 0) 0 else 1
+ }
+
+ override fun getItemViewType(position: Int): Int {
+ return if (position < data.size) {
+ 0
+ } else {
+ -1
+ }
}
fun setExistingPets(pets: List) {
@@ -72,6 +117,8 @@ class ItemRecyclerAdapter(val context: Context) : BaseRecyclerViewAdapter() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
- binding?.recyclerView?.emptyItem = EmptyItem(
- getString(R.string.empty_items, itemTypeText ?: itemType),
- getString(R.string.open_market)
- ) {
- openMarket()
+ val buttonMethod = {
+ Analytics.sendEvent("Items CTA tap", EventCategory.BEHAVIOUR, HitType.EVENT, mapOf(
+ "area" to "empty",
+ "type" to (itemType ?: "")
+ ))
+ if (itemType == "quests") {
+ MainNavigationController.navigate(R.id.questShopFragment)
+ } else {
+ openMarket()
+ }
}
+ binding?.recyclerView?.emptyItem = EmptyItem(
+ getString(R.string.no_x, itemTypeText ?: itemType),
+ when (itemType) {
+ "food" -> getString(R.string.empty_food_description)
+ "quests" -> getString(R.string.empty_quests_description)
+ "special" -> getString(R.string.empty_special_description_subscribed)
+ else -> getString(R.string.empty_items_description)
+ },
+ when (itemType) {
+ "eggs" -> R.drawable.icon_eggs
+ "hatchingPotions" -> R.drawable.icon_hatchingpotions
+ "food" -> R.drawable.icon_food
+ "quests" -> R.drawable.icon_quests
+ "special" -> R.drawable.icon_special
+ else -> null
+ },
+ false,
+ if (itemType == "special") null else buttonMethod)
layoutManager = androidx.recyclerview.widget.LinearLayoutManager(context)
binding?.recyclerView?.layoutManager = layoutManager
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/inventory/items/ItemRecyclerFragment.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/inventory/items/ItemRecyclerFragment.kt
index 2ff326051e..bb90359854 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/inventory/items/ItemRecyclerFragment.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/inventory/items/ItemRecyclerFragment.kt
@@ -17,6 +17,9 @@ import com.habitrpg.android.habitica.data.UserRepository
import com.habitrpg.android.habitica.databinding.FragmentItemsBinding
import com.habitrpg.android.habitica.extensions.addCloseButton
import com.habitrpg.android.habitica.extensions.observeOnce
+import com.habitrpg.android.habitica.helpers.Analytics
+import com.habitrpg.android.habitica.helpers.EventCategory
+import com.habitrpg.android.habitica.helpers.HitType
import com.habitrpg.android.habitica.helpers.MainNavigationController
import com.habitrpg.android.habitica.interactors.HatchPetUseCase
import com.habitrpg.android.habitica.models.inventory.Egg
@@ -90,18 +93,35 @@ class ItemRecyclerFragment : BaseFragment(), SwipeRefreshL
super.onViewCreated(view, savedInstanceState)
binding?.refreshLayout?.setOnRefreshListener(this)
- binding?.recyclerView?.emptyItem = EmptyItem(
- getString(R.string.empty_items, itemTypeText ?: itemType),
- null,
- null,
- if (itemType == "special") null else getString(R.string.open_shop)
- ) {
+ val buttonMethod = {
+ Analytics.sendEvent("Items CTA tap", EventCategory.BEHAVIOUR, HitType.EVENT, mapOf(
+ "area" to "empty",
+ "type" to (itemType ?: "")
+ ))
if (itemType == "quests") {
MainNavigationController.navigate(R.id.questShopFragment)
} else {
openMarket()
}
}
+ binding?.recyclerView?.emptyItem = EmptyItem(
+ getString(R.string.no_x, itemTypeText ?: itemType),
+ when (itemType) {
+ "food" -> getString(R.string.empty_food_description)
+ "quests" -> getString(R.string.empty_quests_description)
+ "special" -> getString(R.string.empty_special_description_subscribed)
+ else -> getString(R.string.empty_items_description)
+ },
+ when (itemType) {
+ "eggs" -> R.drawable.icon_eggs
+ "hatchingPotions" -> R.drawable.icon_hatchingpotions
+ "food" -> R.drawable.icon_food
+ "quests" -> R.drawable.icon_quests
+ "special" -> R.drawable.icon_special
+ else -> null
+ },
+ false,
+ if (itemType == "special") null else buttonMethod)
layoutManager = androidx.recyclerview.widget.LinearLayoutManager(context)
binding?.recyclerView?.layoutManager = layoutManager
@@ -122,12 +142,6 @@ class ItemRecyclerFragment : BaseFragment(), SwipeRefreshL
}
binding?.titleTextView?.visibility = View.GONE
- binding?.footerTextView?.visibility = View.GONE
- binding?.openMarketButton?.visibility = View.GONE
-
- binding?.openMarketButton?.setOnClickListener {
- openMarket()
- }
setAdapter()
this.loadItems()
}
@@ -177,6 +191,19 @@ class ItemRecyclerFragment : BaseFragment(), SwipeRefreshL
adapter?.onStartHatching = { showHatchingDialog(it) }
adapter?.onHatchPet = { pet, egg -> hatchPet(pet, egg) }
adapter?.onCreateNewParty = { createNewParty() }
+ adapter?.itemType = itemType ?: ""
+ adapter?.itemText = (if (itemType == "hatchingPotions") context?.getString(R.string.potions) else itemTypeText) ?: ""
+ adapter?.onOpenShop = {
+ Analytics.sendEvent("Items CTA tap", EventCategory.BEHAVIOUR, HitType.EVENT, mapOf(
+ "area" to "bottom",
+ "type" to (itemType ?: "")
+ ))
+ if (itemType == "quests") {
+ MainNavigationController.navigate(R.id.questShopFragment)
+ } else {
+ openMarket()
+ }
+ }
}
}
diff --git a/common/src/main/java/com/habitrpg/common/habitica/helpers/RecyclerViewEmptySupport.kt b/common/src/main/java/com/habitrpg/common/habitica/helpers/RecyclerViewEmptySupport.kt
index f37c48f923..16d3c152bf 100644
--- a/common/src/main/java/com/habitrpg/common/habitica/helpers/RecyclerViewEmptySupport.kt
+++ b/common/src/main/java/com/habitrpg/common/habitica/helpers/RecyclerViewEmptySupport.kt
@@ -15,7 +15,7 @@ data class EmptyItem(
var title: String,
var text: String? = null,
var iconResource: Int? = null,
- var buttonLabel: String? = null,
+ var tintedIcon: Boolean = true,
var onButtonTap: (() -> Unit)? = null
)
@@ -46,24 +46,20 @@ class EmptyViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
private val binding = EmptyItemBinding.bind(itemView)
fun bind(emptyItem: EmptyItem?) {
- binding.emptyIconView.setColorFilter(
- ContextCompat.getColor(
- itemView.context,
- R.color.text_dimmed
- ),
- android.graphics.PorterDuff.Mode.MULTIPLY
- )
+ if (emptyItem?.tintedIcon == true) {
+ binding.emptyIconView.setColorFilter(
+ ContextCompat.getColor(
+ itemView.context,
+ R.color.text_dimmed
+ ),
+ android.graphics.PorterDuff.Mode.MULTIPLY
+ )
+ }
emptyItem?.iconResource?.let { binding.emptyIconView.setImageResource(it) }
binding.emptyViewTitle.text = emptyItem?.title
- binding.emptyViewDescription.text = emptyItem?.text
-
- val buttonLabel = emptyItem?.buttonLabel
- if (buttonLabel != null) {
- binding.button.visibility = View.VISIBLE
- binding.button.text = buttonLabel
- binding.button.setOnClickListener { emptyItem.onButtonTap?.invoke() }
- } else {
- binding.button.visibility = View.GONE
+ binding.emptyViewDescription.setMarkdown(emptyItem?.text)
+ if (emptyItem?.onButtonTap != null) {
+ binding.emptyView.setOnClickListener { emptyItem.onButtonTap?.invoke() }
}
}
}
diff --git a/common/src/main/res/layout/empty_item.xml b/common/src/main/res/layout/empty_item.xml
index b3d38777a0..6a8febc0c1 100644
--- a/common/src/main/res/layout/empty_item.xml
+++ b/common/src/main/res/layout/empty_item.xml
@@ -5,23 +5,25 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
- android:gravity="center"
- android:padding="30dp">
+ android:gravity="top|center"
+ android:paddingTop="56dp"
+ android:paddingHorizontal="24dp">
+ android:layout_marginBottom="16dp" />
-
-
-
\ No newline at end of file
+
diff --git a/version.properties b/version.properties
index fa5f472264..3d69a2f4e2 100644
--- a/version.properties
+++ b/version.properties
@@ -1,2 +1,2 @@
NAME=4.2.5
-CODE=6321
\ No newline at end of file
+CODE=6331
\ No newline at end of file