From bda64ecbff404dd98d4ff97e3524adf2c9e0c2a4 Mon Sep 17 00:00:00 2001 From: Phillip Thelen Date: Wed, 22 Jul 2020 15:14:41 +0200 Subject: [PATCH] Improve stable display --- Habitica/build.gradle | 2 +- ...ayout_rounded_bg_gray_700_brand_border.xml | 2 +- Habitica/res/layout/main_navigation_view.xml | 12 ++-- Habitica/res/layout/pet_detail_item.xml | 4 +- .../habitica/data/InventoryRepository.kt | 4 +- .../implementation/InventoryRepositoryImpl.kt | 4 +- .../data/local/InventoryLocalRepository.kt | 4 +- .../RealmInventoryLocalRepository.kt | 24 +++++--- .../models/inventory/StableSection.kt | 7 +++ .../inventory/MountDetailRecyclerAdapter.kt | 54 ++++++++++++++++-- .../inventory/PetDetailRecyclerAdapter.kt | 56 ++++++++++++++++--- .../inventory/StableRecyclerAdapter.kt | 30 +++++----- .../stable/MountDetailRecyclerFragment.kt | 36 ++++++++++-- .../stable/PetDetailRecyclerFragment.kt | 43 +++++++++++--- .../stable/StableRecyclerFragment.kt | 42 ++++++++------ .../views/navigation/BottomNavigationItem.kt | 7 ++- fastlane/README.md | 2 +- 17 files changed, 254 insertions(+), 79 deletions(-) create mode 100644 Habitica/src/main/java/com/habitrpg/android/habitica/models/inventory/StableSection.kt diff --git a/Habitica/build.gradle b/Habitica/build.gradle index 9dc5e73df..7f8508f5f 100644 --- a/Habitica/build.gradle +++ b/Habitica/build.gradle @@ -162,7 +162,7 @@ android { multiDexEnabled true 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 + versionCode 2488 versionName "2.8" } diff --git a/Habitica/res/drawable/layout_rounded_bg_gray_700_brand_border.xml b/Habitica/res/drawable/layout_rounded_bg_gray_700_brand_border.xml index 727262a5e..995c49409 100644 --- a/Habitica/res/drawable/layout_rounded_bg_gray_700_brand_border.xml +++ b/Habitica/res/drawable/layout_rounded_bg_gray_700_brand_border.xml @@ -3,5 +3,5 @@ - + \ No newline at end of file diff --git a/Habitica/res/layout/main_navigation_view.xml b/Habitica/res/layout/main_navigation_view.xml index 43a1d455f..ce12da747 100644 --- a/Habitica/res/layout/main_navigation_view.xml +++ b/Habitica/res/layout/main_navigation_view.xml @@ -5,7 +5,8 @@ android:orientation="vertical" android:layout_width="match_parent" android:layout_height="wrap_content" - tools:parentTag="android.widget.RelativeLayout"> + tools:parentTag="android.widget.RelativeLayout" + tools:background="@color/gray_600"> + android:layout_height="62dp" + android:src="@drawable/bottom_navigation_inset" + android:layout_gravity="top"/> diff --git a/Habitica/res/layout/pet_detail_item.xml b/Habitica/res/layout/pet_detail_item.xml index 4b949e17a..286674a7d 100644 --- a/Habitica/res/layout/pet_detail_item.xml +++ b/Habitica/res/layout/pet_detail_item.xml @@ -22,8 +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:layout_marginStart="7dp" + android:layout_marginEnd="7dp" android:max="50" /> fun saveEquipment(equipment: Equipment) - fun getMounts(type: String, group: String, color: String?): Flowable> - fun getPets(type: String, group: String, color: String?): Flowable> + fun getMounts(type: String?, group: String?, color: String?): Flowable> + fun getPets(type: String?, group: String?, color: String?): Flowable> fun updateOwnedEquipment(user: User) diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/InventoryRepositoryImpl.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/InventoryRepositoryImpl.kt index f51c50c29..df65a6585 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/InventoryRepositoryImpl.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/InventoryRepositoryImpl.kt @@ -82,7 +82,7 @@ class InventoryRepositoryImpl(localRepository: InventoryLocalRepository, apiClie return localRepository.getMounts() } - override fun getMounts(type: String, group: String, color: String?): Flowable> { + override fun getMounts(type: String?, group: String?, color: String?): Flowable> { return localRepository.getMounts(type, group, color) } @@ -94,7 +94,7 @@ class InventoryRepositoryImpl(localRepository: InventoryLocalRepository, apiClie return localRepository.getPets() } - override fun getPets(type: String, group: String, color: String?): Flowable> { + override fun getPets(type: String?, group: String?, color: String?): Flowable> { return localRepository.getPets(type, group, color) } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/InventoryLocalRepository.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/InventoryLocalRepository.kt index fb49d0342..63b782fab 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/InventoryLocalRepository.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/InventoryLocalRepository.kt @@ -36,8 +36,8 @@ interface InventoryLocalRepository : ContentLocalRepository { fun getEquipmentType(type: String, set: String): Flowable> fun getEquipment(key: String): Flowable - fun getMounts(type: String, group: String, color: String?): Flowable> - fun getPets(type: String, group: String, color: String?): Flowable> + fun getMounts(type: String?, group: String?, color: String?): Flowable> + fun getPets(type: String?, group: String?, color: String?): Flowable> fun updateOwnedEquipment(user: User) diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/implementation/RealmInventoryLocalRepository.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/implementation/RealmInventoryLocalRepository.kt index 56f292412..789adb98b 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/implementation/RealmInventoryLocalRepository.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/implementation/RealmInventoryLocalRepository.kt @@ -132,11 +132,15 @@ class RealmInventoryLocalRepository(realm: Realm, private val context: Context) .filter { it.isLoaded } } - override fun getMounts(type: String, group: String, color: String?): Flowable> { + override fun getMounts(type: String?, group: String?, color: String?): Flowable> { var query = realm.where(Mount::class.java) - .sort("color", Sort.ASCENDING) - .equalTo("type", group) - .equalTo("animal", type) + .sort("type", Sort.ASCENDING, if (color == null) "color" else "animal", Sort.ASCENDING) + if (type != null) { + query = query.equalTo("animal", type) + } + if (group != null) { + query = query.equalTo("type", group) + } if (color != null) { query = query.equalTo("color", color) } @@ -162,11 +166,15 @@ class RealmInventoryLocalRepository(realm: Realm, private val context: Context) .filter { it.isLoaded } } - override fun getPets(type: String, group: String, color: String?): Flowable> { + override fun getPets(type: String?, group: String?, color: String?): Flowable> { var query = realm.where(Pet::class.java) - .sort("color", Sort.ASCENDING) - .equalTo("type", group) - .equalTo("animal", type) + .sort("type", Sort.ASCENDING, if (color == null) "color" else "animal", Sort.ASCENDING) + if (type != null) { + query = query.equalTo("animal", type) + } + if (group != null) { + query = query.equalTo("type", group) + } if (color != null) { query = query.equalTo("color", color) } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/models/inventory/StableSection.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/models/inventory/StableSection.kt new file mode 100644 index 000000000..a8b390a9d --- /dev/null +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/models/inventory/StableSection.kt @@ -0,0 +1,7 @@ +package com.habitrpg.android.habitica.models.inventory + +class StableSection(val key: Any?, val text: String) { + + var ownedCount = 0 + var totalCount = 0 +} \ No newline at end of file diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/inventory/MountDetailRecyclerAdapter.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/inventory/MountDetailRecyclerAdapter.kt index 8608edbad..76a8f3999 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/inventory/MountDetailRecyclerAdapter.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/inventory/MountDetailRecyclerAdapter.kt @@ -11,11 +11,13 @@ import com.habitrpg.android.habitica.R import com.habitrpg.android.habitica.extensions.inflate import com.habitrpg.android.habitica.helpers.RxErrorHandler import com.habitrpg.android.habitica.models.inventory.Mount +import com.habitrpg.android.habitica.models.inventory.Pet import com.habitrpg.android.habitica.models.user.OwnedMount import com.habitrpg.android.habitica.ui.helpers.DataBindingUtils import com.habitrpg.android.habitica.ui.helpers.bindView import com.habitrpg.android.habitica.ui.menu.BottomSheetMenu import com.habitrpg.android.habitica.ui.menu.BottomSheetMenuItem +import com.habitrpg.android.habitica.ui.viewHolders.SectionViewHolder import io.reactivex.BackpressureStrategy import io.reactivex.Flowable import io.reactivex.Observable @@ -25,7 +27,7 @@ import io.reactivex.subjects.PublishSubject import io.realm.OrderedRealmCollection import io.realm.RealmRecyclerViewAdapter -class MountDetailRecyclerAdapter(data: OrderedRealmCollection?, autoUpdate: Boolean) : RealmRecyclerViewAdapter(data, autoUpdate) { +class MountDetailRecyclerAdapter : androidx.recyclerview.widget.RecyclerView.Adapter() { var itemType: String? = null var context: Context? = null @@ -33,19 +35,60 @@ class MountDetailRecyclerAdapter(data: OrderedRealmCollection?, autoUpdat private val equipEvents = PublishSubject.create() + private var itemList: List = ArrayList() + + fun setItemList(itemList: List) { + this.itemList = itemList + this.notifyDataSetChanged() + } fun getEquipFlowable(): Flowable { return equipEvents.toFlowable(BackpressureStrategy.DROP) } - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MountViewHolder { - return MountViewHolder(parent.inflate(R.layout.mount_overview_item)) + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): androidx.recyclerview.widget.RecyclerView.ViewHolder = + when (viewType) { + 0 -> { + val view = parent.inflate(R.layout.shop_header) + StableRecyclerAdapter.StableHeaderViewHolder(view) + } + 1 -> { + val view = parent.inflate(R.layout.customization_section_header) + SectionViewHolder(view) + } + else -> { + MountViewHolder(parent.inflate(R.layout.mount_overview_item)) + } + } + + override fun onBindViewHolder(holder: androidx.recyclerview.widget.RecyclerView.ViewHolder, position: Int) { + val obj = this.itemList[position] + when { + obj.javaClass == String::class.java -> { + (holder as? SectionViewHolder)?.bind(obj as? String ?: "") + } + else -> { + (obj as? Mount)?.let { (holder as? MountViewHolder)?.bind(it, ownedMounts?.get(it.key ?: "")) } + } + } } - override fun onBindViewHolder(holder: MountViewHolder, position: Int) { - data?.let { holder.bind(it[position], ownedMounts?.get(it[position].key)) } + override fun getItemViewType(position: Int): Int { + val item = itemList[position] + + return if (item.javaClass == String::class.java) { + 1 + } + else if (itemType == "pets") { + 2 + } + else { + 3 + } } + override fun getItemCount(): Int = itemList.size + fun setOwnedMounts(ownedMounts: Map) { this.ownedMounts = ownedMounts notifyDataSetChanged() @@ -97,6 +140,7 @@ class MountDetailRecyclerAdapter(data: OrderedRealmCollection?, autoUpdat return } val menu = BottomSheetMenu(itemView.context) + menu.setTitle(animal?.text) menu.addMenuItem(BottomSheetMenuItem(resources.getString(R.string.equip))) menu.setSelectionRunnable { animal?.let { equipEvents.onNext(it.key) } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/inventory/PetDetailRecyclerAdapter.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/inventory/PetDetailRecyclerAdapter.kt index bb7e121db..78b67982b 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/inventory/PetDetailRecyclerAdapter.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/inventory/PetDetailRecyclerAdapter.kt @@ -7,6 +7,7 @@ import android.view.View import android.view.ViewGroup import android.widget.ImageView import android.widget.ProgressBar +import androidx.recyclerview.widget.GridLayoutManager import com.facebook.drawee.view.SimpleDraweeView import com.habitrpg.android.habitica.R import com.habitrpg.android.habitica.events.commands.FeedCommand @@ -20,6 +21,7 @@ import com.habitrpg.android.habitica.ui.helpers.DataBindingUtils import com.habitrpg.android.habitica.ui.helpers.bindView import com.habitrpg.android.habitica.ui.menu.BottomSheetMenu import com.habitrpg.android.habitica.ui.menu.BottomSheetMenuItem +import com.habitrpg.android.habitica.ui.viewHolders.SectionViewHolder import com.habitrpg.android.habitica.ui.views.dialogs.PetSuggestHatchDialog import io.reactivex.BackpressureStrategy import io.reactivex.Flowable @@ -32,7 +34,7 @@ import io.realm.RealmRecyclerViewAdapter import io.realm.RealmResults import org.greenrobot.eventbus.EventBus -class PetDetailRecyclerAdapter(data: OrderedRealmCollection?, autoUpdate: Boolean) : RealmRecyclerViewAdapter(data, autoUpdate) { +class PetDetailRecyclerAdapter : androidx.recyclerview.widget.RecyclerView.Adapter() { var itemType: String? = null var context: Context? = null @@ -43,22 +45,62 @@ class PetDetailRecyclerAdapter(data: OrderedRealmCollection?, autoUpdate: B private val equipEvents = PublishSubject.create() private var ownsSaddles: Boolean = false + private var itemList: List = ArrayList() + + fun setItemList(itemList: List) { + this.itemList = itemList + this.notifyDataSetChanged() + } + fun getEquipFlowable(): Flowable { return equipEvents.toFlowable(BackpressureStrategy.DROP) } var animalIngredientsRetriever: ((Animal) -> Pair)? = null - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PetViewHolder { - return PetViewHolder(parent.inflate(R.layout.pet_detail_item)) - } + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): androidx.recyclerview.widget.RecyclerView.ViewHolder = + when (viewType) { + 0 -> { + val view = parent.inflate(R.layout.shop_header) + StableRecyclerAdapter.StableHeaderViewHolder(view) + } + 1 -> { + val view = parent.inflate(R.layout.customization_section_header) + SectionViewHolder(view) + } + else -> { + PetViewHolder(parent.inflate(R.layout.pet_detail_item)) + } + } - override fun onBindViewHolder(holder: PetViewHolder, position: Int) { - data?.let { - holder.bind(it[position], ownedPets?.get(it[position]?.key ?: "")) + override fun onBindViewHolder(holder: androidx.recyclerview.widget.RecyclerView.ViewHolder, position: Int) { + val obj = this.itemList[position] + when { + obj.javaClass == String::class.java -> { + (holder as? SectionViewHolder)?.bind(obj as? String ?: "") + } + else -> { + (obj as? Pet)?.let { (holder as? PetViewHolder)?.bind(it, ownedPets?.get(it.key ?: "")) } + } } } + override fun getItemViewType(position: Int): Int { + val item = itemList[position] + + return if (item.javaClass == String::class.java) { + 1 + } + else if (itemType == "pets") { + 2 + } + else { + 3 + } + } + + override fun getItemCount(): Int = itemList.size + fun setExistingMounts(existingMounts: RealmResults) { this.existingMounts = existingMounts notifyDataSetChanged() diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/inventory/StableRecyclerAdapter.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/inventory/StableRecyclerAdapter.kt index 7d6bdcca0..ca2174781 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/inventory/StableRecyclerAdapter.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/inventory/StableRecyclerAdapter.kt @@ -51,18 +51,23 @@ class StableRecyclerAdapter : androidx.recyclerview.widget.RecyclerView.Adapter< } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): androidx.recyclerview.widget.RecyclerView.ViewHolder = - if (viewType == 0) { - val view = parent.inflate(R.layout.shop_header) - StableHeaderViewHolder(view) - } else if (viewType == 1) { - val view = parent.inflate(R.layout.customization_section_header) - SectionViewHolder(view) - } else if (viewType == 2) { - val view = parent.inflate(R.layout.pet_overview_item) - StableViewHolder(view) - } else { - val view = parent.inflate(R.layout.mount_overview_item) - StableViewHolder(view) + when (viewType) { + 0 -> { + val view = parent.inflate(R.layout.shop_header) + StableHeaderViewHolder(view) + } + 1 -> { + val view = parent.inflate(R.layout.customization_section_header) + SectionViewHolder(view) + } + 2 -> { + val view = parent.inflate(R.layout.pet_overview_item) + StableViewHolder(view) + } + else -> { + val view = parent.inflate(R.layout.mount_overview_item) + StableViewHolder(view) + } } override fun onBindViewHolder(holder: androidx.recyclerview.widget.RecyclerView.ViewHolder, position: Int) { @@ -78,7 +83,6 @@ class StableRecyclerAdapter : androidx.recyclerview.widget.RecyclerView.Adapter< holder.itemView.layoutParams = params } (holder as? SectionViewHolder)?.bind(obj as? String ?: "") - } else -> { (obj as? Animal)?.let { (holder as? StableViewHolder)?.bind(it) } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/inventory/stable/MountDetailRecyclerFragment.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/inventory/stable/MountDetailRecyclerFragment.kt index 7da733378..ba524f722 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/inventory/stable/MountDetailRecyclerFragment.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/inventory/stable/MountDetailRecyclerFragment.kt @@ -8,7 +8,10 @@ import android.view.ViewGroup import com.habitrpg.android.habitica.R import com.habitrpg.android.habitica.components.UserComponent import com.habitrpg.android.habitica.data.InventoryRepository +import com.habitrpg.android.habitica.extensions.getTranslatedType import com.habitrpg.android.habitica.helpers.RxErrorHandler +import com.habitrpg.android.habitica.models.inventory.Mount +import com.habitrpg.android.habitica.models.inventory.Pet import com.habitrpg.android.habitica.models.user.OwnedMount import com.habitrpg.android.habitica.ui.adapter.inventory.MountDetailRecyclerAdapter import com.habitrpg.android.habitica.ui.fragments.BaseMainFragment @@ -51,18 +54,29 @@ class MountDetailRecyclerFragment : BaseMainFragment() { arguments?.let { val args = MountDetailRecyclerFragmentArgs.fromBundle(it) - animalGroup = args.group + if (args.group != "drop") { + animalGroup = args.group + } animalType = args.type animalColor = args.color } layoutManager = androidx.recyclerview.widget.GridLayoutManager(activity, 2) + layoutManager?.spanSizeLookup = object : androidx.recyclerview.widget.GridLayoutManager.SpanSizeLookup() { + override fun getSpanSize(position: Int): Int { + return if (adapter?.getItemViewType(position) == 0 || adapter?.getItemViewType(position) == 1) { + layoutManager?.spanCount ?: 1 + } else { + 1 + } + } + } recyclerView.layoutManager = layoutManager recyclerView.addItemDecoration(MarginDecoration(activity)) adapter = recyclerView.adapter as? MountDetailRecyclerAdapter if (adapter == null) { - adapter = MountDetailRecyclerAdapter(null, true) + adapter = MountDetailRecyclerAdapter() adapter?.itemType = this.animalType adapter?.context = context recyclerView.adapter = adapter @@ -101,7 +115,7 @@ class MountDetailRecyclerFragment : BaseMainFragment() { } private fun loadItems() { - if (animalType != null && animalGroup != null) { + if (animalType != null || animalGroup != null) { compositeSubscription.add(inventoryRepository.getOwnedMounts().firstElement() .map { ownedMounts -> val mountMap = mutableMapOf() @@ -109,7 +123,21 @@ class MountDetailRecyclerFragment : BaseMainFragment() { return@map mountMap } .subscribe(Consumer { adapter?.setOwnedMounts(it) }, RxErrorHandler.handleEmptyError())) - compositeSubscription.add(inventoryRepository.getMounts(animalType!!, animalGroup!!, animalColor).firstElement().subscribe(Consumer { adapter?.updateData(it) }, RxErrorHandler.handleEmptyError())) + compositeSubscription.add(inventoryRepository.getMounts(animalType, animalGroup, animalColor) + .map { + val items = mutableListOf() + var lastMount: Mount? = null + for (mount in it) { + if (mount.type == "wacky" || mount.type == "special") continue + if (mount.type != lastMount?.type) { + items.add(mount.getTranslatedType(context)) + } + items.add(mount) + lastMount = mount + } + items + } + .subscribe(Consumer { adapter?.setItemList(it) }, RxErrorHandler.handleEmptyError())) } } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/inventory/stable/PetDetailRecyclerFragment.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/inventory/stable/PetDetailRecyclerFragment.kt index e1944828b..963afcbd5 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/inventory/stable/PetDetailRecyclerFragment.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/inventory/stable/PetDetailRecyclerFragment.kt @@ -8,6 +8,7 @@ import com.habitrpg.android.habitica.R import com.habitrpg.android.habitica.components.UserComponent import com.habitrpg.android.habitica.data.InventoryRepository import com.habitrpg.android.habitica.events.commands.FeedCommand +import com.habitrpg.android.habitica.extensions.getTranslatedType import com.habitrpg.android.habitica.helpers.RxErrorHandler import com.habitrpg.android.habitica.models.inventory.Egg import com.habitrpg.android.habitica.models.inventory.HatchingPotion @@ -35,9 +36,9 @@ class PetDetailRecyclerFragment : BaseMainFragment() { private val recyclerView: androidx.recyclerview.widget.RecyclerView by bindView(R.id.recyclerView) - var adapter: PetDetailRecyclerAdapter = PetDetailRecyclerAdapter(null, true) - var animalType: String = "" - var animalGroup: String = "" + var adapter: PetDetailRecyclerAdapter = PetDetailRecyclerAdapter() + var animalType: String? = null + var animalGroup: String? = null var animalColor: String? = null internal var layoutManager: androidx.recyclerview.widget.GridLayoutManager? = null @@ -65,7 +66,9 @@ class PetDetailRecyclerFragment : BaseMainFragment() { arguments?.let { val args = MountDetailRecyclerFragmentArgs.fromBundle(it) - animalGroup = args.group + if (args.group != "drop") { + animalGroup = args.group + } animalType = args.type animalColor = args.color } @@ -73,6 +76,15 @@ class PetDetailRecyclerFragment : BaseMainFragment() { resetViews() layoutManager = androidx.recyclerview.widget.GridLayoutManager(getActivity(), 2) + layoutManager?.spanSizeLookup = object : androidx.recyclerview.widget.GridLayoutManager.SpanSizeLookup() { + override fun getSpanSize(position: Int): Int { + return if (adapter.getItemViewType(position) == 0 || adapter.getItemViewType(position) == 1) { + layoutManager?.spanCount ?: 1 + } else { + 1 + } + } + } recyclerView.layoutManager = layoutManager recyclerView.addItemDecoration(MarginDecoration(getActivity())) @@ -102,7 +114,8 @@ class PetDetailRecyclerFragment : BaseMainFragment() { private fun setGridSpanCount(width: Int) { var spanCount = 0 if (context != null && context?.resources != null) { - val itemWidth: Float = context?.resources?.getDimension(R.dimen.pet_width) ?: 120f + val animalWidth = R.dimen.pet_width + val itemWidth: Float = context?.resources?.getDimension(animalWidth) ?: 0.toFloat() spanCount = (width / itemWidth).toInt() } @@ -110,11 +123,10 @@ class PetDetailRecyclerFragment : BaseMainFragment() { spanCount = 1 } layoutManager?.spanCount = spanCount - layoutManager?.requestLayout() } private fun loadItems() { - if (animalType.isNotEmpty() && animalGroup.isNotEmpty()) { + if (animalType?.isNotEmpty() == true || animalGroup?.isNotEmpty() == true) { compositeSubscription.add(inventoryRepository.getOwnedPets() .map { ownedMounts -> val mountMap = mutableMapOf() @@ -130,11 +142,26 @@ class PetDetailRecyclerFragment : BaseMainFragment() { } .subscribe(Consumer { adapter.setOwnedMounts(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> { adapter.updateData(it) }, RxErrorHandler.handleEmptyError())) + compositeSubscription.add(inventoryRepository.getPets(animalType, animalGroup, animalColor) + .map { + val items = mutableListOf() + var lastPet: Pet? = null + for (pet in it) { + if (pet.type == "wacky" || pet.type == "special") continue + if (pet.type != lastPet?.type) { + items.add(pet.getTranslatedType(context)) + } + items.add(pet) + lastPet = pet + } + items + } + .subscribe(Consumer { adapter.setItemList(it) }, RxErrorHandler.handleEmptyError())) compositeSubscription.add(inventoryRepository.getMounts(animalType, animalGroup, animalColor).subscribe(Consumer> { adapter.setExistingMounts(it) }, RxErrorHandler.handleEmptyError())) } } + @Subscribe fun showFeedingDialog(event: FeedCommand) { if (event.usingPet == null || event.usingFood == null) { diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/inventory/stable/StableRecyclerFragment.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/inventory/stable/StableRecyclerFragment.kt index 147a49006..4c2d24c92 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/inventory/stable/StableRecyclerFragment.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/inventory/stable/StableRecyclerFragment.kt @@ -12,6 +12,7 @@ import com.habitrpg.android.habitica.extensions.getTranslatedType import com.habitrpg.android.habitica.extensions.inflate import com.habitrpg.android.habitica.helpers.RxErrorHandler import com.habitrpg.android.habitica.models.inventory.Animal +import com.habitrpg.android.habitica.models.inventory.StableSection import com.habitrpg.android.habitica.models.user.* import com.habitrpg.android.habitica.ui.activities.MainActivity import com.habitrpg.android.habitica.ui.adapter.inventory.StableRecyclerAdapter @@ -147,41 +148,50 @@ class StableRecyclerFragment : BaseFragment() { private fun mapAnimals(unsortedAnimals: RealmResults, ownedAnimals: Map): ArrayList { val items = ArrayList() var lastAnimal: Animal = unsortedAnimals[0] ?: return items - var lastSectionTitle = "" + var lastSection: StableSection? = null for (animal in unsortedAnimals) { val identifier = if (animal.animal.isNotEmpty() && (animal.type != "special" && animal.type != "wacky")) animal.animal else animal.key val lastIdentifier = if (lastAnimal.animal.isNotEmpty()) lastAnimal.animal else lastAnimal.key - if (identifier != lastIdentifier || animal === unsortedAnimals[unsortedAnimals.size - 1]) { - if (!((lastAnimal.type == "premium" || lastAnimal.type == "special") && lastAnimal.numberOwned == 0)) { + if (animal.type == "premium") { + if (!items.contains(lastAnimal)) { + items.add(lastAnimal) + } + lastAnimal = items.first { (it as? Animal)?.animal == animal.animal } as Animal + } else if (identifier != lastIdentifier || animal === unsortedAnimals[unsortedAnimals.size - 1]) { + if (!((lastAnimal.type == "special") && lastAnimal.numberOwned == 0) && !items.contains(lastAnimal)) { items.add(lastAnimal) } lastAnimal = animal } - lastAnimal.totalNumber += 1 - if (animal.type != lastSectionTitle) { - if (items.size > 0 && items[items.size - 1].javaClass == String::class.java) { + if (animal.type != lastSection?.key) { + if (items.size > 0 && items[items.size - 1].javaClass == StableSection::class.java) { items.removeAt(items.size - 1) } - items.add(animal.getTranslatedType(context)) - lastSectionTitle = animal.type + val section = StableSection(animal.type, animal.getTranslatedType(context)) + items.add(section) + lastSection = section } - when (itemType) { + val isOwned = when (itemType) { "pets" -> { val ownedPet = ownedAnimals[animal?.key] as? OwnedPet - if (ownedPet?.trained ?: 0 > 0) { - lastAnimal.numberOwned += 1 - } + ownedPet?.trained ?: 0 > 0 } "mounts" -> { val ownedMount = ownedAnimals[animal?.key] as? OwnedMount - if (ownedMount?.owned == true) { - lastAnimal.numberOwned = lastAnimal.numberOwned + 1 - } + ownedMount?.owned == true } + else -> false + } + if (animal.type != "premium" || isOwned) { + lastAnimal.totalNumber += 1 + lastSection?.totalCount = lastSection?.totalCount ?: 0 + 1 + } + if (isOwned) { + lastAnimal.numberOwned += 1 + lastSection?.ownedCount = lastSection?.ownedCount ?: 0 + 1 } - } if (!((lastAnimal.type == "premium" || lastAnimal.type == "special") && lastAnimal.numberOwned == 0)) { items.add(lastAnimal) diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/navigation/BottomNavigationItem.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/navigation/BottomNavigationItem.kt index 7cd9acd0d..132db1afb 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/navigation/BottomNavigationItem.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/navigation/BottomNavigationItem.kt @@ -22,16 +22,19 @@ class BottomNavigationItem @JvmOverloads constructor( private val titleView: TextView by bindView(R.id.title_view) private val badge: TextView by bindView(R.id.badge) + var selectedVisibility = View.VISIBLE + var deselectedVisibility = View.VISIBLE + var isActive = false set(value) { field = value if (isActive) { - selectedTitleView.visibility = View.VISIBLE + selectedTitleView.visibility = selectedVisibility titleView.visibility = View.GONE iconView.drawable.setColorFilter(ContextCompat.getColor(context, R.color.white), PorterDuff.Mode.MULTIPLY ) } else { selectedTitleView.visibility = View.GONE - titleView.visibility = View.VISIBLE + titleView.visibility = deselectedVisibility iconView.drawable.setColorFilter(context.getThemeColor(R.attr.textColorPrimaryDark), PorterDuff.Mode.MULTIPLY ) } } diff --git a/fastlane/README.md b/fastlane/README.md index 33ba19649..305cebbb2 100644 --- a/fastlane/README.md +++ b/fastlane/README.md @@ -12,7 +12,7 @@ Install _fastlane_ using ``` [sudo] gem install fastlane -NV ``` -or alternatively using `brew cask install fastlane` +or alternatively using `brew install fastlane` # Available Actions ## Android