mirror of
https://github.com/libre-tube/LibreTube.git
synced 2025-01-06 17:40:30 +05:30
Convert SearchAdapter to a ListAdapter.
This commit is contained in:
parent
c05734d0fe
commit
3b6ccdb91d
@ -4,7 +4,8 @@ import android.annotation.SuppressLint
|
|||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.DiffUtil
|
||||||
|
import androidx.recyclerview.widget.ListAdapter
|
||||||
import com.github.libretube.R
|
import com.github.libretube.R
|
||||||
import com.github.libretube.api.obj.ContentItem
|
import com.github.libretube.api.obj.ContentItem
|
||||||
import com.github.libretube.databinding.ChannelRowBinding
|
import com.github.libretube.databinding.ChannelRowBinding
|
||||||
@ -25,21 +26,7 @@ import com.github.libretube.ui.sheets.VideoOptionsBottomSheet
|
|||||||
import com.github.libretube.ui.viewholders.SearchViewHolder
|
import com.github.libretube.ui.viewholders.SearchViewHolder
|
||||||
import com.github.libretube.util.TextUtils
|
import com.github.libretube.util.TextUtils
|
||||||
|
|
||||||
class SearchAdapter(
|
class SearchAdapter : ListAdapter<ContentItem, SearchViewHolder>(SearchCallback) {
|
||||||
private val searchItems: MutableList<ContentItem>
|
|
||||||
) :
|
|
||||||
RecyclerView.Adapter<SearchViewHolder>() {
|
|
||||||
|
|
||||||
fun updateItems(newItems: List<ContentItem>) {
|
|
||||||
val searchItemsSize = searchItems.size
|
|
||||||
searchItems.addAll(newItems)
|
|
||||||
notifyItemRangeInserted(searchItemsSize, newItems.size)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getItemCount(): Int {
|
|
||||||
return searchItems.size
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SearchViewHolder {
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SearchViewHolder {
|
||||||
val layoutInflater = LayoutInflater.from(parent.context)
|
val layoutInflater = LayoutInflater.from(parent.context)
|
||||||
|
|
||||||
@ -58,7 +45,7 @@ class SearchAdapter(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onBindViewHolder(holder: SearchViewHolder, position: Int) {
|
override fun onBindViewHolder(holder: SearchViewHolder, position: Int) {
|
||||||
val searchItem = searchItems[position]
|
val searchItem = currentList[position]
|
||||||
|
|
||||||
val videoRowBinding = holder.videoRowBinding
|
val videoRowBinding = holder.videoRowBinding
|
||||||
val channelRowBinding = holder.channelRowBinding
|
val channelRowBinding = holder.channelRowBinding
|
||||||
@ -68,11 +55,13 @@ class SearchAdapter(
|
|||||||
bindWatch(searchItem, videoRowBinding)
|
bindWatch(searchItem, videoRowBinding)
|
||||||
} else if (channelRowBinding != null) {
|
} else if (channelRowBinding != null) {
|
||||||
bindChannel(searchItem, channelRowBinding)
|
bindChannel(searchItem, channelRowBinding)
|
||||||
} else if (playlistRowBinding != null) bindPlaylist(searchItem, playlistRowBinding)
|
} else if (playlistRowBinding != null) {
|
||||||
|
bindPlaylist(searchItem, playlistRowBinding)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getItemViewType(position: Int): Int {
|
override fun getItemViewType(position: Int): Int {
|
||||||
return when (searchItems[position].type) {
|
return when (currentList[position].type) {
|
||||||
"stream" -> 0
|
"stream" -> 0
|
||||||
"channel" -> 1
|
"channel" -> 1
|
||||||
"playlist" -> 2
|
"playlist" -> 2
|
||||||
@ -116,10 +105,7 @@ class SearchAdapter(
|
|||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("SetTextI18n")
|
@SuppressLint("SetTextI18n")
|
||||||
private fun bindChannel(
|
private fun bindChannel(item: ContentItem, binding: ChannelRowBinding) {
|
||||||
item: ContentItem,
|
|
||||||
binding: ChannelRowBinding
|
|
||||||
) {
|
|
||||||
binding.apply {
|
binding.apply {
|
||||||
ImageHelper.loadImage(item.thumbnail, searchChannelImage)
|
ImageHelper.loadImage(item.thumbnail, searchChannelImage)
|
||||||
searchChannelName.text = item.name
|
searchChannelName.text = item.name
|
||||||
@ -144,10 +130,7 @@ class SearchAdapter(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun bindPlaylist(
|
private fun bindPlaylist(item: ContentItem, binding: PlaylistsRowBinding) {
|
||||||
item: ContentItem,
|
|
||||||
binding: PlaylistsRowBinding
|
|
||||||
) {
|
|
||||||
binding.apply {
|
binding.apply {
|
||||||
ImageHelper.loadImage(item.thumbnail, playlistThumbnail)
|
ImageHelper.loadImage(item.thumbnail, playlistThumbnail)
|
||||||
if (item.videos != -1L) videoCount.text = item.videos.toString()
|
if (item.videos != -1L) videoCount.text = item.videos.toString()
|
||||||
@ -169,4 +152,14 @@ class SearchAdapter(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private object SearchCallback : DiffUtil.ItemCallback<ContentItem>() {
|
||||||
|
override fun areItemsTheSame(oldItem: ContentItem, newItem: ContentItem): Boolean {
|
||||||
|
return oldItem.url == newItem.url
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun areContentsTheSame(oldItem: ContentItem, newItem: ContentItem): Boolean {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,9 +28,9 @@ import com.github.libretube.ui.base.BaseFragment
|
|||||||
import com.github.libretube.ui.dialogs.ShareDialog
|
import com.github.libretube.ui.dialogs.ShareDialog
|
||||||
import com.github.libretube.ui.extensions.setupSubscriptionButton
|
import com.github.libretube.ui.extensions.setupSubscriptionButton
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import kotlinx.coroutines.CoroutineScope
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
import retrofit2.HttpException
|
import retrofit2.HttpException
|
||||||
|
|
||||||
class ChannelFragment : BaseFragment() {
|
class ChannelFragment : BaseFragment() {
|
||||||
@ -45,8 +45,6 @@ class ChannelFragment : BaseFragment() {
|
|||||||
|
|
||||||
private var onScrollEnd: () -> Unit = {}
|
private var onScrollEnd: () -> Unit = {}
|
||||||
|
|
||||||
private val scope = CoroutineScope(Dispatchers.IO)
|
|
||||||
|
|
||||||
val possibleTabs = listOf(
|
val possibleTabs = listOf(
|
||||||
ChannelTabs.Channels,
|
ChannelTabs.Channels,
|
||||||
ChannelTabs.Playlists,
|
ChannelTabs.Playlists,
|
||||||
@ -227,18 +225,18 @@ class ChannelFragment : BaseFragment() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun loadTab(tab: ChannelTab) {
|
private fun loadTab(tab: ChannelTab) {
|
||||||
scope.launch {
|
lifecycleScope.launch {
|
||||||
val response = try {
|
val response = try {
|
||||||
RetrofitInstance.api.getChannelTab(tab.data)
|
withContext(Dispatchers.IO) {
|
||||||
|
RetrofitInstance.api.getChannelTab(tab.data)
|
||||||
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
return@launch
|
return@launch
|
||||||
}
|
}
|
||||||
|
|
||||||
val adapter = SearchAdapter(response.content.toMutableList())
|
val adapter = SearchAdapter()
|
||||||
|
binding.channelRecView.adapter = adapter
|
||||||
runOnUiThread {
|
adapter.submitList(response.content)
|
||||||
binding.channelRecView.adapter = adapter
|
|
||||||
}
|
|
||||||
|
|
||||||
var tabNextPage = response.nextpage
|
var tabNextPage = response.nextpage
|
||||||
onScrollEnd = {
|
onScrollEnd = {
|
||||||
@ -284,18 +282,18 @@ class ChannelFragment : BaseFragment() {
|
|||||||
adapter: SearchAdapter,
|
adapter: SearchAdapter,
|
||||||
onNewNextPage: (String?) -> Unit
|
onNewNextPage: (String?) -> Unit
|
||||||
) {
|
) {
|
||||||
scope.launch {
|
lifecycleScope.launch {
|
||||||
val newContent = try {
|
val newContent = try {
|
||||||
RetrofitInstance.api.getChannelTab(tab.data, nextPage)
|
withContext(Dispatchers.IO) {
|
||||||
|
RetrofitInstance.api.getChannelTab(tab.data, nextPage)
|
||||||
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Log.e(TAG(), "Exception: $e")
|
Log.e(TAG(), "Exception: $e")
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
onNewNextPage.invoke(newContent?.nextpage)
|
onNewNextPage(newContent?.nextpage)
|
||||||
runOnUiThread {
|
newContent?.content?.let {
|
||||||
newContent?.content?.let {
|
adapter.submitList(adapter.currentList + it)
|
||||||
adapter.updateItems(it)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,8 @@ import com.github.libretube.extensions.hideKeyboard
|
|||||||
import com.github.libretube.helpers.PreferenceHelper
|
import com.github.libretube.helpers.PreferenceHelper
|
||||||
import com.github.libretube.ui.adapters.SearchAdapter
|
import com.github.libretube.ui.adapters.SearchAdapter
|
||||||
import com.github.libretube.ui.base.BaseFragment
|
import com.github.libretube.ui.base.BaseFragment
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import retrofit2.HttpException
|
import retrofit2.HttpException
|
||||||
|
|
||||||
@ -85,7 +87,9 @@ class SearchResultFragment : BaseFragment() {
|
|||||||
lifecycleScope.launchWhenCreated {
|
lifecycleScope.launchWhenCreated {
|
||||||
view?.let { context?.hideKeyboard(it) }
|
view?.let { context?.hideKeyboard(it) }
|
||||||
val response = try {
|
val response = try {
|
||||||
RetrofitInstance.api.getSearchResults(query, apiSearchFilter)
|
withContext(Dispatchers.IO) {
|
||||||
|
RetrofitInstance.api.getSearchResults(query, apiSearchFilter)
|
||||||
|
}
|
||||||
} 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")
|
||||||
@ -94,11 +98,10 @@ class SearchResultFragment : BaseFragment() {
|
|||||||
Log.e(TAG(), "HttpException, unexpected response")
|
Log.e(TAG(), "HttpException, unexpected response")
|
||||||
return@launchWhenCreated
|
return@launchWhenCreated
|
||||||
}
|
}
|
||||||
runOnUiThread {
|
searchAdapter = SearchAdapter()
|
||||||
searchAdapter = SearchAdapter(response.items.toMutableList())
|
binding.searchRecycler.adapter = searchAdapter
|
||||||
binding.searchRecycler.adapter = searchAdapter
|
searchAdapter.submitList(response.items)
|
||||||
binding.noSearchResult.isVisible = response.items.isEmpty()
|
binding.noSearchResult.isVisible = response.items.isEmpty()
|
||||||
}
|
|
||||||
nextPage = response.nextpage
|
nextPage = response.nextpage
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -106,11 +109,13 @@ class SearchResultFragment : BaseFragment() {
|
|||||||
private fun fetchNextSearchItems() {
|
private fun fetchNextSearchItems() {
|
||||||
lifecycleScope.launchWhenCreated {
|
lifecycleScope.launchWhenCreated {
|
||||||
val response = try {
|
val response = try {
|
||||||
RetrofitInstance.api.getSearchResultsNextPage(
|
withContext(Dispatchers.IO) {
|
||||||
query,
|
RetrofitInstance.api.getSearchResultsNextPage(
|
||||||
apiSearchFilter,
|
query,
|
||||||
nextPage!!
|
apiSearchFilter,
|
||||||
)
|
nextPage!!
|
||||||
|
)
|
||||||
|
}
|
||||||
} catch (e: IOException) {
|
} catch (e: IOException) {
|
||||||
println(e)
|
println(e)
|
||||||
Log.e(TAG(), "IOException, you might not have internet connection")
|
Log.e(TAG(), "IOException, you might not have internet connection")
|
||||||
@ -120,10 +125,8 @@ class SearchResultFragment : BaseFragment() {
|
|||||||
return@launchWhenCreated
|
return@launchWhenCreated
|
||||||
}
|
}
|
||||||
nextPage = response.nextpage!!
|
nextPage = response.nextpage!!
|
||||||
kotlin.runCatching {
|
if (response.items.isNotEmpty()) {
|
||||||
if (response.items.isNotEmpty()) {
|
searchAdapter.submitList(searchAdapter.currentList + response.items)
|
||||||
searchAdapter.updateItems(response.items)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user