Skip to content

Commit 19b5166

Browse files
committed
add search to equipment
1 parent 2095542 commit 19b5166

File tree

5 files changed

+95
-6
lines changed

5 files changed

+95
-6
lines changed

Habitica/res/menu/menu_searchable.xml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<menu xmlns:android="http://schemas.android.com/apk/res/android"
3+
xmlns:app="http://schemas.android.com/apk/res-auto"
4+
android:layout_width="match_parent"
5+
android:layout_height="match_parent"
6+
android:orientation="vertical">
7+
<item
8+
android:id="@+id/action_search"
9+
android:icon="@android:drawable/ic_menu_search"
10+
android:title="@string/search"
11+
app:actionViewClass="androidx.appcompat.widget.SearchView"
12+
app:showAsAction="always" />
13+
</menu>

Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/BaseMainFragment.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ abstract class BaseMainFragment<VB : ViewBinding> : BaseFragment<VB>() {
8888
mainActivity?.supportActionBar?.setDisplayHomeAsUpEnabled(true)
8989
}
9090

91+
@Deprecated("Use onCreateOptionsMenu(Menu, MenuInflater) instead")
9192
override fun onCreateOptionsMenu(
9293
menu: Menu,
9394
inflater: MenuInflater,

Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/NavigationDrawerFragment.kt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -205,11 +205,11 @@ class NavigationDrawerFragment : DialogFragment() {
205205
"spring" -> R.string.spring
206206
"summer" -> R.string.summer
207207
"fall" -> R.string.fall
208-
"nye" -> R.string.nye
208+
"nye" -> R.string.winter
209209
"birthday" -> R.string.winter
210-
"valentines" -> R.string.valentines
211-
"habitoween" -> R.string.habitoween
212-
"thanksgiving" -> R.string.turkey_day
210+
"valentines" -> R.string.winter
211+
"habitoween" -> R.string.fall
212+
"thanksgiving" -> R.string.fall
213213
else -> R.string.open
214214
}
215215
seasonalItem.pillText = requireContext().getString(seasonID)

Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/inventory/equipment/EquipmentDetailFragment.kt

Lines changed: 76 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,19 @@
11
package com.habitrpg.android.habitica.ui.fragments.inventory.equipment
22

3+
import android.app.SearchManager
4+
import android.database.MatrixCursor
35
import android.os.Bundle
6+
import android.provider.BaseColumns
47
import android.view.LayoutInflater
8+
import android.view.Menu
9+
import android.view.MenuInflater
10+
import android.view.MenuItem
511
import android.view.View
612
import android.view.ViewGroup
13+
import android.widget.AutoCompleteTextView
14+
import androidx.appcompat.widget.SearchView
15+
import androidx.core.view.MenuProvider
16+
import androidx.cursoradapter.widget.SimpleCursorAdapter
717
import androidx.lifecycle.lifecycleScope
818
import androidx.recyclerview.widget.DividerItemDecoration
919
import androidx.recyclerview.widget.LinearLayoutManager
@@ -22,14 +32,17 @@ import com.habitrpg.common.habitica.helpers.ExceptionHandler
2232
import com.habitrpg.common.habitica.helpers.MainNavigationController
2333
import com.habitrpg.common.habitica.helpers.launchCatching
2434
import dagger.hilt.android.AndroidEntryPoint
35+
import kotlinx.coroutines.flow.MutableStateFlow
36+
import kotlinx.coroutines.flow.combine
2537
import kotlinx.coroutines.flow.map
2638
import kotlinx.coroutines.launch
2739
import javax.inject.Inject
2840

41+
2942
@AndroidEntryPoint
3043
class EquipmentDetailFragment :
3144
BaseMainFragment<FragmentRefreshRecyclerviewBinding>(),
32-
SwipeRefreshLayout.OnRefreshListener {
45+
SwipeRefreshLayout.OnRefreshListener, MenuProvider {
3346
@Inject
3447
lateinit var inventoryRepository: InventoryRepository
3548

@@ -52,6 +65,8 @@ class EquipmentDetailFragment :
5265
var equippedGear: String? = null
5366
var isCostume: Boolean? = null
5467

68+
private var searchedText = MutableStateFlow<String?>(null)
69+
5570
private var adapter: EquipmentRecyclerViewAdapter = EquipmentRecyclerViewAdapter()
5671

5772
override fun onCreateView(
@@ -74,6 +89,7 @@ class EquipmentDetailFragment :
7489
}
7590
}
7691
}
92+
activity?.addMenuProvider(this, viewLifecycleOwner)
7793
return super.onCreateView(inflater, container, savedInstanceState)
7894
}
7995

@@ -118,6 +134,12 @@ class EquipmentDetailFragment :
118134
type?.let { type ->
119135
lifecycleScope.launchCatching {
120136
inventoryRepository.getOwnedEquipment(type)
137+
.combine(searchedText) { equipment, query ->
138+
if (query.isNullOrBlank()) {
139+
return@combine equipment
140+
}
141+
equipment.filter { it.text.contains(query, true) || it.notes.contains(query, true) }
142+
}
121143
.map { it.sortedBy { equipment -> equipment.text } }
122144
.collect { adapter.data = it }
123145
}
@@ -135,4 +157,57 @@ class EquipmentDetailFragment :
135157
binding?.refreshLayout?.isRefreshing = false
136158
}
137159
}
160+
161+
override fun onCreateMenu(menu: Menu, menuInflater: MenuInflater) {
162+
menuInflater.inflate(R.menu.menu_searchable, menu)
163+
164+
val searchItem = menu.findItem(R.id.action_search)
165+
val searchView = searchItem.actionView as SearchView
166+
val suggestions = arrayOf("Spring Gear", "Summer Gear", "Fall Gear", "Winter Gear")
167+
val from = arrayOf(SearchManager.SUGGEST_COLUMN_TEXT_1)
168+
val to = intArrayOf(android.R.id.text1)
169+
val suggestionAdapter = SimpleCursorAdapter(requireContext(), R.layout.support_simple_spinner_dropdown_item, null, from, to, 0)
170+
val cursor = MatrixCursor(arrayOf(BaseColumns._ID, SearchManager.SUGGEST_COLUMN_TEXT_1))
171+
for ((index, suggestion) in suggestions.withIndex()) {
172+
cursor.addRow(arrayOf(index, suggestion))
173+
}
174+
suggestionAdapter.changeCursor(cursor)
175+
searchView.suggestionsAdapter = suggestionAdapter
176+
searchView.findViewById<AutoCompleteTextView>(R.id.search_src_text).threshold = 0
177+
178+
searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
179+
override fun onQueryTextSubmit(query: String): Boolean {
180+
searchedText.value = query
181+
return false
182+
}
183+
184+
override fun onQueryTextChange(newText: String): Boolean {
185+
searchedText.value = newText
186+
val filteredCursor = MatrixCursor(arrayOf(BaseColumns._ID, SearchManager.SUGGEST_COLUMN_TEXT_1))
187+
for ((index, suggestion) in suggestions.withIndex()) {
188+
if (suggestion.contains(newText, true)) {
189+
filteredCursor.addRow(arrayOf(index, suggestion))
190+
}
191+
}
192+
suggestionAdapter.changeCursor(filteredCursor)
193+
return false
194+
}
195+
})
196+
197+
searchView.setOnSuggestionListener(object : SearchView.OnSuggestionListener {
198+
override fun onSuggestionSelect(position: Int): Boolean {
199+
val text = suggestionAdapter.getItem(position)
200+
searchedText.value = text.toString()
201+
return false
202+
}
203+
204+
override fun onSuggestionClick(position: Int): Boolean {
205+
return false
206+
}
207+
})
208+
}
209+
210+
override fun onMenuItemSelected(menuItem: MenuItem): Boolean {
211+
TODO("Not yet implemented")
212+
}
138213
}

version.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
NAME=4.5.0
2-
CODE=9011
2+
CODE=9231

0 commit comments

Comments
 (0)