AquaStream/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeParentItemAdapter.kt

273 lines
11 KiB
Kotlin
Raw Normal View History

2021-07-29 00:19:42 +00:00
package com.lagradost.cloudstream3.ui.home
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
2021-07-29 00:54:27 +00:00
import android.widget.FrameLayout
2022-12-28 11:51:55 +00:00
import android.widget.LinearLayout
2021-07-29 00:19:42 +00:00
import android.widget.TextView
2022-12-28 11:51:55 +00:00
import androidx.core.content.ContextCompat
import androidx.core.view.isGone
import androidx.core.view.isVisible
2022-01-30 22:02:57 +00:00
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListUpdateCallback
2021-07-29 00:19:42 +00:00
import androidx.recyclerview.widget.RecyclerView
2022-12-28 11:51:55 +00:00
import androidx.transition.ChangeBounds
import androidx.transition.TransitionManager
import androidx.viewpager2.widget.ViewPager2
import com.google.android.material.chip.Chip
import com.google.android.material.chip.ChipDrawable
import com.lagradost.cloudstream3.APIHolder.getId
import com.lagradost.cloudstream3.AcraApplication.Companion.getActivity
2021-07-29 00:19:42 +00:00
import com.lagradost.cloudstream3.HomePageList
2022-12-28 11:51:55 +00:00
import com.lagradost.cloudstream3.LoadResponse
2021-07-29 00:19:42 +00:00
import com.lagradost.cloudstream3.R
2022-12-28 11:51:55 +00:00
import com.lagradost.cloudstream3.SearchResponse
import com.lagradost.cloudstream3.mvvm.Resource
import com.lagradost.cloudstream3.ui.WatchType
import com.lagradost.cloudstream3.ui.result.LinearListLayout
2022-12-28 11:51:55 +00:00
import com.lagradost.cloudstream3.ui.result.ResultViewModel2
import com.lagradost.cloudstream3.ui.result.START_ACTION_RESUME_LATEST
import com.lagradost.cloudstream3.ui.result.setLinearListLayout
2022-12-28 11:51:55 +00:00
import com.lagradost.cloudstream3.ui.search.SEARCH_ACTION_LOAD
2021-07-30 23:41:54 +00:00
import com.lagradost.cloudstream3.ui.search.SearchClickCallback
import com.lagradost.cloudstream3.ui.search.SearchFragment.Companion.filterSearchResponse
2022-03-29 21:07:41 +00:00
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTvSettings
2022-08-02 16:26:16 +00:00
import com.lagradost.cloudstream3.utils.AppUtils.isRecyclerScrollable
2022-12-28 11:51:55 +00:00
import com.lagradost.cloudstream3.utils.AppUtils.loadResult
import com.lagradost.cloudstream3.utils.DataStoreHelper
import com.lagradost.cloudstream3.utils.SingleSelectionHelper.showBottomDialog
import com.lagradost.cloudstream3.utils.UIHelper.fixPaddingStatusbarView
import kotlinx.android.synthetic.main.activity_main_tv.*
import kotlinx.android.synthetic.main.activity_main_tv.view.*
import kotlinx.android.synthetic.main.fragment_home.*
import kotlinx.android.synthetic.main.fragment_home.view.*
import kotlinx.android.synthetic.main.fragment_home_head_tv.*
import kotlinx.android.synthetic.main.fragment_home_head_tv.view.*
import kotlinx.android.synthetic.main.fragment_home_head_tv.view.home_preview
import kotlinx.android.synthetic.main.fragment_home_head_tv.view.home_preview_viewpager
2021-07-29 00:19:42 +00:00
import kotlinx.android.synthetic.main.homepage_parent.view.*
2022-12-28 11:51:55 +00:00
class LoadClickCallback(
val action: Int = 0,
val view: View,
val position: Int,
val response: LoadResponse
)
2022-12-28 11:51:55 +00:00
open class ParentItemAdapter(
private var items: MutableList<HomeViewModel.ExpandableHomepageList>,
2021-07-30 23:41:54 +00:00
private val clickCallback: (SearchClickCallback) -> Unit,
private val moreInfoClickCallback: (HomeViewModel.ExpandableHomepageList) -> Unit,
private val expandCallback: ((String) -> Unit)? = null,
2021-07-29 00:19:42 +00:00
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
2022-12-28 11:51:55 +00:00
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
2021-07-29 00:19:42 +00:00
return ParentViewHolder(
2022-12-28 11:51:55 +00:00
LayoutInflater.from(parent.context).inflate(
if (isTvSettings()) R.layout.homepage_parent_tv else R.layout.homepage_parent,
parent,
false
),
2022-01-30 22:02:57 +00:00
clickCallback,
moreInfoClickCallback,
expandCallback
2021-07-29 00:19:42 +00:00
)
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
when (holder) {
is ParentViewHolder -> {
2021-07-29 01:46:10 +00:00
holder.bind(items[position])
2021-07-29 00:19:42 +00:00
}
}
}
override fun getItemCount(): Int {
2021-07-29 01:46:10 +00:00
return items.size
2021-07-29 00:19:42 +00:00
}
2022-01-30 22:02:57 +00:00
override fun getItemId(position: Int): Long {
return items[position].list.name.hashCode().toLong()
2022-01-30 22:02:57 +00:00
}
@JvmName("updateListHomePageList")
2022-01-30 22:02:57 +00:00
fun updateList(newList: List<HomePageList>) {
updateList(newList.map { HomeViewModel.ExpandableHomepageList(it, 1, false) }
.toMutableList())
}
@JvmName("updateListExpandableHomepageList")
fun updateList(
newList: MutableList<HomeViewModel.ExpandableHomepageList>,
recyclerView: RecyclerView? = null
) {
// this
// 1. prevents deep copy that makes this.items == newList
// 2. filters out undesirable results
// 3. moves empty results to the bottom (sortedBy is a stable sort)
val new =
newList.map { it.copy(list = it.list.copy(list = it.list.list.filterSearchResponse())) }
.sortedBy { it.list.list.isEmpty() }
2022-01-30 22:02:57 +00:00
val diffResult = DiffUtil.calculateDiff(
SearchDiffCallback(items, new)
2022-03-29 21:07:41 +00:00
)
2022-01-30 22:02:57 +00:00
items.clear()
items.addAll(new)
2022-12-29 02:08:08 +00:00
//val mAdapter = this
val delta = if (this@ParentItemAdapter is HomeParentItemAdapterPreview) {
headItems
} else {
0
}
diffResult.dispatchUpdatesTo(object : ListUpdateCallback {
override fun onInserted(position: Int, count: Int) {
2022-12-29 02:08:08 +00:00
//notifyItemRangeChanged(position + delta, count)
notifyItemRangeInserted(position + delta, count)
}
override fun onRemoved(position: Int, count: Int) {
2022-12-29 02:08:08 +00:00
notifyItemRangeRemoved(position + delta, count)
}
override fun onMoved(fromPosition: Int, toPosition: Int) {
2022-12-29 02:08:08 +00:00
notifyItemMoved(fromPosition + delta, toPosition + delta)
}
2022-12-28 11:51:55 +00:00
override fun onChanged(_position: Int, count: Int, payload: Any?) {
2022-12-29 02:08:08 +00:00
2022-12-28 11:51:55 +00:00
val position = _position + delta
// I know kinda messy, what this does is using the update or bind instead of onCreateViewHolder -> bind
recyclerView?.apply {
// this loops every viewHolder in the recycle view and checks the position to see if it is within the update range
val missingUpdates = (position until (position + count)).toMutableSet()
2022-08-05 23:41:35 +00:00
for (i in 0 until itemCount) {
2022-12-28 11:51:55 +00:00
val child = getChildAt(i) ?: continue
val viewHolder = getChildViewHolder(child) ?: continue
if (viewHolder !is ParentViewHolder) continue
val absolutePosition = viewHolder.bindingAdapterPosition
if (absolutePosition >= position && absolutePosition < position + count) {
2022-12-28 11:51:55 +00:00
val expand = items.getOrNull(absolutePosition - delta) ?: continue
missingUpdates -= absolutePosition
//println("Updating ${viewHolder.title.text} ($absolutePosition $position) -> ${expand.list.name}")
if (viewHolder.title.text == expand.list.name) {
viewHolder.update(expand)
} else {
viewHolder.bind(expand)
}
}
}
// just in case some item did not get updated
for (i in missingUpdates) {
2022-12-29 02:08:08 +00:00
notifyItemChanged(i, payload)
}
2022-12-28 11:51:55 +00:00
} ?: run {
// in case we don't have a nice
2022-12-29 02:08:08 +00:00
notifyItemRangeChanged(position, count, payload)
}
}
})
2022-01-30 22:02:57 +00:00
//diffResult.dispatchUpdatesTo(this)
2022-01-30 22:02:57 +00:00
}
2021-07-29 00:19:42 +00:00
class ParentViewHolder
2021-07-29 00:54:27 +00:00
constructor(
itemView: View,
2021-07-30 23:41:54 +00:00
private val clickCallback: (SearchClickCallback) -> Unit,
private val moreInfoClickCallback: (HomeViewModel.ExpandableHomepageList) -> Unit,
private val expandCallback: ((String) -> Unit)? = null,
2021-07-29 00:54:27 +00:00
) :
2021-07-29 00:19:42 +00:00
RecyclerView.ViewHolder(itemView) {
2023-01-21 19:05:37 +00:00
val title: TextView = itemView.home_child_more_info
private val recyclerView: RecyclerView = itemView.home_child_recyclerview
fun update(expand: HomeViewModel.ExpandableHomepageList) {
val info = expand.list
(recyclerView.adapter as? HomeChildItemAdapter?)?.apply {
updateList(info.list.toMutableList())
hasNext = expand.hasNext
} ?: run {
recyclerView.adapter = HomeChildItemAdapter(
info.list.toMutableList(),
clickCallback = clickCallback,
nextFocusUp = recyclerView.nextFocusUpId,
nextFocusDown = recyclerView.nextFocusDownId,
).apply {
isHorizontal = info.isHorizontalImages
}
recyclerView.setLinearListLayout()
}
}
fun bind(expand: HomeViewModel.ExpandableHomepageList) {
val info = expand.list
2021-11-28 12:18:01 +00:00
recyclerView.adapter = HomeChildItemAdapter(
2022-02-13 00:53:40 +00:00
info.list.toMutableList(),
2021-11-28 12:18:01 +00:00
clickCallback = clickCallback,
nextFocusUp = recyclerView.nextFocusUpId,
nextFocusDown = recyclerView.nextFocusDownId,
).apply {
isHorizontal = info.isHorizontalImages
hasNext = expand.hasNext
}
recyclerView.setLinearListLayout()
title.text = info.name
recyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() {
var expandCount = 0
val name = expand.list.name
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
super.onScrollStateChanged(recyclerView, newState)
val adapter = recyclerView.adapter
if (adapter !is HomeChildItemAdapter) return
val count = adapter.itemCount
val hasNext = adapter.hasNext
2022-08-02 16:26:16 +00:00
/*println(
"scolling ${recyclerView.isRecyclerScrollable()} ${
recyclerView.canScrollHorizontally(
1
)
}"
)*/
//!recyclerView.canScrollHorizontally(1)
if (!recyclerView.isRecyclerScrollable() && hasNext && expandCount != count) {
expandCount = count
expandCallback?.invoke(name)
}
}
})
2022-02-13 00:53:40 +00:00
//(recyclerView.adapter as HomeChildItemAdapter).notifyDataSetChanged()
2023-01-21 19:05:37 +00:00
if (!isTvSettings()) {
title.setOnClickListener {
moreInfoClickCallback.invoke(expand)
}
2021-07-29 00:54:27 +00:00
}
2021-07-29 00:19:42 +00:00
}
}
2022-01-30 22:02:57 +00:00
}
2022-03-29 21:07:41 +00:00
class SearchDiffCallback(
private val oldList: List<HomeViewModel.ExpandableHomepageList>,
private val newList: List<HomeViewModel.ExpandableHomepageList>
2022-03-29 21:07:41 +00:00
) :
2022-01-30 22:02:57 +00:00
DiffUtil.Callback() {
override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int) =
oldList[oldItemPosition].list.name == newList[newItemPosition].list.name
2022-01-30 22:02:57 +00:00
override fun getOldListSize() = oldList.size
override fun getNewListSize() = newList.size
override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean =
2022-01-30 22:02:57 +00:00
oldList[oldItemPosition] == newList[newItemPosition]
2021-07-29 00:19:42 +00:00
}