Improve challenge filtering

This commit is contained in:
Phillip Thelen 2019-11-06 15:25:52 +01:00
parent b69fd0c8f5
commit 643e4ec11e
9 changed files with 33 additions and 47 deletions

View file

@ -151,7 +151,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 2291
versionCode 2292
versionName "2.3"
}

View file

@ -4,8 +4,6 @@ import com.habitrpg.android.habitica.models.social.Challenge
import com.habitrpg.android.habitica.models.social.ChallengeMembership
import com.habitrpg.android.habitica.models.tasks.Task
import com.habitrpg.android.habitica.models.tasks.TaskList
import com.habitrpg.android.habitica.models.user.User
import io.reactivex.Flowable
import io.realm.RealmResults
@ -33,7 +31,7 @@ interface ChallengeRepository : BaseRepository {
addedTaskList: List<Task>, updatedTaskList: List<Task>, removedTaskList: List<String>): Flowable<Challenge>
fun deleteChallenge(challengeId: String): Flowable<Void>
fun getUserChallenges(userId: String): Flowable<RealmResults<Challenge>>
fun getUserChallenges(userId: String? = null): Flowable<RealmResults<Challenge>>
fun leaveChallenge(challenge: Challenge, keepTasks: String): Flowable<Void>

View file

@ -118,8 +118,8 @@ class ChallengeRepositoryImpl(localRepository: ChallengeLocalRepository, apiClie
return localRepository.challenges
}
override fun getUserChallenges(userId: String): Flowable<RealmResults<Challenge>> {
return localRepository.getUserChallenges(userId)
override fun getUserChallenges(userId: String?): Flowable<RealmResults<Challenge>> {
return localRepository.getUserChallenges(userId ?: userID)
}
override fun retrieveChallenges(page: Int, memberOnly: Boolean): Flowable<List<Challenge>> {

View file

@ -71,7 +71,11 @@ class RealmChallengeLocalRepository(realm: Realm) : RealmBaseLocalRepository(rea
}.toTypedArray()
realm.where(Challenge::class.java)
.isNotNull("name")
.beginGroup()
.`in`("id", ids)
.or()
.equalTo("leaderId", userId)
.endGroup()
.sort("official", Sort.DESCENDING, "createdAt", Sort.DESCENDING)
.findAll()
.asFlowable()

View file

@ -686,7 +686,6 @@ open class MainActivity : BaseActivity(), TutorialView.OnTutorialReaction {
apiClient.readNotification(event.id)
.subscribe(Consumer { }, RxErrorHandler.handleEmptyError())
}, RxErrorHandler.handleEmptyError()))
}
override fun onEvent(event: ShowConnectionProblemEvent) {

View file

@ -1,16 +1,16 @@
package com.habitrpg.android.habitica.ui.adapter.social.challenges
import androidx.recyclerview.widget.RecyclerView
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.CheckBox
import androidx.recyclerview.widget.RecyclerView
import com.habitrpg.android.habitica.R
import com.habitrpg.android.habitica.models.social.Group
import com.habitrpg.android.habitica.ui.helpers.bindView
import java.util.*
class ChallengesFilterRecyclerViewAdapter(entries: Collection<Group>) : RecyclerView.Adapter<ChallengesFilterRecyclerViewAdapter.ChallengeViewHolder>() {
class ChallengesFilterRecyclerViewAdapter(entries: List<Group>) : RecyclerView.Adapter<ChallengesFilterRecyclerViewAdapter.ChallengeViewHolder>() {
private val entries: List<Group>
@ -66,7 +66,7 @@ class ChallengesFilterRecyclerViewAdapter(entries: Collection<Group>) : Recycler
fun selectAll(groupsToCheck: List<Group>) {
for (h in holderList) {
h.checkbox.isChecked =groupsToCheck.find { g -> h.group?.id == g.id } != null
h.checkbox.isChecked = groupsToCheck.find { g -> h.group?.id == g.id } != null
}
}

View file

@ -2,18 +2,16 @@ package com.habitrpg.android.habitica.ui.fragments.social.challenges
import android.app.Activity
import android.app.AlertDialog
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import android.view.View
import android.widget.Button
import android.widget.CheckBox
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.habitrpg.android.habitica.R
import com.habitrpg.android.habitica.models.social.Challenge
import com.habitrpg.android.habitica.models.social.Group
import com.habitrpg.android.habitica.ui.adapter.social.challenges.ChallengesFilterRecyclerViewAdapter
import com.habitrpg.android.habitica.ui.helpers.bindView
import com.habitrpg.android.habitica.utils.Action1
import java.util.*
internal class ChallengeFilterDialogHolder private constructor(view: View, private val context: Activity) {
@ -24,7 +22,7 @@ internal class ChallengeFilterDialogHolder private constructor(view: View, priva
private val checkboxNotOwned: CheckBox? by bindView(view, R.id.challenge_filter_not_owned)
private var dialog: AlertDialog? = null
private var challengesViewed: List<Challenge>? = null
private var filterGroups: List<Group>? = null
private var currentFilter: ChallengeFilterOptions? = null
private var selectedGroupsCallback: Action1<ChallengeFilterOptions>? = null
private var adapter: ChallengesFilterRecyclerViewAdapter? = null
@ -34,12 +32,12 @@ internal class ChallengeFilterDialogHolder private constructor(view: View, priva
noneButton?.setOnClickListener { noneClicked() }
}
fun bind(builder: AlertDialog.Builder, challengesViewed: List<Challenge>,
fun bind(builder: AlertDialog.Builder, filterGroups: List<Group>,
currentFilter: ChallengeFilterOptions?,
selectedGroupsCallback: Action1<ChallengeFilterOptions>) {
builder.setPositiveButton(context.getString(R.string.done)) { _, _ -> doneClicked() }
.show()
this.challengesViewed = challengesViewed
this.filterGroups = filterGroups
this.currentFilter = currentFilter
this.selectedGroupsCallback = selectedGroupsCallback
fillChallengeGroups()
@ -52,7 +50,7 @@ internal class ChallengeFilterDialogHolder private constructor(view: View, priva
private fun fillChallengeGroups() {
this.groupRecyclerView?.layoutManager = LinearLayoutManager(context)
adapter = ChallengesFilterRecyclerViewAdapter(getGroups(challengesViewed))
adapter = filterGroups?.let { ChallengesFilterRecyclerViewAdapter(it) }
if (currentFilter != null && currentFilter?.showByGroups != null) {
adapter?.selectAll(currentFilter?.showByGroups ?: emptyList())
}
@ -60,25 +58,6 @@ internal class ChallengeFilterDialogHolder private constructor(view: View, priva
this.groupRecyclerView?.adapter = adapter
}
private fun getGroups(challenges: List<Challenge>?): Collection<Group> {
val groupMap = HashMap<String, Group>()
if (challenges != null) {
for (challenge in challenges) {
if (groupMap.containsKey(challenge.groupName)) {
continue
}
val group = Group()
group.id = challenge.groupId ?: ""
group.name = challenge.groupName
groupMap[challenge.groupName ?: ""] = group
}
}
return groupMap.values
}
private fun doneClicked() {
val options = ChallengeFilterOptions()
options.showByGroups = this.adapter?.checkedEntries
@ -100,7 +79,7 @@ internal class ChallengeFilterDialogHolder private constructor(view: View, priva
companion object {
fun showDialog(activity: Activity, challengesViewed: List<Challenge>,
fun showDialog(activity: Activity, filterGroups: List<Group>,
currentFilter: ChallengeFilterOptions?,
selectedGroupsCallback: Action1<ChallengeFilterOptions>) {
val dialogLayout = activity.layoutInflater.inflate(R.layout.dialog_challenge_filter, null)
@ -111,7 +90,7 @@ internal class ChallengeFilterDialogHolder private constructor(view: View, priva
.setTitle(R.string.filter)
.setView(dialogLayout)
challengeFilterDialogHolder.bind(builder, challengesViewed, currentFilter, selectedGroupsCallback)
challengeFilterDialogHolder.bind(builder, filterGroups, currentFilter, selectedGroupsCallback)
}
}

View file

@ -8,12 +8,13 @@ import androidx.recyclerview.widget.RecyclerView
import com.habitrpg.android.habitica.R
import com.habitrpg.android.habitica.components.UserComponent
import com.habitrpg.android.habitica.data.ChallengeRepository
import com.habitrpg.android.habitica.data.SocialRepository
import com.habitrpg.android.habitica.data.UserRepository
import com.habitrpg.android.habitica.extensions.inflate
import com.habitrpg.android.habitica.helpers.MainNavigationController
import com.habitrpg.android.habitica.helpers.RxErrorHandler
import com.habitrpg.android.habitica.models.social.Challenge
import com.habitrpg.android.habitica.models.user.User
import com.habitrpg.android.habitica.models.social.Group
import com.habitrpg.android.habitica.modules.AppModule
import com.habitrpg.android.habitica.ui.adapter.social.ChallengesListViewAdapter
import com.habitrpg.android.habitica.ui.fragments.BaseFragment
@ -24,6 +25,7 @@ import com.habitrpg.android.habitica.ui.helpers.resetViews
import com.habitrpg.android.habitica.utils.Action1
import io.reactivex.Flowable
import io.reactivex.functions.Consumer
import io.reactivex.rxkotlin.combineLatest
import io.realm.RealmResults
import javax.inject.Inject
import javax.inject.Named
@ -34,10 +36,11 @@ class ChallengeListFragment : BaseFragment(), androidx.swiperefreshlayout.widget
@Inject
lateinit var challengeRepository: ChallengeRepository
@Inject
lateinit var socialRepository: SocialRepository
@Inject
lateinit var userRepository: UserRepository
@field:[Inject Named(AppModule.NAMED_USER_ID)]
lateinit var userId: String
var user: User? = null
private val swipeRefreshLayout: androidx.swiperefreshlayout.widget.SwipeRefreshLayout? by bindView(R.id.refreshLayout)
private val recyclerView: RecyclerViewEmptySupport? by bindView(R.id.recyclerView)
@ -50,6 +53,7 @@ class ChallengeListFragment : BaseFragment(), androidx.swiperefreshlayout.widget
private var loadedAllData = false
private var challenges: RealmResults<Challenge>? = null
private var filterGroups: MutableList<Group>? = null
private var filterOptions: ChallengeFilterOptions? = null
@ -85,7 +89,11 @@ class ChallengeListFragment : BaseFragment(), androidx.swiperefreshlayout.widget
this.recyclerView?.setBackgroundResource(R.color.white)
}
compositeSubscription.add(userRepository.getUser().subscribe(Consumer { this.user = it}, RxErrorHandler.handleEmptyError()))
compositeSubscription.add(socialRepository.getGroup(Group.TAVERN_ID).combineLatest(socialRepository.getUserGroups()).subscribe(Consumer {
this.filterGroups = mutableListOf()
filterGroups?.add(it.first)
filterGroups?.addAll(it.second)
}, RxErrorHandler.handleEmptyError()))
recyclerView?.setEmptyView(emptyView)
recyclerView?.itemAnimator = SafeDefaultItemAnimator()
@ -123,8 +131,8 @@ class ChallengeListFragment : BaseFragment(), androidx.swiperefreshlayout.widget
}
private fun loadLocalChallenges() {
val observable: Flowable<RealmResults<Challenge>> = if (viewUserChallengesOnly && user != null) {
challengeRepository.getUserChallenges(user?.id ?: "")
val observable: Flowable<RealmResults<Challenge>> = if (viewUserChallengesOnly) {
challengeRepository.getUserChallenges()
} else {
challengeRepository.getChallenges()
}
@ -156,7 +164,7 @@ class ChallengeListFragment : BaseFragment(), androidx.swiperefreshlayout.widget
internal fun showFilterDialog() {
activity?.let {
ChallengeFilterDialogHolder.showDialog(it,
challenges ?: emptyList(),
filterGroups ?: emptyList(),
filterOptions, object : Action1<ChallengeFilterOptions> {
override fun call(t: ChallengeFilterOptions) {
changeFilter(t)

View file

@ -39,10 +39,8 @@ class ChallengesOverviewFragment : BaseMainFragment() {
resetViews()
userChallengesFragment?.user = this.user
userChallengesFragment?.setViewUserChallengesOnly(true)
availableChallengesFragment?.user = this.user
availableChallengesFragment?.setViewUserChallengesOnly(false)
setViewPagerAdapter()
}