NextPage for Search

This commit is contained in:
Bnyro 2022-05-15 13:12:46 +02:00
parent 9b170c8be2
commit 4ed137c174
4 changed files with 61 additions and 21 deletions

View File

@ -22,6 +22,13 @@ interface PipedApi {
@Query("filter") filter: String @Query("filter") filter: String
): SearchResult ): SearchResult
@GET("nextpage/search")
suspend fun getSearchResultsNextPage(
@Query("q") searchQuery: String,
@Query("filter") filter: String,
@Query("nextpage") nextPage: String
): SearchResult
@GET("suggestions") @GET("suggestions")
suspend fun getSuggestions(@Query("query") query: String): List<String> suspend fun getSuggestions(@Query("query") query: String): List<String>

View File

@ -12,11 +12,10 @@ import android.view.ViewGroup
import android.view.WindowManager import android.view.WindowManager
import android.view.inputmethod.EditorInfo import android.view.inputmethod.EditorInfo
import android.view.inputmethod.InputMethodManager import android.view.inputmethod.InputMethodManager
import android.widget.ArrayAdapter import android.widget.*
import android.widget.AutoCompleteTextView
import android.widget.ImageView
import android.widget.TextView.* import android.widget.TextView.*
import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AlertDialog
import androidx.core.content.ContentProviderCompat.requireContext
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import androidx.preference.PreferenceManager import androidx.preference.PreferenceManager
@ -31,11 +30,13 @@ import kotlinx.coroutines.launch
import retrofit2.HttpException import retrofit2.HttpException
import java.io.IOException import java.io.IOException
private var selectedFilter = 0
class SearchFragment : Fragment() { class SearchFragment : Fragment() {
private val TAG = "SearchFragment" private val TAG = "SearchFragment"
private var selectedFilter = 0
private var nextPage : String? = null
private lateinit var searchRecView : RecyclerView
private var searchAdapter : SearchAdapter? = null
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
arguments?.let { arguments?.let {
@ -54,7 +55,7 @@ class SearchFragment : Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
val recyclerView = view.findViewById<RecyclerView>(R.id.search_recycler) searchRecView = view.findViewById<RecyclerView>(R.id.search_recycler)
val autoTextView = view.findViewById<AutoCompleteTextView>(R.id.autoCompleteTextView) val autoTextView = view.findViewById<AutoCompleteTextView>(R.id.autoCompleteTextView)
@ -73,7 +74,7 @@ class SearchFragment : Fragment() {
}) })
.setPositiveButton(getString(R.string.okay), DialogInterface.OnClickListener { .setPositiveButton(getString(R.string.okay), DialogInterface.OnClickListener {
_, _ -> selectedFilter = tempSelectedItem _, _ -> selectedFilter = tempSelectedItem
fetchSearch(autoTextView.text.toString(), recyclerView) fetchSearch(autoTextView.text.toString())
}) })
.setNegativeButton(getString(R.string.cancel), null) .setNegativeButton(getString(R.string.cancel), null)
.create() .create()
@ -82,7 +83,7 @@ class SearchFragment : Fragment() {
//show search history //show search history
recyclerView.visibility = GONE searchRecView.visibility = GONE
historyRecycler.visibility = VISIBLE historyRecycler.visibility = VISIBLE
historyRecycler.layoutManager = LinearLayoutManager(view.context) historyRecycler.layoutManager = LinearLayoutManager(view.context)
@ -93,7 +94,7 @@ class SearchFragment : Fragment() {
SearchHistoryAdapter(requireContext(), historylist, autoTextView) SearchHistoryAdapter(requireContext(), historylist, autoTextView)
} }
recyclerView.layoutManager = GridLayoutManager(view.context, 1) searchRecView.layoutManager = GridLayoutManager(view.context, 1)
autoTextView.requestFocus() autoTextView.requestFocus()
val imm = val imm =
requireContext().getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager requireContext().getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
@ -110,24 +111,30 @@ class SearchFragment : Fragment() {
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) { override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
if (s!! != "") { if (s!! != "") {
recyclerView.visibility = VISIBLE searchRecView.visibility = VISIBLE
historyRecycler.visibility = GONE historyRecycler.visibility = GONE
recyclerView.adapter = null searchRecView.adapter = null
searchRecView.viewTreeObserver
.addOnScrollChangedListener {
if (!searchRecView.canScrollVertically(1)) {
fetchNextSearchItems(autoTextView.text.toString())
}
}
GlobalScope.launch { GlobalScope.launch {
fetchSuggestions(s.toString(), autoTextView) fetchSuggestions(s.toString(), autoTextView)
delay(1000) delay(1000)
addtohistory(s.toString()) addtohistory(s.toString())
fetchSearch(s.toString(), recyclerView) fetchSearch(s.toString())
} }
} }
} }
override fun afterTextChanged(s: Editable?) { override fun afterTextChanged(s: Editable?) {
if (s!!.isEmpty()) { if (s!!.isEmpty()) {
recyclerView.visibility = GONE searchRecView.visibility = GONE
historyRecycler.visibility = VISIBLE historyRecycler.visibility = VISIBLE
var historylist = getHistory() var historylist = getHistory()
if (historylist.size != 0) { if (historylist.size != 0) {
@ -167,10 +174,10 @@ class SearchFragment : Fragment() {
autoTextView.setAdapter(adapter) autoTextView.setAdapter(adapter)
} }
} }
private fun fetchSearch(query: String, recyclerView: RecyclerView){ private fun fetchSearch(query: String){
lifecycleScope.launchWhenCreated { lifecycleScope.launchWhenCreated {
val response = try { val response = try {
RetrofitInstance.api.getSearchResults(query, "all") RetrofitInstance.api.getSearchResults(query, "videos")
} catch (e: IOException) { } catch (e: IOException) {
println(e) println(e)
Log.e(TAG, "IOException, you might not have internet connection $e") Log.e(TAG, "IOException, you might not have internet connection $e")
@ -179,15 +186,34 @@ class SearchFragment : Fragment() {
Log.e(TAG, "HttpException, unexpected response") Log.e(TAG, "HttpException, unexpected response")
return@launchWhenCreated return@launchWhenCreated
} }
nextPage = response.nextpage
if(response.items!!.isNotEmpty()){ if(response.items!!.isNotEmpty()){
runOnUiThread { runOnUiThread {
recyclerView.adapter = SearchAdapter(response.items, selectedFilter) searchAdapter = SearchAdapter(response.items, selectedFilter)
searchRecView.adapter = searchAdapter
} }
} }
} }
} }
private fun fetchNextSearchItems(query: String){
lifecycleScope.launchWhenCreated {
val response = try {
RetrofitInstance.api.getSearchResultsNextPage(query!!, "videos", nextPage!!)
} catch (e: IOException) {
println(e)
Log.e(TAG, "IOException, you might not have internet connection")
return@launchWhenCreated
} catch (e: HttpException) {
Log.e(TAG, "HttpException, unexpected response," + e.response())
return@launchWhenCreated
}
nextPage = response.nextpage
searchAdapter?.updateItems(response.items!!)
}
}
private fun Fragment?.runOnUiThread(action: () -> Unit) { private fun Fragment?.runOnUiThread(action: () -> Unit) {
this ?: return this ?: return
if (!isAdded) return // Fragment not attached to an Activity if (!isAdded) return // Fragment not attached to an Activity

View File

@ -14,6 +14,7 @@ import com.github.libretube.MainActivity
import com.github.libretube.PlayerFragment import com.github.libretube.PlayerFragment
import com.github.libretube.R import com.github.libretube.R
import com.github.libretube.formatShort import com.github.libretube.formatShort
import com.github.libretube.obj.Comment
import com.github.libretube.obj.SearchItem import com.github.libretube.obj.SearchItem
import com.squareup.picasso.Picasso import com.squareup.picasso.Picasso
import kotlinx.coroutines.NonDisposableHandle.parent import kotlinx.coroutines.NonDisposableHandle.parent
@ -22,7 +23,13 @@ private var showVideos = true
private var showChannels = true private var showChannels = true
private var showPlaylists = true private var showPlaylists = true
class SearchAdapter(private val searchItems: List<SearchItem>, private val selectedFilter : Int): RecyclerView.Adapter<CustomViewHolder1>() { class SearchAdapter(private val searchItems: MutableList<SearchItem>, private val selectedFilter : Int): RecyclerView.Adapter<CustomViewHolder1>() {
fun updateItems(newItems: List<SearchItem>){
var searchItemsSize = searchItems.size
searchItems.addAll(newItems)
notifyItemRangeInserted(searchItemsSize, newItems.size)
}
override fun getItemCount(): Int { override fun getItemCount(): Int {
return searchItems.size return searchItems.size

View File

@ -4,7 +4,7 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
data class SearchResult( data class SearchResult(
val items: List<SearchItem>? = listOf(), val items: MutableList<SearchItem>? = arrayListOf(),
val nextpage: String? ="", val nextpage: String? ="",
val suggestion: String?="", val suggestion: String?="",
val corrected: Boolean? = null val corrected: Boolean? = null