diff --git a/Habitica/build.gradle b/Habitica/build.gradle
index 8b68dfbdb..34a60a120 100644
--- a/Habitica/build.gradle
+++ b/Habitica/build.gradle
@@ -152,7 +152,7 @@ android {
buildConfigField "String", "TESTING_LEVEL", "\"production\""
multiDexEnabled true
- versionCode 2224
+ versionCode 2226
versionName "2.1"
}
diff --git a/Habitica/res/drawable/ic_search.xml b/Habitica/res/drawable/ic_search.xml
new file mode 100644
index 000000000..6ba0de078
--- /dev/null
+++ b/Habitica/res/drawable/ic_search.xml
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/Habitica/res/layout/toolbar_search.xml b/Habitica/res/layout/toolbar_search.xml
new file mode 100644
index 000000000..ffdd8f28f
--- /dev/null
+++ b/Habitica/res/layout/toolbar_search.xml
@@ -0,0 +1,12 @@
+
+
\ No newline at end of file
diff --git a/Habitica/res/menu/menu_main_activity.xml b/Habitica/res/menu/menu_main_activity.xml
index 542721cdf..7225931c4 100644
--- a/Habitica/res/menu/menu_main_activity.xml
+++ b/Habitica/res/menu/menu_main_activity.xml
@@ -8,10 +8,14 @@
android:icon="@drawable/ic_refresh_white"
android:title="@string/action_refresh"
app:showAsAction="never"
- android:actionViewClass="android.widget.ImageButton"/>
-
-
+ app:actionViewClass="android.widget.ImageButton"/>
+
+
diff --git a/Habitica/res/values/strings.xml b/Habitica/res/values/strings.xml
index d2e0a2053..689c799cf 100644
--- a/Habitica/res/values/strings.xml
+++ b/Habitica/res/values/strings.xml
@@ -841,4 +841,6 @@
Reject
Complete
Daily
+ Search
+ Search tasks
diff --git a/Habitica/res/values/styles.xml b/Habitica/res/values/styles.xml
index f81c07ba1..cf59fc0c4 100644
--- a/Habitica/res/values/styles.xml
+++ b/Habitica/res/values/styles.xml
@@ -46,6 +46,8 @@
- @color/brand_50
- @color/brand_50
+
+ - @style/SearchViewStyle
@@ -646,6 +648,11 @@
- @color/red_50
+
+
#99edecee
\ No newline at end of file
diff --git a/Habitica/res/xml/searchable.xml b/Habitica/res/xml/searchable.xml
new file mode 100644
index 000000000..443afb501
--- /dev/null
+++ b/Habitica/res/xml/searchable.xml
@@ -0,0 +1,4 @@
+
+
\ No newline at end of file
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/helpers/TaskFilterHelper.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/helpers/TaskFilterHelper.kt
index 4ac4dee54..288f4e78f 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/helpers/TaskFilterHelper.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/helpers/TaskFilterHelper.kt
@@ -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 = ArrayList()
private val activeFilters = HashMap()
@@ -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) {
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/models/tasks/Task.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/models/tasks/Task.kt
index d815e0729..01c21fd66 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/models/tasks/Task.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/models/tasks/Task.kt
@@ -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)
}
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/tasks/TasksFragment.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/tasks/TasksFragment.kt
index 094bb663c..b4914acdc 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/tasks/TasksFragment.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/tasks/TasksFragment.kt
@@ -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()
}
})
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/helpers/SafeDefaultItemAnimator.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/helpers/SafeDefaultItemAnimator.kt
index 2477698e1..34715012f 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/helpers/SafeDefaultItemAnimator.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/helpers/SafeDefaultItemAnimator.kt
@@ -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
}
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewmodels/InboxViewModel.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewmodels/InboxViewModel.kt
index 327cccb93..ba16da99d 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewmodels/InboxViewModel.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewmodels/InboxViewModel.kt
@@ -63,9 +63,11 @@ private class MessagesDataSource(val socialRepository: SocialRepository, val rec
override fun loadInitial(params: LoadInitialParams, callback: LoadInitialCallback) {
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
diff --git a/shared/src/commonMain/kotlin/com/habitrpg/shared/habitica/Logger.kt b/shared/src/commonMain/kotlin/com/habitrpg/shared/habitica/HLogger.kt
similarity index 98%
rename from shared/src/commonMain/kotlin/com/habitrpg/shared/habitica/Logger.kt
rename to shared/src/commonMain/kotlin/com/habitrpg/shared/habitica/HLogger.kt
index 912824958..1026cc353 100644
--- a/shared/src/commonMain/kotlin/com/habitrpg/shared/habitica/Logger.kt
+++ b/shared/src/commonMain/kotlin/com/habitrpg/shared/habitica/HLogger.kt
@@ -13,7 +13,7 @@ enum class LogLevel {
ERROR, INFO, DEBUG
}
-class Logger {
+class HLogger {
companion object {
private val platformLogger = PlatformLogger()