Convert SearchAdapter to a ListAdapter.

This commit is contained in:
Isira Seneviratne 2023-02-05 06:01:12 +05:30
parent c05734d0fe
commit 3b6ccdb91d
3 changed files with 53 additions and 59 deletions

View File

@ -4,7 +4,8 @@ import android.annotation.SuppressLint
import android.view.LayoutInflater
import android.view.View
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.api.obj.ContentItem
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.util.TextUtils
class SearchAdapter(
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
}
class SearchAdapter : ListAdapter<ContentItem, SearchViewHolder>(SearchCallback) {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SearchViewHolder {
val layoutInflater = LayoutInflater.from(parent.context)
@ -58,7 +45,7 @@ class SearchAdapter(
}
override fun onBindViewHolder(holder: SearchViewHolder, position: Int) {
val searchItem = searchItems[position]
val searchItem = currentList[position]
val videoRowBinding = holder.videoRowBinding
val channelRowBinding = holder.channelRowBinding
@ -68,11 +55,13 @@ class SearchAdapter(
bindWatch(searchItem, videoRowBinding)
} else if (channelRowBinding != null) {
bindChannel(searchItem, channelRowBinding)
} else if (playlistRowBinding != null) bindPlaylist(searchItem, playlistRowBinding)
} else if (playlistRowBinding != null) {
bindPlaylist(searchItem, playlistRowBinding)
}
}
override fun getItemViewType(position: Int): Int {
return when (searchItems[position].type) {
return when (currentList[position].type) {
"stream" -> 0
"channel" -> 1
"playlist" -> 2
@ -116,10 +105,7 @@ class SearchAdapter(
}
@SuppressLint("SetTextI18n")
private fun bindChannel(
item: ContentItem,
binding: ChannelRowBinding
) {
private fun bindChannel(item: ContentItem, binding: ChannelRowBinding) {
binding.apply {
ImageHelper.loadImage(item.thumbnail, searchChannelImage)
searchChannelName.text = item.name
@ -144,10 +130,7 @@ class SearchAdapter(
}
}
private fun bindPlaylist(
item: ContentItem,
binding: PlaylistsRowBinding
) {
private fun bindPlaylist(item: ContentItem, binding: PlaylistsRowBinding) {
binding.apply {
ImageHelper.loadImage(item.thumbnail, playlistThumbnail)
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
}
}
}

View File

@ -28,9 +28,9 @@ import com.github.libretube.ui.base.BaseFragment
import com.github.libretube.ui.dialogs.ShareDialog
import com.github.libretube.ui.extensions.setupSubscriptionButton
import java.io.IOException
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import retrofit2.HttpException
class ChannelFragment : BaseFragment() {
@ -45,8 +45,6 @@ class ChannelFragment : BaseFragment() {
private var onScrollEnd: () -> Unit = {}
private val scope = CoroutineScope(Dispatchers.IO)
val possibleTabs = listOf(
ChannelTabs.Channels,
ChannelTabs.Playlists,
@ -227,18 +225,18 @@ class ChannelFragment : BaseFragment() {
}
private fun loadTab(tab: ChannelTab) {
scope.launch {
lifecycleScope.launch {
val response = try {
RetrofitInstance.api.getChannelTab(tab.data)
withContext(Dispatchers.IO) {
RetrofitInstance.api.getChannelTab(tab.data)
}
} catch (e: Exception) {
return@launch
}
val adapter = SearchAdapter(response.content.toMutableList())
runOnUiThread {
binding.channelRecView.adapter = adapter
}
val adapter = SearchAdapter()
binding.channelRecView.adapter = adapter
adapter.submitList(response.content)
var tabNextPage = response.nextpage
onScrollEnd = {
@ -284,18 +282,18 @@ class ChannelFragment : BaseFragment() {
adapter: SearchAdapter,
onNewNextPage: (String?) -> Unit
) {
scope.launch {
lifecycleScope.launch {
val newContent = try {
RetrofitInstance.api.getChannelTab(tab.data, nextPage)
withContext(Dispatchers.IO) {
RetrofitInstance.api.getChannelTab(tab.data, nextPage)
}
} catch (e: Exception) {
Log.e(TAG(), "Exception: $e")
null
}
onNewNextPage.invoke(newContent?.nextpage)
runOnUiThread {
newContent?.content?.let {
adapter.updateItems(it)
}
onNewNextPage(newContent?.nextpage)
newContent?.content?.let {
adapter.submitList(adapter.currentList + it)
}
}
}

View File

@ -19,6 +19,8 @@ import com.github.libretube.extensions.hideKeyboard
import com.github.libretube.helpers.PreferenceHelper
import com.github.libretube.ui.adapters.SearchAdapter
import com.github.libretube.ui.base.BaseFragment
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import java.io.IOException
import retrofit2.HttpException
@ -85,7 +87,9 @@ class SearchResultFragment : BaseFragment() {
lifecycleScope.launchWhenCreated {
view?.let { context?.hideKeyboard(it) }
val response = try {
RetrofitInstance.api.getSearchResults(query, apiSearchFilter)
withContext(Dispatchers.IO) {
RetrofitInstance.api.getSearchResults(query, apiSearchFilter)
}
} catch (e: IOException) {
println(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")
return@launchWhenCreated
}
runOnUiThread {
searchAdapter = SearchAdapter(response.items.toMutableList())
binding.searchRecycler.adapter = searchAdapter
binding.noSearchResult.isVisible = response.items.isEmpty()
}
searchAdapter = SearchAdapter()
binding.searchRecycler.adapter = searchAdapter
searchAdapter.submitList(response.items)
binding.noSearchResult.isVisible = response.items.isEmpty()
nextPage = response.nextpage
}
}
@ -106,11 +109,13 @@ class SearchResultFragment : BaseFragment() {
private fun fetchNextSearchItems() {
lifecycleScope.launchWhenCreated {
val response = try {
RetrofitInstance.api.getSearchResultsNextPage(
query,
apiSearchFilter,
nextPage!!
)
withContext(Dispatchers.IO) {
RetrofitInstance.api.getSearchResultsNextPage(
query,
apiSearchFilter,
nextPage!!
)
}
} catch (e: IOException) {
println(e)
Log.e(TAG(), "IOException, you might not have internet connection")
@ -120,10 +125,8 @@ class SearchResultFragment : BaseFragment() {
return@launchWhenCreated
}
nextPage = response.nextpage!!
kotlin.runCatching {
if (response.items.isNotEmpty()) {
searchAdapter.updateItems(response.items)
}
if (response.items.isNotEmpty()) {
searchAdapter.submitList(searchAdapter.currentList + response.items)
}
}
}