Add search to task view

This commit is contained in:
Phillip Thelen 2019-08-30 13:25:15 +02:00
parent ca68ac1d18
commit 8ad5ae2d90
13 changed files with 91 additions and 22 deletions

View file

@ -152,7 +152,7 @@ android {
buildConfigField "String", "TESTING_LEVEL", "\"production\""
multiDexEnabled true
versionCode 2224
versionCode 2226
versionName "2.1"
}

View file

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:viewportHeight="24.0" android:viewportWidth="24.0" android:width="24dp">
<path android:fillColor="#FFFFFF" android:pathData="M15.5,14h-0.79l-0.28,-0.27C15.41,12.59 16,11.11 16,9.5 16,5.91 13.09,3 9.5,3S3,5.91 3,9.5 5.91,16 9.5,16c1.61,0 3.09,-0.59 4.23,-1.57l0.27,0.28v0.79l5,4.99L20.49,19l-4.99,-5zM9.5,14C7.01,14 5,11.99 5,9.5S7.01,5 9.5,5 14,7.01 14,9.5 11.99,14 9.5,14z"/>
</vector>

View file

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.appcompat.widget.SearchView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:iconifiedByDefault="false"
app:searchHintIcon="@null"
app:searchIcon="@null"
android:theme="@style/SearchViewStyle"
app:queryHint="@string/search"
tools:background="@color/brand" />

View file

@ -8,10 +8,14 @@
android:icon="@drawable/ic_refresh_white"
android:title="@string/action_refresh"
app:showAsAction="never"
android:actionViewClass="android.widget.ImageButton"/>
<!-- Search, should appear as action button -->
app:actionViewClass="android.widget.ImageButton"/>
<item android:id="@+id/action_search"
android:title="@string/search"
android:icon="@drawable/ic_search"
app:showAsAction="collapseActionView|always"
app:actionLayout="@layout/toolbar_search" />
<item android:id="@+id/action_filter"
android:icon="@drawable/ic_action_filter_list"
android:title="@string/filter"
app:showAsAction="ifRoom" />

View file

@ -841,4 +841,6 @@
<string name="reject">Reject</string>
<string name="complete">Complete</string>
<string name="repeat_daily">Daily</string>
<string name="search">Search</string>
<string name="search_hint">Search tasks</string>
</resources>

View file

@ -46,6 +46,8 @@
<item name="android:statusBarColor">@color/brand_50</item>
<item name="android:navigationBarColor">@color/brand_50</item>
<item name="searchViewStyle">@style/SearchViewStyle</item>
</style>
@ -646,6 +648,11 @@
<item name="android:actionMenuTextColor">@color/red_50</item>
</style>
<style name="SearchViewStyle" parent="Widget.AppCompat.SearchView">
<item name="android:textColorHint">@color/white_50_alpha</item>
<item name="searchHintIcon">@null</item>
</style>
<color name="taskform_gray">#99edecee</color>
</resources>

View file

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<searchable xmlns:android="http://schemas.android.com/apk/res/android"
android:label="@string/app_name"
android:hint="@string/search_hint" />

View file

@ -1,11 +1,13 @@
package com.habitrpg.android.habitica.helpers
import com.habitrpg.android.habitica.models.tasks.Task
import io.realm.Case
import io.realm.OrderedRealmCollection
import io.realm.RealmQuery
import java.util.*
class TaskFilterHelper {
var searchQuery: String? = null
private var tagsId: MutableList<String> = ArrayList()
private val activeFilters = HashMap<String, String>()
@ -96,6 +98,9 @@ class TaskFilterHelper {
if (tagsId.size > 0) {
query = query.`in`("tags.id", tagsId.toTypedArray())
}
if (searchQuery?.isNotEmpty() == true) {
query = query.beginsWith("text", searchQuery ?: "", Case.INSENSITIVE)
}
if (activeFilter != null && activeFilter != Task.FILTER_ALL) {
when (activeFilter) {
Task.FILTER_ACTIVE -> query = if (Task.TYPE_DAILY == taskType) {

View file

@ -236,7 +236,10 @@ open class Task : RealmObject, Parcelable {
}
return if (Task::class.java.isAssignableFrom(other.javaClass)) {
val otherTask = other as? Task
this.id == otherTask?.id
if (!this.isValid || otherTask?.isValid != true) {
return false
}
this.id == otherTask.id
} else {
super.equals(other)
}

View file

@ -5,6 +5,7 @@ import android.content.Intent
import android.graphics.PorterDuff
import android.os.Bundle
import android.view.*
import androidx.appcompat.widget.SearchView
import androidx.fragment.app.FragmentPagerAdapter
import com.habitrpg.android.habitica.HabiticaBaseApplication
import com.habitrpg.android.habitica.R
@ -25,7 +26,8 @@ import java.util.*
import javax.inject.Inject
import kotlin.collections.ArrayList
class TasksFragment : BaseMainFragment() {
class TasksFragment : BaseMainFragment(), SearchView.OnQueryTextListener {
var viewPager: androidx.viewpager.widget.ViewPager? = null
@Inject
@ -108,13 +110,40 @@ class TasksFragment : BaseMainFragment() {
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
inflater.inflate(R.menu.menu_main_activity, menu)
filterMenuItem = menu.findItem(R.id.action_search)
filterMenuItem = menu.findItem(R.id.action_filter)
updateFilterIcon()
val item = menu.findItem(R.id.action_search)
val sv = item.actionView as? SearchView
sv?.setOnQueryTextListener(this)
sv?.setIconifiedByDefault(false)
item.setOnActionExpandListener(object : MenuItem.OnActionExpandListener {
override fun onMenuItemActionCollapse(item: MenuItem): Boolean {
filterMenuItem?.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS)
return true
}
override fun onMenuItemActionExpand(item: MenuItem): Boolean {
// Do something when expanded
filterMenuItem?.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER)
return true
}
})
}
override fun onQueryTextSubmit(query: String?): Boolean {
return true
}
override fun onQueryTextChange(newText: String?): Boolean {
taskFilterHelper.searchQuery = newText
viewFragmentsDictionary?.values?.forEach { values -> values.recyclerAdapter?.filter() }
return true
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
return when (item.itemId) {
R.id.action_search -> {
R.id.action_filter -> {
showFilterDialog()
true
}
@ -145,14 +174,11 @@ class TasksFragment : BaseMainFragment() {
if (viewFragmentsDictionary == null) {
return
}
val activePos = viewPager?.currentItem ?: 0
viewFragmentsDictionary?.get(activePos - 1)?.recyclerAdapter?.filter()
viewFragmentsDictionary?.get(activePos + 1)?.recyclerAdapter?.filter()
taskFilterHelper.tags = activeTags
if (activeTaskFilter != null) {
activeFragment?.setActiveFilter(activeTaskFilter)
}
viewFragmentsDictionary?.values?.forEach { it.recyclerAdapter?.filter() }
viewFragmentsDictionary?.values?.forEach { values -> values.recyclerAdapter?.filter() }
updateFilterIcon()
}
})

View file

@ -8,7 +8,7 @@ import androidx.core.view.ViewCompat
import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.SimpleItemAnimator
import com.habitrpg.shared.habitica.LogLevel
import com.habitrpg.shared.habitica.Logger
import com.habitrpg.shared.habitica.HLogger
import java.util.*
/**
@ -226,8 +226,8 @@ class SafeDefaultItemAnimator : SimpleItemAnimator() {
if (deltaY != 0) {
view.translationY = (-deltaY).toFloat()
}
Logger.log(LogLevel.INFO, "Moving1", "$toX, $fromX, $deltaX")
Logger.log(LogLevel.INFO, "Moving1", "$toX, $fromX, $deltaX")
HLogger.log(LogLevel.INFO, "Moving1", "$toX, $fromX, $deltaX")
HLogger.log(LogLevel.INFO, "Moving1", "$toX, $fromX, $deltaX")
pendingMoves.add(MoveInfo(holder, newFromX, newFromY, toX, toY))
return true
}
@ -242,8 +242,8 @@ class SafeDefaultItemAnimator : SimpleItemAnimator() {
if (deltaY != 0) {
view.animate().translationY(0f)
}
Logger.log(LogLevel.INFO, "Moving", "$toX, $fromX, $deltaX")
Logger.log(LogLevel.INFO, "Moving", "$toX, $fromX, $deltaX")
HLogger.log(LogLevel.INFO, "Moving", "$toX, $fromX, $deltaX")
HLogger.log(LogLevel.INFO, "Moving", "$toX, $fromX, $deltaX")
// vpas are canceled (and can't end them. why?)
// need listener functionality in VPACompat for this. Ick.
val animation = view.animate()
@ -295,8 +295,8 @@ class SafeDefaultItemAnimator : SimpleItemAnimator() {
newHolder.itemView.translationY = (-deltaY).toFloat()
newHolder.itemView.alpha = 0f
}
Logger.log(LogLevel.INFO, "Changing", "$toX, $fromX, $deltaX")
Logger.log(LogLevel.INFO, "Changing", "$toX, $fromX, $deltaX")
HLogger.log(LogLevel.INFO, "Changing", "$toX, $fromX, $deltaX")
HLogger.log(LogLevel.INFO, "Changing", "$toX, $fromX, $deltaX")
newHolder?.let { pendingChanges.add(ChangeInfo(oldHolder, it, fromX, fromY, toX, toY)) }
return true
}

View file

@ -63,9 +63,11 @@ private class MessagesDataSource(val socialRepository: SocialRepository, val rec
override fun loadInitial(params: LoadInitialParams, callback: LoadInitialCallback<ChatMessage>) {
lastFetchWasEnd = false
GlobalScope.launch(Dispatchers.Main.immediate) {
socialRepository.getInboxMessages(recipientID).firstElement()
socialRepository.getInboxMessages(recipientID)
.map { socialRepository.getUnmanagedCopy(it) }
.firstElement()
.flatMapPublisher {
if (it.size == 0) {
if (it.isEmpty()) {
socialRepository.retrieveInboxMessages(recipientID, 0)
.doOnNext {
messages -> if (messages.size != 10) lastFetchWasEnd = true

View file

@ -13,7 +13,7 @@ enum class LogLevel {
ERROR, INFO, DEBUG
}
class Logger {
class HLogger {
companion object {
private val platformLogger = PlatformLogger()