2022-08-11 12:25:54 +02:00

198 lines
7.8 KiB
Kotlin

package com.github.libretube.adapters
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.FragmentManager
import androidx.recyclerview.widget.RecyclerView
import com.github.libretube.R
import com.github.libretube.databinding.ChannelRowBinding
import com.github.libretube.databinding.PlaylistSearchRowBinding
import com.github.libretube.databinding.VideoRowBinding
import com.github.libretube.dialogs.PlaylistOptionsDialog
import com.github.libretube.dialogs.VideoOptionsDialog
import com.github.libretube.extensions.setFormattedDuration
import com.github.libretube.obj.SearchItem
import com.github.libretube.util.ConnectionHelper
import com.github.libretube.util.NavigationHelper
import com.github.libretube.util.SubscriptionHelper
import com.github.libretube.util.formatShort
import com.github.libretube.util.setWatchProgressLength
import com.github.libretube.util.toID
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
class SearchAdapter(
private val searchItems: MutableList<SearchItem>,
private val childFragmentManager: FragmentManager
) :
RecyclerView.Adapter<SearchViewHolder>() {
fun updateItems(newItems: List<SearchItem>) {
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 {
val layoutInflater = LayoutInflater.from(parent.context)
return when (viewType) {
0 -> SearchViewHolder(
VideoRowBinding.inflate(layoutInflater, parent, false)
)
1 -> SearchViewHolder(
ChannelRowBinding.inflate(layoutInflater, parent, false)
)
2 -> SearchViewHolder(
PlaylistSearchRowBinding.inflate(layoutInflater, parent, false)
)
else -> throw IllegalArgumentException("Invalid type")
}
}
override fun onBindViewHolder(holder: SearchViewHolder, position: Int) {
val searchItem = searchItems[position]
val videoRowBinding = holder.videoRowBinding
val channelRowBinding = holder.channelRowBinding
val playlistRowBinding = holder.playlistRowBinding
if (videoRowBinding != null) bindWatch(searchItem, videoRowBinding)
else if (channelRowBinding != null) bindChannel(searchItem, channelRowBinding)
else if (playlistRowBinding != null) bindPlaylist(searchItem, playlistRowBinding)
}
override fun getItemViewType(position: Int): Int {
return when {
searchItems[position].url!!.startsWith("/watch", false) -> 0
searchItems[position].url!!.startsWith("/channel", false) -> 1
searchItems[position].url!!.startsWith("/playlist", false) -> 2
else -> 3
}
}
private fun bindWatch(item: SearchItem, binding: VideoRowBinding) {
binding.apply {
ConnectionHelper.loadImage(item.thumbnail, thumbnail)
thumbnailDuration.setFormattedDuration(item.duration!!)
ConnectionHelper.loadImage(item.uploaderAvatar, channelImage)
videoTitle.text = item.title
val viewsString = if (item.views?.toInt() != -1) item.views.formatShort() else ""
val uploadDate = if (item.uploadedDate != null) item.uploadedDate else ""
videoInfo.text =
if (viewsString != "" && uploadDate != "") {
"$viewsString$uploadDate"
} else {
viewsString + uploadDate
}
channelName.text = item.uploaderName
root.setOnClickListener {
NavigationHelper.navigateVideo(root.context, item.url)
}
val videoId = item.url.toID()
root.setOnLongClickListener {
VideoOptionsDialog(videoId)
.show(childFragmentManager, VideoOptionsDialog::class.java.name)
true
}
channelImage.setOnClickListener {
NavigationHelper.navigateChannel(root.context, item.uploaderUrl)
}
watchProgress.setWatchProgressLength(videoId, item.duration!!)
}
}
private fun bindChannel(item: SearchItem, binding: ChannelRowBinding) {
binding.apply {
ConnectionHelper.loadImage(item.thumbnail, searchChannelImage)
searchChannelName.text = item.name
searchViews.text = root.context.getString(
R.string.subscribers,
item.subscribers.formatShort()
) + "" + root.context.getString(R.string.videoCount, item.videos.toString())
root.setOnClickListener {
NavigationHelper.navigateChannel(root.context, item.url)
}
val channelId = item.url.toID()
isSubscribed(channelId, binding)
}
}
private fun isSubscribed(channelId: String, binding: ChannelRowBinding) {
// check whether the user subscribed to the channel
CoroutineScope(Dispatchers.Main).launch {
var isSubscribed = SubscriptionHelper.isSubscribed(channelId)
// if subscribed change text to unsubscribe
if (isSubscribed == true) {
binding.searchSubButton.text = binding.root.context.getString(R.string.unsubscribe)
}
// make sub button visible and set the on click listeners to (un)subscribe
if (isSubscribed == null) return@launch
binding.searchSubButton.visibility = View.VISIBLE
binding.searchSubButton.setOnClickListener {
if (isSubscribed == false) {
SubscriptionHelper.subscribe(channelId)
binding.searchSubButton.text =
binding.root.context.getString(R.string.unsubscribe)
isSubscribed = true
} else {
SubscriptionHelper.unsubscribe(channelId)
binding.searchSubButton.text =
binding.root.context.getString(R.string.subscribe)
isSubscribed = false
}
}
}
}
private fun bindPlaylist(item: SearchItem, binding: PlaylistSearchRowBinding) {
binding.apply {
ConnectionHelper.loadImage(item.thumbnail, searchThumbnail)
if (item.videos?.toInt() != -1) searchPlaylistNumber.text = item.videos.toString()
searchDescription.text = item.name
searchName.text = item.uploaderName
if (item.videos?.toInt() != -1) {
searchPlaylistVideos.text =
root.context.getString(R.string.videoCount, item.videos.toString())
}
root.setOnClickListener {
NavigationHelper.navigatePlaylist(root.context, item.url, false)
}
root.setOnLongClickListener {
val playlistId = item.url!!.toID()
PlaylistOptionsDialog(playlistId, false)
.show(childFragmentManager, PlaylistOptionsDialog::class.java.name)
true
}
}
}
}
class SearchViewHolder : RecyclerView.ViewHolder {
var videoRowBinding: VideoRowBinding? = null
var channelRowBinding: ChannelRowBinding? = null
var playlistRowBinding: PlaylistSearchRowBinding? = null
constructor(binding: VideoRowBinding) : super(binding.root) {
videoRowBinding = binding
}
constructor(binding: ChannelRowBinding) : super(binding.root) {
channelRowBinding = binding
}
constructor(binding: PlaylistSearchRowBinding) : super(binding.root) {
playlistRowBinding = binding
}
}