1
1
package com.habitrpg.android.habitica.ui.fragments.inventory.equipment
2
2
3
+ import android.app.SearchManager
4
+ import android.database.MatrixCursor
3
5
import android.os.Bundle
6
+ import android.provider.BaseColumns
4
7
import android.view.LayoutInflater
8
+ import android.view.Menu
9
+ import android.view.MenuInflater
10
+ import android.view.MenuItem
5
11
import android.view.View
6
12
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
7
17
import androidx.lifecycle.lifecycleScope
8
18
import androidx.recyclerview.widget.DividerItemDecoration
9
19
import androidx.recyclerview.widget.LinearLayoutManager
@@ -22,14 +32,17 @@ import com.habitrpg.common.habitica.helpers.ExceptionHandler
22
32
import com.habitrpg.common.habitica.helpers.MainNavigationController
23
33
import com.habitrpg.common.habitica.helpers.launchCatching
24
34
import dagger.hilt.android.AndroidEntryPoint
35
+ import kotlinx.coroutines.flow.MutableStateFlow
36
+ import kotlinx.coroutines.flow.combine
25
37
import kotlinx.coroutines.flow.map
26
38
import kotlinx.coroutines.launch
27
39
import javax.inject.Inject
28
40
41
+
29
42
@AndroidEntryPoint
30
43
class EquipmentDetailFragment :
31
44
BaseMainFragment <FragmentRefreshRecyclerviewBinding >(),
32
- SwipeRefreshLayout .OnRefreshListener {
45
+ SwipeRefreshLayout .OnRefreshListener , MenuProvider {
33
46
@Inject
34
47
lateinit var inventoryRepository: InventoryRepository
35
48
@@ -52,6 +65,8 @@ class EquipmentDetailFragment :
52
65
var equippedGear: String? = null
53
66
var isCostume: Boolean? = null
54
67
68
+ private var searchedText = MutableStateFlow <String ?>(null )
69
+
55
70
private var adapter: EquipmentRecyclerViewAdapter = EquipmentRecyclerViewAdapter ()
56
71
57
72
override fun onCreateView (
@@ -74,6 +89,7 @@ class EquipmentDetailFragment :
74
89
}
75
90
}
76
91
}
92
+ activity?.addMenuProvider(this , viewLifecycleOwner)
77
93
return super .onCreateView(inflater, container, savedInstanceState)
78
94
}
79
95
@@ -118,6 +134,12 @@ class EquipmentDetailFragment :
118
134
type?.let { type ->
119
135
lifecycleScope.launchCatching {
120
136
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
+ }
121
143
.map { it.sortedBy { equipment -> equipment.text } }
122
144
.collect { adapter.data = it }
123
145
}
@@ -135,4 +157,57 @@ class EquipmentDetailFragment :
135
157
binding?.refreshLayout?.isRefreshing = false
136
158
}
137
159
}
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
+ }
138
213
}
0 commit comments