From bcd2c2e2aa7b31cfa1e82e58881499eb5f0cc13e Mon Sep 17 00:00:00 2001 From: Hafiz Date: Fri, 18 Feb 2022 09:43:17 -0500 Subject: [PATCH 1/5] Add ability for users to create party from quest items --- Habitica/res/values/strings.xml | 3 ++ .../adapter/inventory/ItemRecyclerAdapter.kt | 19 +++++++- .../inventory/items/ItemDialogFragment.kt | 2 +- .../inventory/items/ItemRecyclerFragment.kt | 44 ++++++++++++++++++- 4 files changed, 63 insertions(+), 5 deletions(-) diff --git a/Habitica/res/values/strings.xml b/Habitica/res/values/strings.xml index 1047ee33d..17b7b8d70 100644 --- a/Habitica/res/values/strings.xml +++ b/Habitica/res/values/strings.xml @@ -242,6 +242,8 @@ Equipped Are you sure you want to cancel this Quest? Canceling the Quest will cancel all accepted and pending invitations. The Quest will be returned to the owner’s inventory. Are you sure? Only %1$d of your %2$d party members have joined this quest! Quests start automatically when all players have joined or rejected the invitation. + You have to be in a Party before starting a Quest + Once in a Party, you can take on Quests by yourself or invite friends to Quest with them too! 1 month ago %d months ago 1w ago @@ -789,6 +791,7 @@ Create Only leader can create Challenges Create Party + Create a Party Add Local Authentication Task Title 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 9d5188afc..bfa076a30 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 @@ -2,6 +2,7 @@ package com.habitrpg.android.habitica.ui.adapter.inventory import android.content.Context import android.content.res.Resources +import android.os.Bundle import android.view.View import android.view.ViewGroup import androidx.fragment.app.DialogFragment @@ -12,6 +13,7 @@ import com.habitrpg.android.habitica.extensions.layoutInflater 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.User import com.habitrpg.android.habitica.ui.adapter.BaseRecyclerViewAdapter import com.habitrpg.android.habitica.ui.helpers.DataBindingUtils import com.habitrpg.android.habitica.ui.menu.BottomSheetMenu @@ -23,7 +25,7 @@ import io.reactivex.rxjava3.subjects.PublishSubject import java.text.SimpleDateFormat import java.util.* -class ItemRecyclerAdapter(val context: Context) : BaseRecyclerViewAdapter() { +class ItemRecyclerAdapter(val context: Context, val user: User?) : BaseRecyclerViewAdapter() { var isHatching: Boolean = false var isFeeding: Boolean = false @@ -44,6 +46,7 @@ class ItemRecyclerAdapter(val context: Context) : BaseRecyclerViewAdapter() private val hatchPetSubject = PublishSubject.create>() private val feedPetSubject = PublishSubject.create() + private val createNewPartySubject = PublishSubject.create() fun getSellItemFlowable(): Flowable { return sellItemEvents.toFlowable(BackpressureStrategy.DROP) @@ -59,6 +62,7 @@ class ItemRecyclerAdapter(val context: Context) : BaseRecyclerViewAdapter = startHatchingSubject.toFlowable(BackpressureStrategy.DROP) val hatchPetEvents: Flowable> = hatchPetSubject.toFlowable(BackpressureStrategy.DROP) val feedPetEvents: Flowable = feedPetSubject.toFlowable(BackpressureStrategy.DROP) + val startNewPartyEvents: Flowable = createNewPartySubject.toFlowable(BackpressureStrategy.DROP) override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { return ItemViewHolder(ItemItemBinding.inflate(context.layoutInflater, parent, false)) @@ -173,7 +177,18 @@ class ItemRecyclerAdapter(val context: Context) : BaseRecyclerViewAdapter openMysteryItemEvents.onNext(selectedItem) diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/inventory/items/ItemDialogFragment.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/inventory/items/ItemDialogFragment.kt index 27d2f0368..f208af7a5 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/inventory/items/ItemDialogFragment.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/inventory/items/ItemDialogFragment.kt @@ -102,7 +102,7 @@ class ItemDialogFragment : BaseDialogFragment(), SwipeRefr adapter = binding?.recyclerView?.adapter as? ItemRecyclerAdapter if (adapter == null) { context?.let { - adapter = ItemRecyclerAdapter(context) + adapter = ItemRecyclerAdapter(context, user) adapter?.isHatching = this.isHatching adapter?.isFeeding = this.isFeeding adapter?.fragment = this 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 52e1a3262..9fbb4dcf5 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 @@ -4,6 +4,7 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import androidx.core.os.bundleOf import androidx.swiperefreshlayout.widget.SwipeRefreshLayout import com.habitrpg.android.habitica.R import com.habitrpg.android.habitica.components.UserComponent @@ -16,7 +17,6 @@ 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.interactors.NotifyUserUseCase import com.habitrpg.android.habitica.models.inventory.* import com.habitrpg.android.habitica.models.user.OwnedPet import com.habitrpg.android.habitica.models.user.User @@ -27,6 +27,7 @@ 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.dialogs.HabiticaAlertDialog import com.habitrpg.android.habitica.ui.views.dialogs.OpenedMysteryitemDialog import javax.inject.Inject @@ -87,7 +88,7 @@ class ItemRecyclerFragment : BaseFragment(), SwipeRefreshL adapter = binding?.recyclerView?.adapter as? ItemRecyclerAdapter if (adapter == null) { context?.let { - adapter = ItemRecyclerAdapter(context) + adapter = ItemRecyclerAdapter(context, user) } binding?.recyclerView?.adapter = adapter @@ -132,6 +133,7 @@ class ItemRecyclerFragment : BaseFragment(), SwipeRefreshL ) compositeSubscription.add(adapter.startHatchingEvents.subscribeWithErrorHandler { showHatchingDialog(it) }) compositeSubscription.add(adapter.hatchPetEvents.subscribeWithErrorHandler { hatchPet(it.first, it.second) }) + compositeSubscription.addAll(adapter.startNewPartyEvents.subscribeWithErrorHandler { createNewParty(it) }) } } activity?.let { @@ -193,6 +195,44 @@ class ItemRecyclerFragment : BaseFragment(), SwipeRefreshL } } + private fun createNewParty(bundle: Bundle) { + val alert = context?.let { HabiticaAlertDialog(it) }//Context results? + alert?.setTitle(R.string.quest_party_required_title) + alert?.setMessage(R.string.quest_party_required_description) + alert?.addButton(R.string.create_a_party, true, false) { _, _ -> + socialRepository.createGroup( + bundle.getString("name"), + bundle.getString("description"), + bundle.getString("leader"), + "party", + bundle.getString("privacy"), + bundle.getBoolean("leaderCreateChallenge") + ) + .flatMap { + userRepository.retrieveUser(false) + } + .subscribe( + { + if (isAdded) { + parentFragmentManager.popBackStack()//Needed? + } + MainNavigationController.navigate(//Same nav? + R.id.partyFragment, + bundleOf(Pair("partyID", user?.party?.id)) + ) + }, + RxErrorHandler.handleEmptyError() + ) + + } + alert?.addButton(R.string.close, false) { _, _ -> + alert.dismiss() + } + alert?.show() + + + } + private fun loadItems() { val itemClass: Class = when (itemType) { "eggs" -> Egg::class.java From 5409066318c37b7c6e9a789d4d554b72e3ee4975 Mon Sep 17 00:00:00 2001 From: Hafiz Date: Fri, 18 Feb 2022 10:40:59 -0500 Subject: [PATCH 2/5] Update quest item menu description Update quest item menu description Retrieve members --- Habitica/res/values/strings.xml | 1 + .../ui/adapter/inventory/ItemRecyclerAdapter.kt | 12 ++++++++---- .../inventory/items/ItemRecyclerFragment.kt | 5 ++++- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/Habitica/res/values/strings.xml b/Habitica/res/values/strings.xml index 17b7b8d70..1af6bf802 100644 --- a/Habitica/res/values/strings.xml +++ b/Habitica/res/values/strings.xml @@ -281,6 +281,7 @@ Hatch with potion Hatch with egg Invite party + Create new party Feed %s with: Use Feed 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 bfa076a30..a371b7f6b 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 @@ -155,7 +155,11 @@ class ItemRecyclerAdapter(val context: Context, val user: User?) : BaseRecyclerV menu.addMenuItem(BottomSheetMenuItem(resources.getString(R.string.hatch_egg))) } else if (item is QuestContent) { menu.addMenuItem(BottomSheetMenuItem(resources.getString(R.string.details))) - menu.addMenuItem(BottomSheetMenuItem(resources.getString(R.string.invite_party))) + if (user?.hasParty == true){ + menu.addMenuItem(BottomSheetMenuItem(resources.getString(R.string.invite_party))) + } else { + menu.addMenuItem(BottomSheetMenuItem(resources.getString(R.string.create_new_party))) + } } else if (item is SpecialItem) { val specialItem = item as SpecialItem if (specialItem.isMysteryItem && ownedItem?.numberOwned ?: 0 > 0) { @@ -177,13 +181,13 @@ class ItemRecyclerAdapter(val context: Context, val user: User?) : BaseRecyclerV dialog.quest = selectedItem dialog.show() } else { - if (user?.hasParty == true) { + if (user?.hasParty == true || user == null) { questInvitationEvents.onNext(selectedItem) } else { val bundle = Bundle() bundle.putString("groupType", "party") - bundle.putString("leader", user?.id)//Check null values - bundle.putString("name", user?.username) + bundle.putString("leader", user.id)//Check null values + bundle.putString("name", user.username) bundle.putString("description", "") bundle.putBoolean("leaderOnlyChallenges", false) createNewPartySubject.onNext(bundle) 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 9fbb4dcf5..f0b84d671 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 @@ -209,7 +209,10 @@ class ItemRecyclerFragment : BaseFragment(), SwipeRefreshL bundle.getBoolean("leaderCreateChallenge") ) .flatMap { - userRepository.retrieveUser(false) + userRepository.retrieveUser(false, true) + .filter { it.hasParty } + .flatMap { socialRepository.retrieveGroup("party") } + .flatMap { group1 -> socialRepository.retrieveGroupMembers(group1.id, true) } } .subscribe( { From f645f227150c7c1c977753ffab2c719c45cd8a94 Mon Sep 17 00:00:00 2001 From: Hafiz Date: Fri, 18 Feb 2022 10:52:08 -0500 Subject: [PATCH 3/5] User null check --- .../habitica/ui/adapter/inventory/ItemRecyclerAdapter.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 a371b7f6b..055041d00 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 @@ -155,7 +155,7 @@ class ItemRecyclerAdapter(val context: Context, val user: User?) : BaseRecyclerV menu.addMenuItem(BottomSheetMenuItem(resources.getString(R.string.hatch_egg))) } else if (item is QuestContent) { menu.addMenuItem(BottomSheetMenuItem(resources.getString(R.string.details))) - if (user?.hasParty == true){ + if (user?.hasParty == true || user == null){ menu.addMenuItem(BottomSheetMenuItem(resources.getString(R.string.invite_party))) } else { menu.addMenuItem(BottomSheetMenuItem(resources.getString(R.string.create_new_party))) From ede1668da4912d12d46464854c16ea0c8cccf054 Mon Sep 17 00:00:00 2001 From: Hafiz Date: Fri, 18 Feb 2022 11:12:23 -0500 Subject: [PATCH 4/5] Update party name from name -> name's party --- .../habitica/ui/adapter/inventory/ItemRecyclerAdapter.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 055041d00..d4efd4e91 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 @@ -187,7 +187,7 @@ class ItemRecyclerAdapter(val context: Context, val user: User?) : BaseRecyclerV val bundle = Bundle() bundle.putString("groupType", "party") bundle.putString("leader", user.id)//Check null values - bundle.putString("name", user.username) + bundle.putString("name", user.profile?.name + "'s " + "Party") bundle.putString("description", "") bundle.putBoolean("leaderOnlyChallenges", false) createNewPartySubject.onNext(bundle) From 92cf00def31f684380a2a231277f61e5aad50579 Mon Sep 17 00:00:00 2001 From: Hafiz Date: Tue, 1 Mar 2022 08:27:30 -0500 Subject: [PATCH 5/5] Code Cleanup & update create party string resources --- Habitica/res/values/strings.xml | 2 +- .../adapter/inventory/ItemRecyclerAdapter.kt | 16 ++++------ .../inventory/items/ItemRecyclerFragment.kt | 30 +++++++++---------- 3 files changed, 21 insertions(+), 27 deletions(-) diff --git a/Habitica/res/values/strings.xml b/Habitica/res/values/strings.xml index 1af6bf802..a204ca68d 100644 --- a/Habitica/res/values/strings.xml +++ b/Habitica/res/values/strings.xml @@ -134,6 +134,7 @@ Buy Dismiss Party + %s\'s Party Chat Members Habits @@ -792,7 +793,6 @@ Create Only leader can create Challenges Create Party - Create a Party Add Local Authentication Task Title 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 d4efd4e91..88143efb8 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 @@ -46,7 +46,7 @@ class ItemRecyclerAdapter(val context: Context, val user: User?) : BaseRecyclerV private val startHatchingSubject = PublishSubject.create() private val hatchPetSubject = PublishSubject.create>() private val feedPetSubject = PublishSubject.create() - private val createNewPartySubject = PublishSubject.create() + private val createNewPartySubject = PublishSubject.create() fun getSellItemFlowable(): Flowable { return sellItemEvents.toFlowable(BackpressureStrategy.DROP) @@ -62,7 +62,7 @@ class ItemRecyclerAdapter(val context: Context, val user: User?) : BaseRecyclerV val startHatchingEvents: Flowable = startHatchingSubject.toFlowable(BackpressureStrategy.DROP) val hatchPetEvents: Flowable> = hatchPetSubject.toFlowable(BackpressureStrategy.DROP) val feedPetEvents: Flowable = feedPetSubject.toFlowable(BackpressureStrategy.DROP) - val startNewPartyEvents: Flowable = createNewPartySubject.toFlowable(BackpressureStrategy.DROP) + val startNewPartyEvents: Flowable = createNewPartySubject.toFlowable(BackpressureStrategy.DROP) override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { return ItemViewHolder(ItemItemBinding.inflate(context.layoutInflater, parent, false)) @@ -155,7 +155,7 @@ class ItemRecyclerAdapter(val context: Context, val user: User?) : BaseRecyclerV menu.addMenuItem(BottomSheetMenuItem(resources.getString(R.string.hatch_egg))) } else if (item is QuestContent) { menu.addMenuItem(BottomSheetMenuItem(resources.getString(R.string.details))) - if (user?.hasParty == true || user == null){ + if (user?.hasParty == true){ menu.addMenuItem(BottomSheetMenuItem(resources.getString(R.string.invite_party))) } else { menu.addMenuItem(BottomSheetMenuItem(resources.getString(R.string.create_new_party))) @@ -181,16 +181,10 @@ class ItemRecyclerAdapter(val context: Context, val user: User?) : BaseRecyclerV dialog.quest = selectedItem dialog.show() } else { - if (user?.hasParty == true || user == null) { + if (user?.hasParty == true) { questInvitationEvents.onNext(selectedItem) } else { - val bundle = Bundle() - bundle.putString("groupType", "party") - bundle.putString("leader", user.id)//Check null values - bundle.putString("name", user.profile?.name + "'s " + "Party") - bundle.putString("description", "") - bundle.putBoolean("leaderOnlyChallenges", false) - createNewPartySubject.onNext(bundle) + createNewPartySubject.onNext(true) } } 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 f0b84d671..1031771ba 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 @@ -195,31 +195,33 @@ class ItemRecyclerFragment : BaseFragment(), SwipeRefreshL } } - private fun createNewParty(bundle: Bundle) { - val alert = context?.let { HabiticaAlertDialog(it) }//Context results? + private fun createNewParty(isCreateNewParty: Boolean) { + val alert = context?.let { HabiticaAlertDialog(it) } alert?.setTitle(R.string.quest_party_required_title) alert?.setMessage(R.string.quest_party_required_description) - alert?.addButton(R.string.create_a_party, true, false) { _, _ -> + alert?.addButton(R.string.create_new_party, true, false) { _, _ -> socialRepository.createGroup( - bundle.getString("name"), - bundle.getString("description"), - bundle.getString("leader"), + getString(R.string.usernames_party, user?.profile?.name), + "", + user?.id, "party", - bundle.getString("privacy"), - bundle.getBoolean("leaderCreateChallenge") + "", + false ) .flatMap { userRepository.retrieveUser(false, true) .filter { it.hasParty } .flatMap { socialRepository.retrieveGroup("party") } - .flatMap { group1 -> socialRepository.retrieveGroupMembers(group1.id, true) } + .flatMap { group1 -> + socialRepository.retrieveGroupMembers( + group1.id, + true + ) + } } .subscribe( { - if (isAdded) { - parentFragmentManager.popBackStack()//Needed? - } - MainNavigationController.navigate(//Same nav? + MainNavigationController.navigate( R.id.partyFragment, bundleOf(Pair("partyID", user?.party?.id)) ) @@ -232,8 +234,6 @@ class ItemRecyclerFragment : BaseFragment(), SwipeRefreshL alert.dismiss() } alert?.show() - - } private fun loadItems() {