tv UI change + homepage optimization

This commit is contained in:
LagradOst 2022-12-28 12:51:55 +01:00
parent 4f4061961a
commit 2a32f62fe3
31 changed files with 2012 additions and 1362 deletions

View file

@ -183,7 +183,9 @@ class ExampleInstrumentedTest {
getAllProviders().amap { api -> getAllProviders().amap { api ->
if (api.hasMainPage) { if (api.hasMainPage) {
try { try {
val homepage = api.getMainPage() val f = api.mainPage.first()
val homepage =
api.getMainPage(1, MainPageRequest(f.name, f.data, f.horizontalImages))
when { when {
homepage == null -> { homepage == null -> {
System.err.println("Homepage provider ${api.name} did not correctly load homepage!") System.err.println("Homepage provider ${api.name} did not correctly load homepage!")

View file

@ -0,0 +1,11 @@
package com.lagradost.cloudstream3
import android.view.LayoutInflater
import androidx.annotation.LayoutRes
import androidx.recyclerview.widget.RecyclerView
import com.lagradost.cloudstream3.ui.HeaderViewDecoration
fun setHeaderDecoration(view: RecyclerView, @LayoutRes headerViewRes: Int) {
val headerView = LayoutInflater.from(view.context).inflate(headerViewRes, null)
view.addItemDecoration(HeaderViewDecoration(headerView))
}

View file

@ -10,12 +10,18 @@ import android.view.KeyEvent
import android.view.Menu import android.view.Menu
import android.view.MenuItem import android.view.MenuItem
import android.view.WindowManager import android.view.WindowManager
import android.widget.FrameLayout
import android.widget.LinearLayout
import androidx.activity.result.ActivityResultLauncher import androidx.activity.result.ActivityResultLauncher
import androidx.annotation.IdRes import androidx.annotation.IdRes
import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.view.isVisible import androidx.core.view.isVisible
import androidx.core.view.marginRight
import androidx.core.view.setMargins
import androidx.fragment.app.FragmentActivity import androidx.fragment.app.FragmentActivity
import androidx.fragment.app.FragmentContainerView
import androidx.navigation.NavController import androidx.navigation.NavController
import androidx.navigation.NavDestination import androidx.navigation.NavDestination
import androidx.navigation.NavDestination.Companion.hierarchy import androidx.navigation.NavDestination.Companion.hierarchy
@ -66,6 +72,7 @@ import com.lagradost.cloudstream3.ui.search.SearchResultBuilder
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isEmulatorSettings import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isEmulatorSettings
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTrueTvSettings import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTrueTvSettings
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTvSettings import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTvSettings
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.updateTv
import com.lagradost.cloudstream3.ui.settings.SettingsGeneral import com.lagradost.cloudstream3.ui.settings.SettingsGeneral
import com.lagradost.cloudstream3.ui.setup.HAS_DONE_SETUP_KEY import com.lagradost.cloudstream3.ui.setup.HAS_DONE_SETUP_KEY
import com.lagradost.cloudstream3.ui.setup.SetupFragmentExtensions import com.lagradost.cloudstream3.ui.setup.SetupFragmentExtensions
@ -89,6 +96,7 @@ import com.lagradost.cloudstream3.utils.UIHelper.getResourceColor
import com.lagradost.cloudstream3.utils.UIHelper.hideKeyboard import com.lagradost.cloudstream3.utils.UIHelper.hideKeyboard
import com.lagradost.cloudstream3.utils.UIHelper.navigate import com.lagradost.cloudstream3.utils.UIHelper.navigate
import com.lagradost.cloudstream3.utils.UIHelper.requestRW import com.lagradost.cloudstream3.utils.UIHelper.requestRW
import com.lagradost.cloudstream3.utils.UIHelper.toPx
import com.lagradost.cloudstream3.utils.USER_PROVIDER_API import com.lagradost.cloudstream3.utils.USER_PROVIDER_API
import com.lagradost.cloudstream3.utils.USER_SELECTED_HOMEPAGE_API import com.lagradost.cloudstream3.utils.USER_SELECTED_HOMEPAGE_API
import com.lagradost.nicehttp.Requests import com.lagradost.nicehttp.Requests
@ -379,6 +387,27 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener {
R.id.navigation_settings_plugins, R.id.navigation_settings_plugins,
).contains(destination.id) ).contains(destination.id)
val dontPush = listOf(
R.id.navigation_home,
R.id.navigation_search,
R.id.navigation_results_phone,
R.id.navigation_results_tv,
R.id.navigation_player,
).contains(destination.id)
nav_host_fragment?.apply {
val params = layoutParams as ConstraintLayout.LayoutParams
params.setMargins(
if (!dontPush && isTvSettings()) resources.getDimensionPixelSize(R.dimen.navbar_width) else 0,
params.topMargin,
params.rightMargin,
params.bottomMargin
)
layoutParams = params
}
val landscape = when (resources.configuration.orientation) { val landscape = when (resources.configuration.orientation) {
Configuration.ORIENTATION_LANDSCAPE -> { Configuration.ORIENTATION_LANDSCAPE -> {
true true
@ -619,7 +648,7 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener {
} }
window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN) window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN)
updateTv()
if (isTvSettings()) { if (isTvSettings()) {
setContentView(R.layout.activity_main_tv) setContentView(R.layout.activity_main_tv)
} else { } else {
@ -743,7 +772,12 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener {
nav_view?.setupWithNavController(navController) nav_view?.setupWithNavController(navController)
val nav_rail = findViewById<NavigationRailView?>(R.id.nav_rail_view) val nav_rail = findViewById<NavigationRailView?>(R.id.nav_rail_view)
nav_rail?.setupWithNavController(navController) nav_rail?.setupWithNavController(navController)
if (isTvSettings()) {
nav_rail?.background?.alpha = 200
} else {
nav_rail?.background?.alpha = 255
}
nav_rail?.setOnItemSelectedListener { item -> nav_rail?.setOnItemSelectedListener { item ->
onNavDestinationSelected( onNavDestinationSelected(
item, item,

View file

@ -0,0 +1,42 @@
package com.lagradost.cloudstream3.ui
import android.graphics.Canvas
import android.graphics.Rect
import android.view.View
import androidx.recyclerview.widget.RecyclerView
class HeaderViewDecoration(private val customView: View) : RecyclerView.ItemDecoration() {
override fun onDraw(c: Canvas, parent: RecyclerView, state: RecyclerView.State) {
super.onDraw(c, parent, state)
customView.layout(parent.left, 0, parent.right, customView.measuredHeight)
for (i in 0 until parent.childCount) {
val view = parent.getChildAt(i)
if (parent.getChildAdapterPosition(view) == 0) {
c.save()
val height = customView.measuredHeight
val top = view.top - height
c.translate(0f, top.toFloat())
customView.draw(c)
c.restore()
break
}
}
}
override fun getItemOffsets(
outRect: Rect,
view: View,
parent: RecyclerView,
state: RecyclerView.State
) {
if (parent.getChildAdapterPosition(view) == 0) {
customView.measure(
View.MeasureSpec.makeMeasureSpec(parent.measuredWidth, View.MeasureSpec.AT_MOST),
View.MeasureSpec.makeMeasureSpec(parent.measuredHeight, View.MeasureSpec.AT_MOST)
)
outRect.set(0, customView.measuredHeight, 0, 0)
} else {
outRect.setEmpty()
}
}
}

View file

@ -31,6 +31,7 @@ import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.google.android.material.bottomsheet.BottomSheetDialog import com.google.android.material.bottomsheet.BottomSheetDialog
import com.google.android.material.button.MaterialButton import com.google.android.material.button.MaterialButton
import com.google.android.material.chip.Chip import com.google.android.material.chip.Chip
import com.google.android.material.chip.ChipDrawable
import com.google.android.material.chip.ChipGroup import com.google.android.material.chip.ChipGroup
import com.lagradost.cloudstream3.* import com.lagradost.cloudstream3.*
import com.lagradost.cloudstream3.APIHolder.apis import com.lagradost.cloudstream3.APIHolder.apis
@ -84,31 +85,21 @@ import com.lagradost.cloudstream3.utils.UIHelper.setImage
import com.lagradost.cloudstream3.utils.UIHelper.setImageBlur import com.lagradost.cloudstream3.utils.UIHelper.setImageBlur
import com.lagradost.cloudstream3.utils.USER_SELECTED_HOMEPAGE_API import com.lagradost.cloudstream3.utils.USER_SELECTED_HOMEPAGE_API
import com.lagradost.cloudstream3.widget.CenterZoomLayoutManager import com.lagradost.cloudstream3.widget.CenterZoomLayoutManager
import kotlinx.android.synthetic.main.activity_main_tv.*
import kotlinx.android.synthetic.main.fragment_home.* import kotlinx.android.synthetic.main.fragment_home.*
import kotlinx.android.synthetic.main.fragment_home.home_api_fab import kotlinx.android.synthetic.main.fragment_home.home_api_fab
import kotlinx.android.synthetic.main.fragment_home.home_bookmarked_child_recyclerview
import kotlinx.android.synthetic.main.fragment_home.home_bookmarked_holder
import kotlinx.android.synthetic.main.fragment_home.home_change_api_loading import kotlinx.android.synthetic.main.fragment_home.home_change_api_loading
import kotlinx.android.synthetic.main.fragment_home.home_loaded
import kotlinx.android.synthetic.main.fragment_home.home_loading import kotlinx.android.synthetic.main.fragment_home.home_loading
import kotlinx.android.synthetic.main.fragment_home.home_loading_error import kotlinx.android.synthetic.main.fragment_home.home_loading_error
import kotlinx.android.synthetic.main.fragment_home.home_loading_shimmer import kotlinx.android.synthetic.main.fragment_home.home_loading_shimmer
import kotlinx.android.synthetic.main.fragment_home.home_loading_statusbar import kotlinx.android.synthetic.main.fragment_home.home_loading_statusbar
import kotlinx.android.synthetic.main.fragment_home.home_master_recycler import kotlinx.android.synthetic.main.fragment_home.home_master_recycler
import kotlinx.android.synthetic.main.fragment_home.home_plan_to_watch_btt
import kotlinx.android.synthetic.main.fragment_home.home_provider_meta_info
import kotlinx.android.synthetic.main.fragment_home.home_provider_name
import kotlinx.android.synthetic.main.fragment_home.home_reload_connection_open_in_browser import kotlinx.android.synthetic.main.fragment_home.home_reload_connection_open_in_browser
import kotlinx.android.synthetic.main.fragment_home.home_reload_connectionerror import kotlinx.android.synthetic.main.fragment_home.home_reload_connectionerror
import kotlinx.android.synthetic.main.fragment_home.home_type_completed_btt
import kotlinx.android.synthetic.main.fragment_home.home_type_dropped_btt
import kotlinx.android.synthetic.main.fragment_home.home_type_on_hold_btt
import kotlinx.android.synthetic.main.fragment_home.home_type_watching_btt
import kotlinx.android.synthetic.main.fragment_home.home_watch_child_recyclerview
import kotlinx.android.synthetic.main.fragment_home.home_watch_holder
import kotlinx.android.synthetic.main.fragment_home.home_watch_parent_item_title
import kotlinx.android.synthetic.main.fragment_home.result_error_text import kotlinx.android.synthetic.main.fragment_home.result_error_text
import kotlinx.android.synthetic.main.fragment_home_head_tv.*
import kotlinx.android.synthetic.main.fragment_home_tv.* import kotlinx.android.synthetic.main.fragment_home_tv.*
import kotlinx.android.synthetic.main.fragment_result.*
import kotlinx.android.synthetic.main.fragment_search.* import kotlinx.android.synthetic.main.fragment_search.*
import kotlinx.android.synthetic.main.home_episodes_expanded.* import kotlinx.android.synthetic.main.home_episodes_expanded.*
import kotlinx.android.synthetic.main.tvtypes_chips.* import kotlinx.android.synthetic.main.tvtypes_chips.*
@ -440,10 +431,6 @@ class HomeFragment : Fragment() {
return inflater.inflate(layout, container, false) return inflater.inflate(layout, container, false)
} }
private fun toggleMainVisibility(visible: Boolean) {
home_main_poster_recyclerview?.isVisible = visible
}
@SuppressLint("NotifyDataSetChanged") // we need to notify to change poster @SuppressLint("NotifyDataSetChanged") // we need to notify to change poster
private fun fixGrid() { private fun fixGrid() {
activity?.getSpanCount()?.let { activity?.getSpanCount()?.let {
@ -467,7 +454,7 @@ class HomeFragment : Fragment() {
override fun onConfigurationChanged(newConfig: Configuration) { override fun onConfigurationChanged(newConfig: Configuration) {
super.onConfigurationChanged(newConfig) super.onConfigurationChanged(newConfig)
(home_preview_viewpager?.adapter as? HomeScrollAdapter)?.notifyDataSetChanged() //(home_preview_viewpager?.adapter as? HomeScrollAdapter)?.notifyDataSetChanged()
fixGrid() fixGrid()
} }
@ -517,8 +504,9 @@ class HomeFragment : Fragment() {
}*/ }*/
private fun focusCallback(card: SearchResponse) { private fun focusCallback(card: SearchResponse) {
home_focus_text?.text = card.name // home_focus_text?.text = card.name
home_blur_poster?.setImageBlur(card.posterUrl, 50) // home_blur_poster?.setImageBlur(card.posterUrl, 50, headers = card.posterHeaders)
// home_bg_poster?.setImage(card.posterUrl,headers =card.posterHeaders)
} }
private fun homeHandleSearch(callback: SearchClickCallback) { private fun homeHandleSearch(callback: SearchClickCallback) {
@ -537,8 +525,8 @@ class HomeFragment : Fragment() {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
fixGrid() fixGrid()
home_change_api?.setOnClickListener(apiChangeClickListener)
home_change_api_loading?.setOnClickListener(apiChangeClickListener) home_change_api_loading?.setOnClickListener(apiChangeClickListener)
home_preview_change_api?.setOnClickListener(apiChangeClickListener)
home_api_fab?.setOnClickListener(apiChangeClickListener) home_api_fab?.setOnClickListener(apiChangeClickListener)
home_random?.setOnClickListener { home_random?.setOnClickListener {
if (listHomepageItems.isNotEmpty()) { if (listHomepageItems.isNotEmpty()) {
@ -557,208 +545,135 @@ class HomeFragment : Fragment() {
observe(homeViewModel.preview) { preview -> observe(homeViewModel.preview) { preview ->
// Always reset the padding, otherwise the will move lower and lower // Always reset the padding, otherwise the will move lower and lower
// home_fix_padding?.setPadding(0, 0, 0, 0) // home_fix_padding?.setPadding(0, 0, 0, 0)
home_fix_padding?.let { v -> //home_fix_padding?.let { v ->
val params = v.layoutParams // val params = v.layoutParams
params.height = 0 // params.height = 0
v.layoutParams = params // v.layoutParams = params
} //}
when (preview) { (home_master_recycler?.adapter as? HomeParentItemAdapterPreview?)?.setPreviewData(
is Resource.Success -> { preview
home_preview?.isVisible = true )
(home_preview_viewpager?.adapter as? HomeScrollAdapter)?.apply {
if (!setItems(preview.value.second, preview.value.first)) {
home_preview_viewpager?.setCurrentItem(0, false)
}
// home_preview_viewpager?.setCurrentItem(1000, false)
}
//.also { //when (preview) {
//home_preview_viewpager?.adapter = // is Resource.Success -> {
// home_preview?.isVisible = true
// (home_preview_viewpager?.adapter as? HomeScrollAdapter)?.apply {
// if (!setItems(preview.value.second, preview.value.first)) {
// home_preview_viewpager?.setCurrentItem(0, false)
// }
// // home_preview_viewpager?.setCurrentItem(1000, false)
// }
//
// //.also {
// //home_preview_viewpager?.adapter =
// //}
// }
// else -> {
// (home_preview_viewpager?.adapter as? HomeScrollAdapter)?.setItems(
// listOf(),
// false
// )
// home_preview?.isVisible = false
// context?.fixPaddingStatusbarView(home_fix_padding)
// }
//} //}
} }
else -> {
(home_preview_viewpager?.adapter as? HomeScrollAdapter)?.setItems(
listOf(),
false
)
home_preview?.isVisible = false
context?.fixPaddingStatusbarView(home_fix_padding)
}
}
}
val searchText = //val searchText =
home_search?.findViewById<SearchView.SearchAutoComplete>(androidx.appcompat.R.id.search_src_text) // home_search?.findViewById<SearchView.SearchAutoComplete>(androidx.appcompat.R.id.search_src_text)
searchText?.context?.getResourceColor(R.attr.white)?.let { color -> //searchText?.context?.getResourceColor(R.attr.white)?.let { color ->
searchText.setTextColor(color) // searchText.setTextColor(color)
searchText.setHintTextColor(color) // searchText.setHintTextColor(color)
} //}
home_preview_viewpager?.apply {
setPageTransformer(HomeScrollTransformer())
val callback: OnPageChangeCallback = object : OnPageChangeCallback() {
override fun onPageSelected(position: Int) {
// home_search?.isIconified = true
//home_search?.isVisible = true
//home_search?.clearFocus()
(home_preview_viewpager?.adapter as? HomeScrollAdapter)?.apply {
if (position >= itemCount - 1 && hasMoreItems) {
hasMoreItems = false // dont make two requests
homeViewModel.loadMoreHomeScrollResponses()
}
getItem(position)
?.apply {
home_preview_title_holder?.let { parent ->
TransitionManager.beginDelayedTransition(parent, ChangeBounds())
}
// home_preview_tags?.text = tags?.joinToString(" • ") ?: ""
// home_preview_tags?.isGone = tags.isNullOrEmpty()
// home_preview_image?.setImage(posterUrl, posterHeaders)
// home_preview_title?.text = name
home_preview_play?.setOnClickListener {
activity?.loadResult(url, apiName, START_ACTION_RESUME_LATEST)
//activity.loadSearchResult(url, START_ACTION_RESUME_LATEST)
}
home_preview_info?.setOnClickListener {
activity?.loadResult(url, apiName)
//activity.loadSearchResult(random)
}
// very ugly code, but I dont care
val watchType = DataStoreHelper.getResultWatchState(this.getId())
home_preview_bookmark?.setText(watchType.stringRes)
home_preview_bookmark?.setCompoundDrawablesWithIntrinsicBounds(
null,
getDrawable(home_preview_bookmark.context, watchType.iconRes),
null,
null
)
home_preview_bookmark?.setOnClickListener { fab ->
activity?.showBottomDialog(
WatchType.values()
.map { fab.context.getString(it.stringRes) }
.toList(),
DataStoreHelper.getResultWatchState(this.getId()).ordinal,
fab.context.getString(R.string.action_add_to_bookmarks),
showApply = false,
{}) {
val newValue = WatchType.values()[it]
home_preview_bookmark?.setCompoundDrawablesWithIntrinsicBounds(
null,
getDrawable(
home_preview_bookmark.context,
newValue.iconRes
),
null,
null
)
home_preview_bookmark?.setText(newValue.stringRes)
updateWatchStatus(this, newValue)
reloadStored()
}
}
}
}
}
}
registerOnPageChangeCallback(callback)
adapter = HomeScrollAdapter()
}
observe(homeViewModel.apiName) { apiName -> observe(homeViewModel.apiName) { apiName ->
currentApiName = apiName currentApiName = apiName
// setKey(USER_SELECTED_HOMEPAGE_API, apiName) // setKey(USER_SELECTED_HOMEPAGE_API, apiName)
home_api_fab?.text = apiName home_api_fab?.text = apiName
home_provider_name?.text = apiName //home_provider_name?.text = apiName
try { // try {
home_search?.queryHint = getString(R.string.search_hint_site).format(apiName) // home_search?.queryHint = getString(R.string.search_hint_site).format(apiName)
} catch (e: Exception) { // } catch (e: Exception) {
logError(e) // logError(e)
} // }
home_provider_meta_info?.isVisible = false //home_provider_meta_info?.isVisible = false
getApiFromNameNull(apiName)?.let { currentApi -> //getApiFromNameNull(apiName)?.let { currentApi ->
val typeChoices = listOf( // val typeChoices = listOf(
Pair(R.string.movies, listOf(TvType.Movie)), // Pair(R.string.movies, listOf(TvType.Movie)),
Pair(R.string.tv_series, listOf(TvType.TvSeries)), // Pair(R.string.tv_series, listOf(TvType.TvSeries)),
Pair(R.string.documentaries, listOf(TvType.Documentary)), // Pair(R.string.documentaries, listOf(TvType.Documentary)),
Pair(R.string.cartoons, listOf(TvType.Cartoon)), // Pair(R.string.cartoons, listOf(TvType.Cartoon)),
Pair(R.string.anime, listOf(TvType.Anime, TvType.OVA, TvType.AnimeMovie)), // Pair(R.string.anime, listOf(TvType.Anime, TvType.OVA, TvType.AnimeMovie)),
Pair(R.string.torrent, listOf(TvType.Torrent)), // Pair(R.string.torrent, listOf(TvType.Torrent)),
Pair(R.string.asian_drama, listOf(TvType.AsianDrama)), // Pair(R.string.asian_drama, listOf(TvType.AsianDrama)),
).filter { item -> currentApi.supportedTypes.any { type -> item.second.contains(type) } } // ).filter { item -> currentApi.supportedTypes.any { type -> item.second.contains(type) } }
home_provider_meta_info?.text = // home_provider_meta_info?.text =
typeChoices.joinToString(separator = ", ") { getString(it.first) } // typeChoices.joinToString(separator = ", ") { getString(it.first) }
home_provider_meta_info?.isVisible = true // home_provider_meta_info?.isVisible = true
} //}
} }
home_main_poster_recyclerview?.adapter = //home_main_poster_recyclerview?.adapter =
HomeChildItemAdapter( // HomeChildItemAdapter(
mutableListOf(), // mutableListOf(),
R.layout.home_result_big_grid, // R.layout.home_result_big_grid,
nextFocusUp = home_main_poster_recyclerview?.nextFocusUpId, // nextFocusUp = home_main_poster_recyclerview?.nextFocusUpId,
nextFocusDown = home_main_poster_recyclerview?.nextFocusDownId // nextFocusDown = home_main_poster_recyclerview?.nextFocusDownId
) { callback -> // ) { callback ->
homeHandleSearch(callback) // homeHandleSearch(callback)
} // }
home_main_poster_recyclerview?.setLinearListLayout() //home_main_poster_recyclerview?.setLinearListLayout()
observe(homeViewModel.randomItems) { items -> //observe(homeViewModel.randomItems) { items ->
if (items.isNullOrEmpty()) { // if (items.isNullOrEmpty()) {
toggleMainVisibility(false) // toggleMainVisibility(false)
} else { // } else {
val tempAdapter = home_main_poster_recyclerview?.adapter as? HomeChildItemAdapter? // val tempAdapter = home_main_poster_recyclerview?.adapter as? HomeChildItemAdapter?
// no need to reload if it has the same data // // no need to reload if it has the same data
if (tempAdapter != null && tempAdapter.cardList == items) { // if (tempAdapter != null && tempAdapter.cardList == items) {
toggleMainVisibility(true) // toggleMainVisibility(true)
return@observe // return@observe
} // }
//
// val randomSize = items.size
// tempAdapter?.updateList(items)
// if (!isTvSettings()) {
// home_main_poster_recyclerview?.post {
// (home_main_poster_recyclerview?.layoutManager as CenterZoomLayoutManager?)?.let { manager ->
// manager.updateSize(forceUpdate = true)
// if (randomSize > 2) {
// manager.scrollToPosition(randomSize / 2)
// manager.snap { dx ->
// home_main_poster_recyclerview?.post {
// // this is the best I can do, fuck android for not including instant scroll
// home_main_poster_recyclerview?.smoothScrollBy(dx, 0)
// }
// }
// }
// }
// }
// } else {
// items.firstOrNull()?.let {
// focusCallback(it)
// }
// }
// toggleMainVisibility(true)
// }
//}
val randomSize = items.size //home_search?.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
tempAdapter?.updateList(items) // override fun onQueryTextSubmit(query: String): Boolean {
if (!isTvSettings()) { // QuickSearchFragment.pushSearch(activity, query, currentApiName?.let { arrayOf(it) })
home_main_poster_recyclerview?.post { //
(home_main_poster_recyclerview?.layoutManager as CenterZoomLayoutManager?)?.let { manager -> // return true
manager.updateSize(forceUpdate = true) // }
if (randomSize > 2) { //
manager.scrollToPosition(randomSize / 2) // override fun onQueryTextChange(newText: String): Boolean {
manager.snap { dx -> // //searchViewModel.quickSearch(newText)
home_main_poster_recyclerview?.post { // return true
// this is the best I can do, fuck android for not including instant scroll // }
home_main_poster_recyclerview?.smoothScrollBy(dx, 0) //})
}
}
}
}
}
} else {
items.firstOrNull()?.let {
focusCallback(it)
}
}
toggleMainVisibility(true)
}
}
home_search?.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
override fun onQueryTextSubmit(query: String): Boolean {
QuickSearchFragment.pushSearch(activity, query, currentApiName?.let { arrayOf(it) })
return true
}
override fun onQueryTextChange(newText: String): Boolean {
//searchViewModel.quickSearch(newText)
return true
}
})
observe(homeViewModel.page) { data -> observe(homeViewModel.page) { data ->
when (data) { when (data) {
@ -769,7 +684,6 @@ class HomeFragment : Fragment() {
val mutableListOfResponse = mutableListOf<SearchResponse>() val mutableListOfResponse = mutableListOf<SearchResponse>()
listHomepageItems.clear() listHomepageItems.clear()
// println("ITEMCOUNT: ${d.values.size} ${home_master_recycler?.adapter?.itemCount}")
(home_master_recycler?.adapter as? ParentItemAdapter?)?.updateList( (home_master_recycler?.adapter as? ParentItemAdapter?)?.updateList(
d.values.toMutableList(), d.values.toMutableList(),
home_master_recycler home_master_recycler
@ -777,7 +691,7 @@ class HomeFragment : Fragment() {
home_loading?.isVisible = false home_loading?.isVisible = false
home_loading_error?.isVisible = false home_loading_error?.isVisible = false
home_loaded?.isVisible = true //home_loaded?.isVisible = true
if (toggleRandomButton) { if (toggleRandomButton) {
//Flatten list //Flatten list
d.values.forEach { dlist -> d.values.forEach { dlist ->
@ -817,80 +731,29 @@ class HomeFragment : Fragment() {
home_loading?.isVisible = false home_loading?.isVisible = false
home_loading_error?.isVisible = true home_loading_error?.isVisible = true
home_loaded?.isVisible = false //home_loaded?.isVisible = false
} }
is Resource.Loading -> { is Resource.Loading -> {
(home_master_recycler?.adapter as? ParentItemAdapter?)?.updateList(listOf()) (home_master_recycler?.adapter as? ParentItemAdapter?)?.updateList(listOf())
home_loading_shimmer?.startShimmer() home_loading_shimmer?.startShimmer()
home_loading?.isVisible = true home_loading?.isVisible = true
home_loading_error?.isVisible = false home_loading_error?.isVisible = false
home_loaded?.isVisible = false //home_loaded?.isVisible = false
} }
} }
} }
val toggleList = listOf(
Pair(home_type_watching_btt, WatchType.WATCHING),
Pair(home_type_completed_btt, WatchType.COMPLETED),
Pair(home_type_dropped_btt, WatchType.DROPPED),
Pair(home_type_on_hold_btt, WatchType.ONHOLD),
Pair(home_plan_to_watch_btt, WatchType.PLANTOWATCH),
)
val currentSet = getKey<IntArray>(HOME_BOOKMARK_VALUE_LIST)
?.map { WatchType.fromInternalId(it) }?.toSet() ?: emptySet()
for ((chip, watch) in toggleList) {
chip.isChecked = currentSet.contains(watch)
chip?.setOnCheckedChangeListener { _, isChecked ->
if (isChecked) {
homeViewModel.loadStoredData(
setOf(watch)
// If we filter all buttons then two can be checked at the same time
// Revert this if you want to go back to multi selection
// toggleList.filter { it.first?.isChecked == true }.map { it.second }.toSet()
)
}
// Else if all are unchecked -> Do not load data
else if (toggleList.all { it.first?.isChecked != true }) {
homeViewModel.loadStoredData(emptySet())
}
}
/*chip?.setOnClickListener {
homeViewModel.loadStoredData(EnumSet.of(watch))
}
chip?.setOnLongClickListener { itemView ->
val list = EnumSet.noneOf(WatchType::class.java)
itemView.context.getKey<IntArray>(HOME_BOOKMARK_VALUE_LIST)
?.map { WatchType.fromInternalId(it) }?.let {
list.addAll(it)
}
if (list.contains(watch)) {
list.remove(watch)
} else {
list.add(watch)
}
homeViewModel.loadStoredData(list)
return@setOnLongClickListener true
}*/
}
observe(homeViewModel.availableWatchStatusTypes) { availableWatchStatusTypes -> observe(homeViewModel.availableWatchStatusTypes) { availableWatchStatusTypes ->
context?.setKey( context?.setKey(
HOME_BOOKMARK_VALUE_LIST, HOME_BOOKMARK_VALUE_LIST,
availableWatchStatusTypes.first.map { it.internalId }.toIntArray() availableWatchStatusTypes.first.map { it.internalId }.toIntArray()
) )
(home_master_recycler?.adapter as? HomeParentItemAdapterPreview?)?.setAvailableWatchStatusTypes(
availableWatchStatusTypes
)
for (item in toggleList) {
val watch = item.second
item.first?.apply {
isVisible = availableWatchStatusTypes.second.contains(watch)
isSelected = availableWatchStatusTypes.first.contains(watch)
}
}
/*home_bookmark_select?.setOnClickListener { /*home_bookmark_select?.setOnClickListener {
it.popupMenuNoIcons(availableWatchStatusTypes.second.map { type -> it.popupMenuNoIcons(availableWatchStatusTypes.second.map { type ->
@ -905,32 +768,40 @@ class HomeFragment : Fragment() {
home_bookmarked_parent_item_title?.text = getString(availableWatchStatusTypes.first.stringRes)*/ home_bookmarked_parent_item_title?.text = getString(availableWatchStatusTypes.first.stringRes)*/
} }
observe(homeViewModel.bookmarks) { (isVis, bookmarks) -> //TODO REMAKE
home_bookmarked_holder.isVisible = isVis observe(homeViewModel.bookmarks) { data ->
(home_master_recycler?.adapter as? HomeParentItemAdapterPreview?)?.setBookmarkData(
(home_bookmarked_child_recyclerview?.adapter as? HomeChildItemAdapter?)?.updateList( data
bookmarks
) )
home_bookmarked_child_more_info?.setOnClickListener { //(home_bookmarked_child_recyclerview?.adapter as? HomeChildItemAdapter?)?.updateList(
activity?.loadHomepageList( // bookmarks
HomePageList( //)
getString(R.string.error_bookmarks_text), //home_bookmarked_parent_item_title?.text?.toString() ?: getString(R.string.error_bookmarks_text), //
bookmarks // home_bookmarked_child_more_info?.setOnClickListener {
) // activity?.loadHomepageList(
) { // HomePageList(
deleteAllBookmarkedData() // getString(R.string.error_bookmarks_text), //home_bookmarked_parent_item_title?.text?.toString() ?: getString(R.string.error_bookmarks_text),
homeViewModel.loadStoredData(null) // bookmarks
} // )
} // ) {
// deleteAllBookmarkedData()
// homeViewModel.loadStoredData(null)
// }
// }
} }
observe(homeViewModel.resumeWatching) { resumeWatching -> observe(homeViewModel.resumeWatching) { resumeWatching ->
home_watch_holder?.isVisible = resumeWatching.isNotEmpty() (home_master_recycler?.adapter as? HomeParentItemAdapterPreview?)?.setResumeWatchingData(
(home_watch_child_recyclerview?.adapter as? HomeChildItemAdapter?)?.updateList(
resumeWatching resumeWatching
) )
//home_watch_holder?.isVisible = resumeWatching.isNotEmpty()
//(home_watch_child_recyclerview?.adapter as? HomeChildItemAdapter?)?.updateList(
// resumeWatching
//)
if (isTrueTvSettings()) { if (isTrueTvSettings()) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
ioSafe { ioSafe {
@ -939,21 +810,21 @@ class HomeFragment : Fragment() {
} }
} }
home_watch_child_more_info?.setOnClickListener { //home_watch_child_more_info?.setOnClickListener {
activity?.loadHomepageList( // activity?.loadHomepageList(
HomePageList( // HomePageList(
home_watch_parent_item_title?.text?.toString() // home_watch_parent_item_title?.text?.toString()
?: getString(R.string.continue_watching), // ?: getString(R.string.continue_watching),
resumeWatching // resumeWatching
) // )
) { // ) {
deleteAllResumeStateIds() // deleteAllResumeStateIds()
homeViewModel.loadResumeWatching() // homeViewModel.loadResumeWatching()
} // }
} //}
} }
home_bookmarked_child_recyclerview.adapter = HomeChildItemAdapter( home_bookmarked_child_recyclerview?.adapter = HomeChildItemAdapter(
ArrayList(), ArrayList(),
nextFocusUp = home_bookmarked_child_recyclerview?.nextFocusUpId, nextFocusUp = home_bookmarked_child_recyclerview?.nextFocusUpId,
nextFocusDown = home_bookmarked_child_recyclerview?.nextFocusDownId nextFocusDown = home_bookmarked_child_recyclerview?.nextFocusDownId
@ -995,7 +866,6 @@ class HomeFragment : Fragment() {
reloadStored() reloadStored()
} }
if (isTv) {
when (actionId) { when (actionId) {
0 -> { 0 -> {
play() play()
@ -1007,23 +877,13 @@ class HomeFragment : Fragment() {
remove() remove()
} }
} }
} else {
when (actionId) {
0 -> {
info()
}
1 -> {
remove()
}
}
}
} }
} else { } else {
homeHandleSearch(callback) homeHandleSearch(callback)
} }
} }
home_watch_child_recyclerview.setLinearListLayout() home_watch_child_recyclerview?.setLinearListLayout()
home_bookmarked_child_recyclerview.setLinearListLayout() home_bookmarked_child_recyclerview?.setLinearListLayout()
home_watch_child_recyclerview?.adapter = HomeChildItemAdapter( home_watch_child_recyclerview?.adapter = HomeChildItemAdapter(
ArrayList(), ArrayList(),
@ -1100,11 +960,11 @@ class HomeFragment : Fragment() {
} }
//context?.fixPaddingStatusbarView(home_statusbar) //context?.fixPaddingStatusbarView(home_statusbar)
context?.fixPaddingStatusbar(home_padding) //context?.fixPaddingStatusbar(home_padding)
context?.fixPaddingStatusbar(home_loading_statusbar) context?.fixPaddingStatusbar(home_loading_statusbar)
home_master_recycler.adapter = home_master_recycler?.adapter =
ParentItemAdapter(mutableListOf(), { callback -> HomeParentItemAdapterPreview(mutableListOf(), { callback ->
homeHandleSearch(callback) homeHandleSearch(callback)
}, { item -> }, { item ->
activity?.loadHomepageList(item, expandCallback = { activity?.loadHomepageList(item, expandCallback = {
@ -1112,19 +972,38 @@ class HomeFragment : Fragment() {
}) })
}, { name -> }, { name ->
homeViewModel.expand(name) homeViewModel.expand(name)
}) }, { load ->
home_master_recycler.setLinearListLayout() activity?.loadResult(load.response.url, load.response.apiName, load.action)
home_master_recycler?.setMaxViewPoolSize(0, Int.MAX_VALUE) }, {
home_master_recycler.layoutManager = object : LinearLayoutManager(context) { homeViewModel.loadMoreHomeScrollResponses()
override fun supportsPredictiveItemAnimations(): Boolean { }, {
return false apiChangeClickListener.onClick(it)
}, reloadStored = {
reloadStored()
}, loadStoredData = {
homeViewModel.loadStoredData(it)
}, { (isQuickSearch, text) ->
if (!isQuickSearch) {
QuickSearchFragment.pushSearch(
activity,
text,
currentApiName?.let { arrayOf(it) })
} }
} // GridLayoutManager(context, 1).also { it.supportsPredictiveItemAnimations() } })
//home_master_recycler.setLinearListLayout()
//home_master_recycler?.setMaxViewPoolSize(0, 4)
//home_master_recycler.layoutManager = object : LinearLayoutManager(context) {
// override fun supportsPredictiveItemAnimations(): Boolean {
// return false
// }
//} // GridLayoutManager(context, 1).also { it.supportsPredictiveItemAnimations() }
reloadStored() reloadStored()
loadHomePage(false) loadHomePage(false)
home_loaded.setOnScrollChangeListener(NestedScrollView.OnScrollChangeListener { v, _, scrollY, _, oldScrollY -> /*
home_loaded?.setOnScrollChangeListener(NestedScrollView.OnScrollChangeListener { v, _, scrollY, _, oldScrollY ->
val dy = scrollY - oldScrollY val dy = scrollY - oldScrollY
if (dy > 0) { //check for scroll down if (dy > 0) { //check for scroll down
home_api_fab?.shrink() // hide home_api_fab?.shrink() // hide
@ -1136,29 +1015,25 @@ class HomeFragment : Fragment() {
} }
} }
}) })
*/
// nice profile pic on homepage // nice profile pic on homepage
home_profile_picture_holder?.isVisible = false //home_profile_picture_holder?.isVisible = false
// just in case // just in case
if (isTvSettings()) { if (isTvSettings()) {
home_api_fab?.isVisible = false home_api_fab?.isVisible = false
home_change_api?.isVisible = true
if (isTrueTvSettings()) { if (isTrueTvSettings()) {
home_change_api_loading?.isVisible = true home_change_api_loading?.isVisible = true
home_change_api_loading?.isFocusable = true home_change_api_loading?.isFocusable = true
home_change_api_loading?.isFocusableInTouchMode = true home_change_api_loading?.isFocusableInTouchMode = true
home_change_api?.isFocusable = true
home_change_api?.isFocusableInTouchMode = true
} }
// home_bookmark_select?.isFocusable = true // home_bookmark_select?.isFocusable = true
// home_bookmark_select?.isFocusableInTouchMode = true // home_bookmark_select?.isFocusableInTouchMode = true
} else { } else {
home_api_fab?.isVisible = true home_api_fab?.isVisible = true
home_change_api?.isVisible = false
home_change_api_loading?.isVisible = false home_change_api_loading?.isVisible = false
} }
for (syncApi in OAuth2Apis) { /*for (syncApi in OAuth2Apis) {
val login = syncApi.loginInfo() val login = syncApi.loginInfo()
val pic = login?.profilePicture val pic = login?.profilePicture
if (home_profile_picture?.setImage( if (home_profile_picture?.setImage(
@ -1169,6 +1044,6 @@ class HomeFragment : Fragment() {
home_profile_picture_holder?.isVisible = true home_profile_picture_holder?.isVisible = true
break break
} }
} }*/
} }
} }

View file

@ -4,34 +4,70 @@ import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.FrameLayout import android.widget.FrameLayout
import android.widget.LinearLayout
import android.widget.TextView import android.widget.TextView
import androidx.core.content.ContextCompat
import androidx.core.view.isGone
import androidx.core.view.isVisible
import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListUpdateCallback import androidx.recyclerview.widget.ListUpdateCallback
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
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
import com.lagradost.cloudstream3.HomePageList import com.lagradost.cloudstream3.HomePageList
import com.lagradost.cloudstream3.LoadResponse
import com.lagradost.cloudstream3.R import com.lagradost.cloudstream3.R
import com.lagradost.cloudstream3.SearchResponse
import com.lagradost.cloudstream3.mvvm.Resource
import com.lagradost.cloudstream3.ui.WatchType
import com.lagradost.cloudstream3.ui.result.LinearListLayout import com.lagradost.cloudstream3.ui.result.LinearListLayout
import com.lagradost.cloudstream3.ui.result.ResultViewModel2
import com.lagradost.cloudstream3.ui.result.START_ACTION_RESUME_LATEST
import com.lagradost.cloudstream3.ui.result.setLinearListLayout import com.lagradost.cloudstream3.ui.result.setLinearListLayout
import com.lagradost.cloudstream3.ui.search.SEARCH_ACTION_LOAD
import com.lagradost.cloudstream3.ui.search.SearchClickCallback import com.lagradost.cloudstream3.ui.search.SearchClickCallback
import com.lagradost.cloudstream3.ui.search.SearchFragment.Companion.filterSearchResponse import com.lagradost.cloudstream3.ui.search.SearchFragment.Companion.filterSearchResponse
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTvSettings import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTvSettings
import com.lagradost.cloudstream3.utils.AppUtils.isRecyclerScrollable import com.lagradost.cloudstream3.utils.AppUtils.isRecyclerScrollable
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
import kotlinx.android.synthetic.main.homepage_parent.view.* import kotlinx.android.synthetic.main.homepage_parent.view.*
class LoadClickCallback(
val action: Int = 0,
val view: View,
val position: Int,
val response: LoadResponse
)
class ParentItemAdapter( open class ParentItemAdapter(
private var items: MutableList<HomeViewModel.ExpandableHomepageList>, private var items: MutableList<HomeViewModel.ExpandableHomepageList>,
private val clickCallback: (SearchClickCallback) -> Unit, private val clickCallback: (SearchClickCallback) -> Unit,
private val moreInfoClickCallback: (HomeViewModel.ExpandableHomepageList) -> Unit, private val moreInfoClickCallback: (HomeViewModel.ExpandableHomepageList) -> Unit,
private val expandCallback: ((String) -> Unit)? = null, private val expandCallback: ((String) -> Unit)? = null,
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() { ) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
override fun onCreateViewHolder(parent: ViewGroup, i: Int): ParentViewHolder {
//println("onCreateViewHolder $i")
val layout =
if (isTvSettings()) R.layout.homepage_parent_tv else R.layout.homepage_parent
return ParentViewHolder( return ParentViewHolder(
LayoutInflater.from(parent.context).inflate(layout, parent, false), LayoutInflater.from(parent.context).inflate(
if (isTvSettings()) R.layout.homepage_parent_tv else R.layout.homepage_parent,
parent,
false
),
clickCallback, clickCallback,
moreInfoClickCallback, moreInfoClickCallback,
expandCallback expandCallback
@ -39,8 +75,6 @@ class ParentItemAdapter(
} }
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
//println("onBindViewHolder $position")
when (holder) { when (holder) {
is ParentViewHolder -> { is ParentViewHolder -> {
holder.bind(items[position]) holder.bind(items[position])
@ -84,7 +118,10 @@ class ParentItemAdapter(
val mAdapter = this val mAdapter = this
diffResult.dispatchUpdatesTo(object : ListUpdateCallback { diffResult.dispatchUpdatesTo(object : ListUpdateCallback {
override fun onInserted(position: Int, count: Int) { override fun onInserted(position: Int, count: Int) {
mAdapter.notifyItemRangeInserted(position, count) mAdapter.notifyItemRangeChanged(
position,
count
)//notifyItemRangeInserted(position, count)
} }
override fun onRemoved(position: Int, count: Int) { override fun onRemoved(position: Int, count: Int) {
@ -95,18 +132,28 @@ class ParentItemAdapter(
mAdapter.notifyItemMoved(fromPosition, toPosition) mAdapter.notifyItemMoved(fromPosition, toPosition)
} }
override fun onChanged(position: Int, count: Int, payload: Any?) { override fun onChanged(_position: Int, count: Int, payload: Any?) {
val delta = if (this@ParentItemAdapter is HomeParentItemAdapterPreview) {
headItems
} else {
0
}
val position = _position + delta
// I know kinda messy, what this does is using the update or bind instead of onCreateViewHolder -> bind // I know kinda messy, what this does is using the update or bind instead of onCreateViewHolder -> bind
recyclerView?.apply { recyclerView?.apply {
// this loops every viewHolder in the recycle view and checks the position to see if it is within the update range // 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() val missingUpdates = (position until (position + count)).toMutableSet()
for (i in 0 until itemCount) { for (i in 0 until itemCount) {
val viewHolder = getChildViewHolder(getChildAt(i)) val child = getChildAt(i) ?: continue
val absolutePosition = viewHolder.absoluteAdapterPosition val viewHolder = getChildViewHolder(child) ?: continue
if (viewHolder !is ParentViewHolder) continue
val absolutePosition = viewHolder.bindingAdapterPosition
if (absolutePosition >= position && absolutePosition < position + count) { if (absolutePosition >= position && absolutePosition < position + count) {
val expand = items.getOrNull(absolutePosition) ?: continue val expand = items.getOrNull(absolutePosition - delta) ?: continue
if (viewHolder is ParentViewHolder) {
missingUpdates -= absolutePosition missingUpdates -= absolutePosition
//println("Updating ${viewHolder.title.text} ($absolutePosition $position) -> ${expand.list.name}")
if (viewHolder.title.text == expand.list.name) { if (viewHolder.title.text == expand.list.name) {
viewHolder.update(expand) viewHolder.update(expand)
} else { } else {
@ -114,13 +161,13 @@ class ParentItemAdapter(
} }
} }
} }
}
// just in case some item did not get updated // just in case some item did not get updated
for (i in missingUpdates) { for (i in missingUpdates) {
mAdapter.notifyItemChanged(i, payload) mAdapter.notifyItemChanged(i, payload)
} }
} ?: run { // in case we don't have a nice } ?: run {
// in case we don't have a nice
mAdapter.notifyItemRangeChanged(position, count, payload) mAdapter.notifyItemRangeChanged(position, count, payload)
} }
} }

View file

@ -0,0 +1,581 @@
package com.lagradost.cloudstream3.ui.home
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.LinearLayout
import androidx.appcompat.widget.SearchView
import androidx.core.content.ContextCompat
import androidx.core.view.isGone
import androidx.core.view.isVisible
import androidx.recyclerview.widget.RecyclerView
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
import com.lagradost.cloudstream3.AcraApplication.Companion.getActivity
import com.lagradost.cloudstream3.LoadResponse
import com.lagradost.cloudstream3.R
import com.lagradost.cloudstream3.SearchResponse
import com.lagradost.cloudstream3.mvvm.Resource
import com.lagradost.cloudstream3.ui.WatchType
import com.lagradost.cloudstream3.ui.quicksearch.QuickSearchFragment
import com.lagradost.cloudstream3.ui.result.ResultViewModel2
import com.lagradost.cloudstream3.ui.result.START_ACTION_RESUME_LATEST
import com.lagradost.cloudstream3.ui.search.SEARCH_ACTION_LOAD
import com.lagradost.cloudstream3.ui.search.SEARCH_ACTION_SHOW_METADATA
import com.lagradost.cloudstream3.ui.search.SearchClickCallback
import com.lagradost.cloudstream3.ui.search.SearchHelper
import com.lagradost.cloudstream3.ui.settings.SettingsFragment
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTvSettings
import com.lagradost.cloudstream3.utils.AppUtils.loadSearchResult
import com.lagradost.cloudstream3.utils.DataStoreHelper
import com.lagradost.cloudstream3.utils.SingleSelectionHelper.showBottomDialog
import com.lagradost.cloudstream3.utils.SingleSelectionHelper.showOptionSelectStringRes
import com.lagradost.cloudstream3.utils.UIHelper.fixPaddingStatusbar
import com.lagradost.cloudstream3.utils.UIHelper.setImage
import kotlinx.android.synthetic.main.activity_main_tv.view.*
import kotlinx.android.synthetic.main.fragment_home_head.view.*
import kotlinx.android.synthetic.main.fragment_home_head.view.home_bookmarked_child_recyclerview
import kotlinx.android.synthetic.main.fragment_home_head_tv.view.*
import kotlinx.android.synthetic.main.fragment_home_head_tv.view.home_bookmarked_holder
import kotlinx.android.synthetic.main.fragment_home_head_tv.view.home_plan_to_watch_btt
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
import kotlinx.android.synthetic.main.fragment_home_head_tv.view.home_type_completed_btt
import kotlinx.android.synthetic.main.fragment_home_head_tv.view.home_type_dropped_btt
import kotlinx.android.synthetic.main.fragment_home_head_tv.view.home_type_on_hold_btt
import kotlinx.android.synthetic.main.fragment_home_head_tv.view.home_type_watching_btt
import kotlinx.android.synthetic.main.fragment_home_head_tv.view.home_watch_child_recyclerview
import kotlinx.android.synthetic.main.fragment_home_head_tv.view.home_watch_holder
import kotlinx.android.synthetic.main.fragment_setup_media.*
import java.util.ArrayList
class HomeParentItemAdapterPreview(
items: MutableList<HomeViewModel.ExpandableHomepageList>,
val clickCallback: (SearchClickCallback) -> Unit,
moreInfoClickCallback: (HomeViewModel.ExpandableHomepageList) -> Unit,
expandCallback: ((String) -> Unit)? = null,
private val loadCallback: (LoadClickCallback) -> Unit,
private val loadMoreCallback: (() -> Unit),
private val changeHomePageCallback: ((View) -> Unit),
private val reloadStored: (() -> Unit),
private val loadStoredData: ((Set<WatchType>) -> Unit),
private val searchQueryCallback: ((Pair<Boolean, String>) -> Unit)
) : ParentItemAdapter(items, clickCallback, moreInfoClickCallback, expandCallback) {
private var previewData: Resource<Pair<Boolean, List<LoadResponse>>> = Resource.Loading()
private var resumeWatchingData: List<SearchResponse> = listOf()
private var bookmarkData: Pair<Boolean, List<SearchResponse>> =
false to listOf()
val headItems = 1
private var availableWatchStatusTypes: Pair<Set<WatchType>, Set<WatchType>> =
setOf<WatchType>() to setOf()
fun setAvailableWatchStatusTypes(data: Pair<Set<WatchType>, Set<WatchType>>) {
availableWatchStatusTypes = data
holder?.setAvailableWatchStatusTypes(data)
}
companion object {
private const val VIEW_TYPE_HEADER = 4815
private const val VIEW_TYPE_ITEM = 1623
}
fun setResumeWatchingData(resumeWatching: List<SearchResponse>) {
resumeWatchingData = resumeWatching
holder?.updateResume(resumeWatchingData)
}
fun setPreviewData(preview: Resource<Pair<Boolean, List<LoadResponse>>>) {
previewData = preview
holder?.updatePreview(preview)
//notifyItemChanged(0)
}
fun setBookmarkData(data: Pair<Boolean, List<SearchResponse>>) {
bookmarkData = data
holder?.updateBookmarks(data)
}
override fun getItemViewType(position: Int) = when (position) {
0 -> VIEW_TYPE_HEADER
else -> VIEW_TYPE_ITEM
}
var holder: HeaderViewHolder? = null
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
when (holder) {
is HeaderViewHolder -> {
holder.updatePreview(previewData)
holder.updateResume(resumeWatchingData)
holder.updateBookmarks(bookmarkData)
holder.setAvailableWatchStatusTypes(availableWatchStatusTypes)
}
else -> super.onBindViewHolder(holder, position - 1)
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
return when (viewType) {
VIEW_TYPE_HEADER -> HeaderViewHolder(
LayoutInflater.from(parent.context).inflate(
if (isTvSettings()) R.layout.fragment_home_head_tv else R.layout.fragment_home_head,
parent,
false
),
loadCallback,
loadMoreCallback,
changeHomePageCallback,
clickCallback,
reloadStored,
loadStoredData,
searchQueryCallback
).also {
this.holder = it
}
VIEW_TYPE_ITEM -> super.onCreateViewHolder(parent, viewType)
else -> error("Unhandled viewType=$viewType")
}
}
override fun getItemCount(): Int {
return super.getItemCount() + headItems
}
override fun getItemId(position: Int): Long {
if (position == 0) return previewData.hashCode().toLong()
return super.getItemId(position - headItems)
}
override fun onViewDetachedFromWindow(holder: RecyclerView.ViewHolder) {
when (holder) {
is HeaderViewHolder -> {
holder.onViewDetachedFromWindow()
}
else -> super.onViewDetachedFromWindow(holder)
}
}
override fun onViewAttachedToWindow(holder: RecyclerView.ViewHolder) {
when (holder) {
is HeaderViewHolder -> {
holder.onViewAttachedToWindow()
}
else -> super.onViewAttachedToWindow(holder)
}
}
class HeaderViewHolder
constructor(
itemView: View,
private val clickCallback: ((LoadClickCallback) -> Unit)?,
private val loadMoreCallback: (() -> Unit),
private val changeHomePageCallback: ((View) -> Unit),
private val searchClickCallback: (SearchClickCallback) -> Unit,
private val reloadStored: () -> Unit,
private val loadStoredData: ((Set<WatchType>) -> Unit),
private val searchQueryCallback: ((Pair<Boolean, String>) -> Unit)
) : RecyclerView.ViewHolder(itemView) {
private var previewAdapter: HomeScrollAdapter? = null
private val previewViewpager: ViewPager2? = itemView.home_preview_viewpager
private val previewHeader: LinearLayout? = itemView.home_preview
private val previewCallback: ViewPager2.OnPageChangeCallback =
object : ViewPager2.OnPageChangeCallback() {
override fun onPageSelected(position: Int) {
// home_search?.isIconified = true
//home_search?.isVisible = true
//home_search?.clearFocus()
previewAdapter?.apply {
if (position >= itemCount - 1 && hasMoreItems) {
hasMoreItems = false // dont make two requests
loadMoreCallback()
//homeViewModel.loadMoreHomeScrollResponses()
}
}
previewAdapter?.getItem(position)
?.apply {
//itemView.home_preview_title_holder?.let { parent ->
// TransitionManager.beginDelayedTransition(
// parent,
// ChangeBounds()
// )
//}
itemView.home_preview_description?.isGone =
this.plot.isNullOrBlank()
itemView.home_preview_description?.text =
this.plot ?: ""
itemView.home_preview_text?.text = this.name
itemView.home_preview_change_api?.text = apiName
itemView.home_preview_change_api?.setOnClickListener { view ->
changeHomePageCallback(view)
}
itemView.home_preview_tags?.apply {
removeAllViews()
tags?.forEach { tag ->
val chip = Chip(context)
val chipDrawable =
ChipDrawable.createFromAttributes(
context,
null,
0,
R.style.ChipFilledSemiTransparent
)
chip.setChipDrawable(chipDrawable)
chip.text = tag
chip.isChecked = false
chip.isCheckable = false
chip.isFocusable = false
chip.isClickable = false
addView(chip)
}
}
itemView.home_preview_tags?.isGone =
tags.isNullOrEmpty()
itemView.home_preview_image?.setImage(
posterUrl,
posterHeaders
)
// itemView.home_preview_title?.text = name
itemView.home_preview_play?.setOnClickListener { view ->
clickCallback?.invoke(
LoadClickCallback(
START_ACTION_RESUME_LATEST,
view,
position,
this
)
)
}
itemView.home_preview_info?.setOnClickListener { view ->
clickCallback?.invoke(
LoadClickCallback(0, view, position, this)
)
}
itemView.home_preview_play_btt?.setOnClickListener { view ->
clickCallback?.invoke(
LoadClickCallback(
START_ACTION_RESUME_LATEST,
view,
position,
this
)
)
}
itemView.home_preview_info_btt?.setOnClickListener { view ->
clickCallback?.invoke(
LoadClickCallback(0, view, position, this)
)
}
itemView.home_preview_hidden_next_focus?.setOnFocusChangeListener { _, hasFocus ->
if (hasFocus) {
previewViewpager?.apply {
setCurrentItem(currentItem + 1, true)
}
itemView.home_preview_info_btt?.requestFocus()
}
}
itemView.home_preview_hidden_prev_focus?.setOnFocusChangeListener { _, hasFocus ->
if (hasFocus) {
previewViewpager?.apply {
if (currentItem <= 0) {
nav_rail_view?.menu?.getItem(0)?.actionView?.requestFocus()
} else {
setCurrentItem(currentItem - 1, true)
itemView.home_preview_play_btt?.requestFocus()
}
}
}
}
// very ugly code, but I dont care
val watchType =
DataStoreHelper.getResultWatchState(this.getId())
itemView.home_preview_bookmark?.setText(watchType.stringRes)
itemView.home_preview_bookmark?.setCompoundDrawablesWithIntrinsicBounds(
null,
ContextCompat.getDrawable(
itemView.home_preview_bookmark.context,
watchType.iconRes
),
null,
null
)
itemView.home_preview_bookmark?.setOnClickListener { fab ->
fab.context.getActivity()?.showBottomDialog(
WatchType.values()
.map { fab.context.getString(it.stringRes) }
.toList(),
DataStoreHelper.getResultWatchState(this.getId()).ordinal,
fab.context.getString(R.string.action_add_to_bookmarks),
showApply = false,
{}) {
val newValue = WatchType.values()[it]
itemView.home_preview_bookmark?.setCompoundDrawablesWithIntrinsicBounds(
null,
ContextCompat.getDrawable(
itemView.home_preview_bookmark.context,
newValue.iconRes
),
null,
null
)
itemView.home_preview_bookmark?.setText(newValue.stringRes)
ResultViewModel2.updateWatchStatus(
this,
newValue
)
reloadStored()
}
}
}
}
}
private var resumeAdapter: HomeChildItemAdapter? = null
private var resumeHolder: View? = itemView.home_watch_holder
private var resumeRecyclerView: RecyclerView? = itemView.home_watch_child_recyclerview
private var bookmarkHolder: View? = itemView.home_bookmarked_holder
private var bookmarkAdapter: HomeChildItemAdapter? = null
private var bookmarkRecyclerView: RecyclerView? =
itemView.home_bookmarked_child_recyclerview
fun onViewDetachedFromWindow() {
previewViewpager?.unregisterOnPageChangeCallback(previewCallback)
}
fun onViewAttachedToWindow() {
previewViewpager?.registerOnPageChangeCallback(previewCallback)
}
private val toggleList = listOf(
Pair(itemView.home_type_watching_btt, WatchType.WATCHING),
Pair(itemView.home_type_completed_btt, WatchType.COMPLETED),
Pair(itemView.home_type_dropped_btt, WatchType.DROPPED),
Pair(itemView.home_type_on_hold_btt, WatchType.ONHOLD),
Pair(itemView.home_plan_to_watch_btt, WatchType.PLANTOWATCH),
)
init {
previewViewpager?.apply {
if (!isTvSettings())
setPageTransformer(HomeScrollTransformer())
else
setPageTransformer(null)
if (adapter == null)
adapter = HomeScrollAdapter(
if (isTvSettings()) R.layout.home_scroll_view_tv else R.layout.home_scroll_view,
if (isTvSettings()) true else null
)
}
previewAdapter = previewViewpager?.adapter as? HomeScrollAdapter?
previewViewpager?.registerOnPageChangeCallback(previewCallback)
if (resumeAdapter == null) {
resumeRecyclerView?.adapter = HomeChildItemAdapter(
ArrayList(),
nextFocusUp = itemView.nextFocusUpId,
nextFocusDown = itemView.nextFocusDownId
) { callback ->
if (callback.action != SEARCH_ACTION_SHOW_METADATA) {
searchClickCallback(callback)
return@HomeChildItemAdapter
}
callback.view.context?.getActivity()?.showOptionSelectStringRes(
callback.view,
callback.card.posterUrl,
listOf(
R.string.action_open_watching,
R.string.action_remove_watching
),
listOf(
R.string.action_open_play,
R.string.action_open_watching,
R.string.action_remove_watching
)
) { (isTv, actionId) ->
when (actionId + if (isTv) 0 else 1) {
// play
0 -> {
searchClickCallback.invoke(
SearchClickCallback(
START_ACTION_RESUME_LATEST,
callback.view,
-1,
callback.card
)
)
reloadStored()
}
//info
1 -> {
searchClickCallback(
SearchClickCallback(
SEARCH_ACTION_LOAD,
callback.view,
-1,
callback.card
)
)
reloadStored()
}
// remove
2 -> {
val card = callback.card
if (card is DataStoreHelper.ResumeWatchingResult) {
DataStoreHelper.removeLastWatched(card.parentId)
reloadStored()
}
}
}
}
}
}
resumeAdapter = resumeRecyclerView?.adapter as? HomeChildItemAdapter
if (bookmarkAdapter == null) {
bookmarkRecyclerView?.adapter = HomeChildItemAdapter(
ArrayList(),
nextFocusUp = itemView.nextFocusUpId,
nextFocusDown = itemView.nextFocusDownId
) { callback ->
if (callback.action != SEARCH_ACTION_SHOW_METADATA) {
searchClickCallback(callback)
return@HomeChildItemAdapter
}
callback.view.context?.getActivity()?.showOptionSelectStringRes(
callback.view,
callback.card.posterUrl,
listOf(
R.string.action_open_watching,
R.string.action_remove_from_bookmarks,
),
listOf(
R.string.action_open_play,
R.string.action_open_watching,
R.string.action_remove_from_bookmarks
)
) { (isTv, actionId) ->
when (actionId + if (isTv) 0 else 1) { // play
0 -> {
searchClickCallback.invoke(
SearchClickCallback(
START_ACTION_RESUME_LATEST,
callback.view,
-1,
callback.card
)
)
reloadStored()
}
1 -> { // info
searchClickCallback(
SearchClickCallback(
SEARCH_ACTION_LOAD,
callback.view,
-1,
callback.card
)
)
reloadStored()
}
2 -> { // remove
DataStoreHelper.setResultWatchState(
callback.card.id,
WatchType.NONE.internalId
)
reloadStored()
}
}
}
}
}
bookmarkAdapter = bookmarkRecyclerView?.adapter as? HomeChildItemAdapter
for ((chip, watch) in toggleList) {
chip?.isChecked = false
chip?.setOnCheckedChangeListener { _, isChecked ->
if (isChecked) {
loadStoredData(
setOf(watch)
// If we filter all buttons then two can be checked at the same time
// Revert this if you want to go back to multi selection
// toggleList.filter { it.first?.isChecked == true }.map { it.second }.toSet()
)
}
// Else if all are unchecked -> Do not load data
else if (toggleList.all { it.first?.isChecked != true }) {
loadStoredData(emptySet())
}
}
}
itemView.home_search?.context?.fixPaddingStatusbar(itemView.home_search)
itemView.home_search?.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
override fun onQueryTextSubmit(query: String): Boolean {
searchQueryCallback.invoke(false to query)
//QuickSearchFragment.pushSearch(activity, query, currentApiName?.let { arrayOf(it) }
return true
}
override fun onQueryTextChange(newText: String): Boolean {
searchQueryCallback.invoke(true to newText)
//searchViewModel.quickSearch(newText)
return true
}
})
}
fun updatePreview(preview: Resource<Pair<Boolean, List<LoadResponse>>>) {
when (preview) {
is Resource.Success -> {
previewHeader?.isVisible = true
if (true != previewAdapter?.setItems(
preview.value.second,
preview.value.first
)
) {
previewViewpager?.setCurrentItem(0, false)
}
}
else -> {
previewHeader?.isVisible = false
previewAdapter?.setItems(listOf(), false)
previewViewpager?.setCurrentItem(0, false)
}
}
}
fun updateResume(resumeWatching: List<SearchResponse>) {
resumeHolder?.isVisible = resumeWatching.isNotEmpty()
resumeAdapter?.updateList(resumeWatching)
}
fun updateBookmarks(data: Pair<Boolean, List<SearchResponse>>) {
bookmarkHolder?.isVisible = true // data.first
bookmarkAdapter?.updateList(data.second)
}
fun setAvailableWatchStatusTypes(availableWatchStatusTypes: Pair<Set<WatchType>, Set<WatchType>>) {
for ((chip, watch) in toggleList) {
chip?.apply {
isVisible = availableWatchStatusTypes.second.contains(watch)
isChecked = availableWatchStatusTypes.first.contains(watch)
}
}
}
}
}

View file

@ -4,16 +4,22 @@ import android.content.res.Configuration
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.annotation.LayoutRes
import androidx.core.view.isGone import androidx.core.view.isGone
import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.lagradost.cloudstream3.LoadResponse import com.lagradost.cloudstream3.LoadResponse
import com.lagradost.cloudstream3.R import com.lagradost.cloudstream3.R
import com.lagradost.cloudstream3.utils.UIHelper.setImage import com.lagradost.cloudstream3.utils.UIHelper.setImage
import kotlinx.android.synthetic.main.fragment_home_head_tv.*
import kotlinx.android.synthetic.main.fragment_home_head_tv.view.*
import kotlinx.android.synthetic.main.home_scroll_view.view.* import kotlinx.android.synthetic.main.home_scroll_view.view.*
class HomeScrollAdapter : RecyclerView.Adapter<RecyclerView.ViewHolder>() { class HomeScrollAdapter(
@LayoutRes val layout: Int = R.layout.home_scroll_view,
private val forceHorizontalPosters: Boolean? = null
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
private var items: MutableList<LoadResponse> = mutableListOf() private var items: MutableList<LoadResponse> = mutableListOf()
var hasMoreItems: Boolean = false var hasMoreItems: Boolean = false
@ -40,7 +46,8 @@ class HomeScrollAdapter : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
return CardViewHolder( return CardViewHolder(
LayoutInflater.from(parent.context).inflate(R.layout.home_scroll_view, parent, false), LayoutInflater.from(parent.context).inflate(layout, parent, false),
forceHorizontalPosters
) )
} }
@ -55,13 +62,15 @@ class HomeScrollAdapter : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
class CardViewHolder class CardViewHolder
constructor( constructor(
itemView: View, itemView: View,
private val forceHorizontalPosters: Boolean? = null
) : ) :
RecyclerView.ViewHolder(itemView) { RecyclerView.ViewHolder(itemView) {
fun bind(card: LoadResponse) { fun bind(card: LoadResponse) {
card.apply { card.apply {
val isHorizontal = val isHorizontal =
itemView.resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE (forceHorizontalPosters == true) || ((forceHorizontalPosters != false) && itemView.resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE)
val posterUrl = if (isHorizontal) backgroundPosterUrl ?: posterUrl else posterUrl val posterUrl = if (isHorizontal) backgroundPosterUrl ?: posterUrl else posterUrl
?: backgroundPosterUrl ?: backgroundPosterUrl
itemView.home_scroll_preview_tags?.text = tags?.joinToString("") ?: "" itemView.home_scroll_preview_tags?.text = tags?.joinToString("") ?: ""

View file

@ -128,6 +128,7 @@ class HomeViewModel : ViewModel() {
currentWatchTypes.remove(WatchType.NONE) currentWatchTypes.remove(WatchType.NONE)
if (currentWatchTypes.size <= 0) { if (currentWatchTypes.size <= 0) {
_availableWatchStatusTypes.postValue(setOf<WatchType>() to setOf())
_bookmarks.postValue(Pair(false, ArrayList())) _bookmarks.postValue(Pair(false, ArrayList()))
return@launchSafe return@launchSafe
} }

View file

@ -921,8 +921,6 @@ open class ResultFragment : ResultTrailerPlayer() {
} }
result_tag?.removeAllViews()
d.comingSoon.let { soon -> d.comingSoon.let { soon ->
result_coming_soon?.isVisible = soon result_coming_soon?.isVisible = soon
result_data_holder?.isGone = soon result_data_holder?.isGone = soon
@ -931,6 +929,7 @@ open class ResultFragment : ResultTrailerPlayer() {
val tags = d.tags val tags = d.tags
result_tag_holder?.isVisible = tags.isNotEmpty() result_tag_holder?.isVisible = tags.isNotEmpty()
result_tag?.apply { result_tag?.apply {
removeAllViews()
tags.forEach { tag -> tags.forEach { tag ->
val chip = Chip(context) val chip = Chip(context)
val chipDrawable = ChipDrawable.createFromAttributes( val chipDrawable = ChipDrawable.createFromAttributes(

View file

@ -20,7 +20,12 @@ const val SEARCH_ACTION_SHOW_METADATA = 1
const val SEARCH_ACTION_PLAY_FILE = 2 const val SEARCH_ACTION_PLAY_FILE = 2
const val SEARCH_ACTION_FOCUSED = 4 const val SEARCH_ACTION_FOCUSED = 4
class SearchClickCallback(val action: Int, val view: View, val position : Int, val card: SearchResponse) class SearchClickCallback(
val action: Int,
val view: View,
val position: Int,
val card: SearchResponse
)
class SearchAdapter( class SearchAdapter(
private val cardList: MutableList<SearchResponse>, private val cardList: MutableList<SearchResponse>,
@ -30,7 +35,8 @@ class SearchAdapter(
var hasNext: Boolean = false var hasNext: Boolean = false
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
val layout = if(parent.context.IsBottomLayout()) R.layout.search_result_grid_expanded else R.layout.search_result_grid val layout =
if (parent.context.IsBottomLayout()) R.layout.search_result_grid_expanded else R.layout.search_result_grid
return CardViewHolder( return CardViewHolder(
LayoutInflater.from(parent.context).inflate(layout, parent, false), LayoutInflater.from(parent.context).inflate(layout, parent, false),
clickCallback, clickCallback,
@ -71,7 +77,8 @@ class SearchAdapter(
val cardView: ImageView = itemView.imageView val cardView: ImageView = itemView.imageView
private val compactView = false//itemView.context.getGridIsCompact() private val compactView = false//itemView.context.getGridIsCompact()
private val coverHeight: Int = if (compactView) 80.toPx else (resView.itemWidth / 0.68).roundToInt() private val coverHeight: Int =
if (compactView) 80.toPx else (resView.itemWidth / 0.68).roundToInt()
fun bind(card: SearchResponse, position: Int) { fun bind(card: SearchResponse, position: Int) {
if (!compactView) { if (!compactView) {
@ -88,7 +95,10 @@ class SearchAdapter(
} }
} }
class SearchResponseDiffCallback(private val oldList: List<SearchResponse>, private val newList: List<SearchResponse>) : class SearchResponseDiffCallback(
private val oldList: List<SearchResponse>,
private val newList: List<SearchResponse>
) :
DiffUtil.Callback() { DiffUtil.Callback() {
override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int) = override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int) =
oldList[oldItemPosition].name == newList[newItemPosition].name oldList[oldItemPosition].name == newList[newItemPosition].name

View file

@ -44,6 +44,7 @@ import com.lagradost.cloudstream3.ui.home.HomeFragment.Companion.loadHomepageLis
import com.lagradost.cloudstream3.ui.home.HomeFragment.Companion.updateChips import com.lagradost.cloudstream3.ui.home.HomeFragment.Companion.updateChips
import com.lagradost.cloudstream3.ui.home.ParentItemAdapter import com.lagradost.cloudstream3.ui.home.ParentItemAdapter
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTrueTvSettings import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTrueTvSettings
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTvSettings
import com.lagradost.cloudstream3.utils.Coroutines.main import com.lagradost.cloudstream3.utils.Coroutines.main
import com.lagradost.cloudstream3.utils.DataStore.getKey import com.lagradost.cloudstream3.utils.DataStore.getKey
import com.lagradost.cloudstream3.utils.DataStore.setKey import com.lagradost.cloudstream3.utils.DataStore.setKey
@ -93,7 +94,11 @@ class SearchFragment : Fragment() {
activity?.window?.setSoftInputMode( activity?.window?.setSoftInputMode(
WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE
) )
return inflater.inflate(R.layout.fragment_search, container, false) return inflater.inflate(
if (isTvSettings()) R.layout.fragment_search_tv else R.layout.fragment_search,
container,
false
)
} }
private fun fixGrid() { private fun fixGrid() {

View file

@ -99,7 +99,8 @@ object SingleSelectionHelper {
val textView = dialog.text1//.findViewById<TextView>(R.id.text1)!! val textView = dialog.text1//.findViewById<TextView>(R.id.text1)!!
val applyButton = dialog.apply_btt//.findViewById<TextView>(R.id.apply_btt) val applyButton = dialog.apply_btt//.findViewById<TextView>(R.id.apply_btt)
val cancelButton = dialog.cancel_btt//findViewById<TextView>(R.id.cancel_btt) val cancelButton = dialog.cancel_btt//findViewById<TextView>(R.id.cancel_btt)
val applyHolder = dialog.apply_btt_holder//.findViewById<LinearLayout>(R.id.apply_btt_holder) val applyHolder =
dialog.apply_btt_holder//.findViewById<LinearLayout>(R.id.apply_btt_holder)
applyHolder?.isVisible = realShowApply applyHolder?.isVisible = realShowApply
if (!realShowApply) { if (!realShowApply) {
@ -249,6 +250,17 @@ object SingleSelectionHelper {
) )
} }
fun showBottomDialog(
items: List<String>,
selectedIndex: Int,
name: String,
showApply: Boolean,
dismissCallback: () -> Unit,
callback: (Int) -> Unit,
) {
}
/** Only for a low amount of items */ /** Only for a low amount of items */
fun Activity?.showBottomDialog( fun Activity?.showBottomDialog(
items: List<String>, items: List<String>,

View file

@ -1,5 +1,5 @@
<vector android:autoMirrored="true" android:height="24dp" <vector android:autoMirrored="true" android:height="24dp"
android:tint="?attr/white" android:viewportHeight="24" android:tint="?attr/white" android:viewportHeight="24"
android:viewportWidth="24" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android"> android:viewportWidth="24" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M15.41,16.59L10.83,12l4.58,-4.59L14,6l-6,6 6,6 1.41,-1.41z"/> <path android:fillColor="@android:color/white" android:pathData="M13.3,17.3 L8.7,12.7Q8.55,12.55 8.488,12.375Q8.425,12.2 8.425,12Q8.425,11.8 8.488,11.625Q8.55,11.45 8.7,11.3L13.3,6.7Q13.575,6.425 14,6.425Q14.425,6.425 14.7,6.7Q14.975,6.975 14.975,7.4Q14.975,7.825 14.7,8.1L10.8,12L14.7,15.9Q14.975,16.175 14.975,16.6Q14.975,17.025 14.7,17.3Q14.425,17.575 14,17.575Q13.575,17.575 13.3,17.3Z"/>
</vector> </vector>

View file

@ -1,5 +1,11 @@
<vector android:autoMirrored="true" android:height="24dp" <vector android:autoMirrored="true"
android:tint="?attr/white" android:viewportHeight="24" android:height="24dp"
android:viewportWidth="24" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android"> android:tint="?attr/white"
<path android:fillColor="@android:color/white" android:pathData="M8.59,16.59L13.17,12 8.59,7.41 10,6l6,6 -6,6 -1.41,-1.41z"/> android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp"
xmlns:android="http://schemas.android.com/apk/res/android">
<path
android:fillColor="@android:color/white"
android:pathData="M8.7,17.3Q8.425,17.025 8.425,16.6Q8.425,16.175 8.7,15.9L12.6,12L8.7,8.1Q8.425,7.825 8.425,7.4Q8.425,6.975 8.7,6.7Q8.975,6.425 9.4,6.425Q9.825,6.425 10.1,6.7L14.7,11.3Q14.85,11.45 14.913,11.625Q14.975,11.8 14.975,12Q14.975,12.2 14.913,12.375Q14.85,12.55 14.7,12.7L10.1,17.3Q9.825,17.575 9.4,17.575Q8.975,17.575 8.7,17.3Z" />
</vector> </vector>

View file

@ -14,10 +14,11 @@
<com.google.android.material.navigationrail.NavigationRailView <com.google.android.material.navigationrail.NavigationRailView
android:id="@+id/nav_rail_view" android:id="@+id/nav_rail_view"
android:layout_width="62dp" android:layout_width="@dimen/navbar_width"
android:layout_height="match_parent" android:layout_height="match_parent"
android:background="?attr/primaryGrayBackground" android:background="?attr/primaryGrayBackground"
app:itemIconTint="@color/item_select_color" app:itemIconTint="@color/item_select_color"
android:descendantFocusability="afterDescendants"
app:itemTextColor="@color/item_select_color" app:itemTextColor="@color/item_select_color"
app:labelVisibilityMode="unlabeled" app:labelVisibilityMode="unlabeled"

View file

@ -9,55 +9,55 @@
android:paddingTop="0dp"> android:paddingTop="0dp">
<androidx.constraintlayout.widget.ConstraintLayout <androidx.constraintlayout.widget.ConstraintLayout
android:layout_height="match_parent" android:layout_width="match_parent"
android:layout_width="match_parent"> android:layout_height="match_parent">
<androidx.fragment.app.FragmentContainerView <androidx.fragment.app.FragmentContainerView
android:id="@+id/nav_host_fragment" android:id="@+id/nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment" android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="0dp" android:layout_width="match_parent"
android:layout_height="0dp" android:layout_height="match_parent"
app:defaultNavHost="true" app:defaultNavHost="true"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toRightOf="parent"
app:layout_constraintBottom_toTopOf="@id/cast_mini_controller_holder" app:layout_constraintBottom_toTopOf="@id/cast_mini_controller_holder"
app:navGraph="@navigation/mobile_navigation" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/nav_rail_view" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent" /> app:navGraph="@navigation/mobile_navigation" />
<com.google.android.material.navigationrail.NavigationRailView <com.google.android.material.navigationrail.NavigationRailView
android:layout_width="62dp"
android:layout_height="match_parent"
android:id="@+id/nav_rail_view" android:id="@+id/nav_rail_view"
android:background="?attr/primaryGrayBackground" android:layout_width="62dp"
app:itemTextColor="@color/item_select_color"
app:itemIconTint="@color/item_select_color"
app:menuGravity="center" android:layout_height="match_parent"
android:background="?attr/primaryGrayBackground"
android:descendantFocusability="afterDescendants"
app:itemIconTint="@color/item_select_color"
app:itemTextColor="@color/item_select_color"
app:labelVisibilityMode="unlabeled"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
app:labelVisibilityMode="unlabeled" app:menu="@menu/bottom_nav_menu"
app:menu="@menu/bottom_nav_menu"> app:menuGravity="center">
</com.google.android.material.navigationrail.NavigationRailView> </com.google.android.material.navigationrail.NavigationRailView>
<LinearLayout <LinearLayout
app:layout_constraintStart_toEndOf="@+id/nav_rail_view" android:id="@+id/cast_mini_controller_holder"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
tools:layout_height="100dp"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:id="@+id/cast_mini_controller_holder"> app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/nav_rail_view"
tools:layout_height="100dp">
<!--com.google.android.gms.cast.framework.media.widget.MiniControllerFragment--> <!--com.google.android.gms.cast.framework.media.widget.MiniControllerFragment-->
<fragment <fragment
app:customCastBackgroundColor="?attr/primaryGrayBackground"
app:castControlButtons="@array/cast_mini_controller_control_buttons"
android:id="@+id/cast_mini_controller" android:id="@+id/cast_mini_controller"
class="com.lagradost.cloudstream3.ui.MyMiniControllerFragment"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:visibility="gone" android:visibility="gone"
class="com.lagradost.cloudstream3.ui.MyMiniControllerFragment" app:castControlButtons="@array/cast_mini_controller_control_buttons"
app:customCastBackgroundColor="?attr/primaryGrayBackground"
tools:ignore="FragmentTagUsage" /> tools:ignore="FragmentTagUsage" />
</LinearLayout> </LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -153,435 +153,14 @@
android:textColor="?attr/textColor" /> android:textColor="?attr/textColor" />
</LinearLayout> </LinearLayout>
<androidx.core.widget.NestedScrollView
android:id="@+id/home_loaded"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/primaryBlackBackground"
android:visibility="gone"
tools:visibility="visible">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<View
android:id="@+id/home_statusbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/primaryGrayBackground" />
<FrameLayout
android:id="@+id/home_settings_bar"
android:layout_width="match_parent"
android:layout_height="70dp"
android:background="?attr/primaryGrayBackground"
android:visibility="gone">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:paddingStart="10dp"
android:paddingTop="10dp"
android:paddingEnd="10dp"
android:paddingBottom="10dp">
<androidx.cardview.widget.CardView
android:id="@+id/home_profile_picture_holder"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_gravity="center_vertical"
android:layout_marginEnd="10dp"
app:cardCornerRadius="100dp">
<ImageView
android:id="@+id/home_profile_picture"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
tools:ignore="ContentDescription" />
</androidx.cardview.widget.CardView>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="40dp"
android:layout_gravity="center_vertical"
android:background="@drawable/search_background"
android:visibility="visible">
<androidx.appcompat.widget.SearchView
android:id="@+id/home_search2"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center_vertical"
android:iconifiedByDefault="false"
android:paddingStart="-10dp"
app:iconifiedByDefault="false"
app:queryBackground="@color/transparent"
app:queryHint="@string/search_hint"
app:searchIcon="@drawable/search_icon"
tools:ignore="RtlSymmetry" />
</FrameLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical"
android:visibility="gone">
<TextView
android:id="@+id/home_provider_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center_vertical"
android:textColor="?attr/textColor"
android:textSize="20sp"
tools:text="Hello World" />
<TextView
android:id="@+id/home_provider_meta_info"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center_vertical"
android:textColor="?attr/grayTextColor"
android:textSize="14sp"
tools:text="Hello World" />
</LinearLayout>
</LinearLayout>
<!--
<ImageView
android:nextFocusDown="@id/home_main_poster_recyclerview"
android:nextFocusUp="@id/nav_rail_view"
android:nextFocusLeft="@id/nav_rail_view"
android:id="@+id/home_change_api"
android:layout_margin="10dp"
android:layout_gravity="center|end"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:src="@drawable/ic_baseline_keyboard_arrow_down_24"
android:layout_width="30dp"
android:layout_height="30dp"
android:contentDescription="@string/home_change_provider_img_des">
<requestFocus />
</ImageView>-->
</FrameLayout>
<!--https://www.digitalocean.com/community/tutorials/android-viewpager-example-tutorial-->
<FrameLayout
android:id="@+id/home_preview"
android:layout_width="match_parent"
android:layout_height="500dp"
android:visibility="gone"
tools:visibility="visible">
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/home_preview_viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
</androidx.viewpager2.widget.ViewPager2>
<ImageView
android:id="@+id/home_preview_image"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:alpha="0.8"
android:scaleType="centerCrop"
android:visibility="gone"
tools:src="@drawable/example_poster" />
<LinearLayout
android:id="@+id/home_padding"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<androidx.appcompat.widget.SearchView
android:id="@+id/home_search"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="start"
android:editTextColor="@color/white"
android:gravity="start"
android:iconifiedByDefault="true"
android:textColor="@color/white"
android:textColorHint="@color/white"
app:iconifiedByDefault="true"
app:queryBackground="@color/transparent"
app:queryHint="@string/search"
app:closeIcon="@drawable/ic_baseline_close_24"
app:searchIcon="@drawable/search_icon"
tools:ignore="RtlSymmetry" />
</LinearLayout>
<!--
<TextView
android:visibility="gone"
android:id="@+id/test_search"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:layout_gravity="start"
android:gravity="center"
android:textSize="20dp"
android:layout_margin="20dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/search"
android:textColor="@color/white"
app:drawableLeftCompat="@drawable/search_icon"
app:tint="@color/white" />
-->
<LinearLayout
android:id="@+id/home_preview_title_holder"
android:layout_width="match_parent"
android:layout_height="100dp"
android:layout_gravity="bottom"
android:gravity="center"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:orientation="horizontal"
android:padding="20dp">
<TextView
android:id="@+id/home_preview_bookmark"
android:layout_width="70dp"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginStart="25dp"
android:layout_marginEnd="25dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:gravity="center"
android:text="@string/none"
android:textColor="?attr/white"
app:drawableTint="?attr/white"
app:drawableTopCompat="@drawable/ic_baseline_add_24"
app:tint="?attr/white" />
<com.google.android.material.button.MaterialButton
android:id="@+id/home_preview_play"
style="@style/WhiteButton"
android:layout_width="wrap_content"
android:layout_gravity="center"
android:text="@string/home_play"
app:icon="@drawable/ic_baseline_play_arrow_24" />
<TextView
android:id="@+id/home_preview_info"
android:layout_width="70dp"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginStart="25dp"
android:layout_marginEnd="25dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:gravity="center"
android:text="@string/home_info"
android:textColor="?attr/white"
app:drawableTint="?attr/white"
app:drawableTopCompat="@drawable/ic_outline_info_24"
app:tint="?attr/white" />
</LinearLayout>
</LinearLayout>
</FrameLayout>
<View
android:id="@+id/home_fix_padding"
android:layout_width="match_parent"
android:layout_height="0dp"></View>
<!--
All padding in home_watch_holder is determined in runtime
This is because the home poster can be invisible which forces
us to take the status bar space into account
-->
<LinearLayout
android:id="@+id/home_watch_holder"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:visibility="gone"
tools:visibility="visible">
<FrameLayout
android:id="@+id/home_watch_child_more_info"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:foreground="?android:attr/selectableItemBackgroundBorderless"
android:nextFocusLeft="@id/nav_rail_view"
android:nextFocusDown="@id/home_watch_child_recyclerview"
android:padding="12dp">
<TextView
android:id="@+id/home_watch_parent_item_title"
style="@style/WatchHeaderText"
android:layout_gravity="center_vertical"
android:text="@string/continue_watching" />
<ImageView
android:layout_width="30dp"
android:layout_height="match_parent"
android:layout_gravity="end|center_vertical"
android:layout_marginEnd="5dp"
android:contentDescription="@string/home_more_info"
android:src="@drawable/ic_baseline_arrow_forward_24"
app:tint="?attr/textColor" />
</FrameLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/home_watch_child_recyclerview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:clipToPadding="false"
android:descendantFocusability="afterDescendants"
android:orientation="horizontal"
android:paddingHorizontal="5dp"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
tools:listitem="@layout/home_result_grid" />
</LinearLayout>
<LinearLayout
android:id="@+id/home_bookmarked_holder"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:visibility="gone"
tools:visibility="visible">
<FrameLayout
android:id="@+id/home_bookmarked_child_more_info"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:foreground="?android:attr/selectableItemBackgroundBorderless"
android:nextFocusLeft="@id/nav_rail_view"
android:nextFocusUp="@id/home_watch_child_recyclerview"
android:nextFocusForward="@id/home_bookmarked_child_recyclerview"
android:paddingStart="12dp"
android:paddingTop="5dp"
android:paddingEnd="12dp"
android:paddingBottom="5dp">
<HorizontalScrollView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="50dp"
android:fadingEdge="horizontal"
android:requiresFadingEdge="horizontal">
<com.google.android.material.chip.ChipGroup
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:singleSelection="true">
<com.google.android.material.chip.Chip
android:id="@+id/home_type_watching_btt"
style="@style/ChipFilled"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:nextFocusLeft="@id/nav_rail_view"
android:nextFocusRight="@id/home_plan_to_watch_btt"
android:text="@string/type_watching" />
<com.google.android.material.chip.Chip
android:id="@+id/home_plan_to_watch_btt"
style="@style/ChipFilled"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:nextFocusLeft="@id/home_type_watching_btt"
android:nextFocusRight="@id/home_type_on_hold_btt"
android:text="@string/type_plan_to_watch" />
<com.google.android.material.chip.Chip
android:id="@+id/home_type_on_hold_btt"
style="@style/ChipFilled"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:nextFocusLeft="@id/home_plan_to_watch_btt"
android:nextFocusRight="@id/home_type_dropped_btt"
android:text="@string/type_on_hold" />
<com.google.android.material.chip.Chip
android:id="@+id/home_type_dropped_btt"
style="@style/ChipFilled"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:nextFocusLeft="@id/home_type_on_hold_btt"
android:nextFocusRight="@id/home_type_completed_btt"
android:text="@string/type_dropped" />
<com.google.android.material.chip.Chip
android:id="@+id/home_type_completed_btt"
style="@style/ChipFilled"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:nextFocusLeft="@id/home_type_dropped_btt"
android:text="@string/type_completed" />
</com.google.android.material.chip.ChipGroup>
</HorizontalScrollView>
<ImageView
android:layout_width="30dp"
android:layout_height="match_parent"
android:layout_gravity="end|center_vertical"
android:layout_marginEnd="5dp"
android:contentDescription="@string/home_more_info"
android:src="@drawable/ic_baseline_arrow_forward_24"
app:tint="?attr/textColor" />
</FrameLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/home_bookmarked_child_recyclerview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:clipToPadding="false"
android:descendantFocusability="afterDescendants"
android:orientation="horizontal"
android:paddingHorizontal="5dp"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
tools:listitem="@layout/home_result_grid" />
</LinearLayout>
<androidx.recyclerview.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
android:id="@+id/home_master_recycler" android:id="@+id/home_master_recycler"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="wrap_content"
android:descendantFocusability="afterDescendants" android:descendantFocusability="afterDescendants"
android:nextFocusLeft="@id/nav_rail_view" android:nextFocusLeft="@id/nav_rail_view"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
tools:listitem="@layout/homepage_parent" /> tools:listitem="@layout/homepage_parent" />
</LinearLayout>
</androidx.core.widget.NestedScrollView>
<com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton <com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
android:id="@+id/home_api_fab" android:id="@+id/home_api_fab"

View file

@ -0,0 +1,259 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout android:orientation="vertical"
android:id="@+id/home_preview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/primaryBlackBackground"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="500dp">
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/home_preview_viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
</androidx.viewpager2.widget.ViewPager2>
<ImageView
android:id="@+id/home_preview_image"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:alpha="0.8"
android:scaleType="centerCrop"
android:visibility="gone"
tools:src="@drawable/example_poster" />
<LinearLayout
android:id="@+id/home_padding"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<androidx.appcompat.widget.SearchView
android:id="@+id/home_search"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="start"
android:editTextColor="@color/white"
android:gravity="start"
android:iconifiedByDefault="true"
android:textColor="@color/white"
android:textColorHint="@color/white"
app:iconifiedByDefault="true"
app:queryBackground="@color/transparent"
app:queryHint="@string/search_hint"
app:closeIcon="@drawable/ic_baseline_close_24"
app:searchIcon="@drawable/search_icon"
tools:ignore="RtlSymmetry" />
</LinearLayout>
<!--
<TextView
android:visibility="gone"
android:id="@+id/test_search"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:layout_gravity="start"
android:gravity="center"
android:textSize="20dp"
android:layout_margin="20dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/search"
android:textColor="@color/white"
app:drawableLeftCompat="@drawable/search_icon"
app:tint="@color/white" />
-->
<LinearLayout
android:id="@+id/home_preview_title_holder"
android:layout_width="match_parent"
android:layout_height="100dp"
android:layout_gravity="bottom"
android:gravity="center"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:orientation="horizontal"
android:padding="20dp">
<TextView
android:id="@+id/home_preview_bookmark"
android:layout_width="70dp"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginStart="25dp"
android:layout_marginEnd="25dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:gravity="center"
android:text="@string/none"
android:textColor="?attr/white"
app:drawableTint="?attr/white"
app:drawableTopCompat="@drawable/ic_baseline_add_24"
app:tint="?attr/white" />
<com.google.android.material.button.MaterialButton
android:id="@+id/home_preview_play"
style="@style/WhiteButton"
android:layout_width="wrap_content"
android:layout_gravity="center"
android:text="@string/home_play"
app:icon="@drawable/ic_baseline_play_arrow_24" />
<TextView
android:id="@+id/home_preview_info"
android:layout_width="70dp"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginStart="25dp"
android:layout_marginEnd="25dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:gravity="center"
android:text="@string/home_info"
android:textColor="?attr/white"
app:drawableTint="?attr/white"
app:drawableTopCompat="@drawable/ic_outline_info_24"
app:tint="?attr/white" />
</LinearLayout>
</LinearLayout>
</FrameLayout>
<LinearLayout
android:id="@+id/home_watch_holder"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:visibility="gone"
tools:visibility="visible">
<TextView
android:id="@+id/home_watch_parent_item_title"
style="@style/WatchHeaderText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginEnd="0dp"
android:padding="12dp"
android:text="@string/continue_watching" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/home_watch_child_recyclerview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:clipToPadding="false"
android:descendantFocusability="afterDescendants"
android:orientation="horizontal"
android:paddingEnd="5dp"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
tools:listitem="@layout/home_result_grid" />
</LinearLayout>
<LinearLayout
android:id="@+id/home_bookmarked_holder"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:visibility="gone"
tools:visibility="visible">
<HorizontalScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fadingEdge="horizontal"
android:foreground="?android:attr/selectableItemBackgroundBorderless"
android:nextFocusLeft="@id/nav_rail_view"
android:nextFocusUp="@id/home_watch_child_recyclerview"
android:nextFocusForward="@id/home_bookmarked_child_recyclerview"
android:paddingStart="12dp"
android:paddingTop="5dp"
android:paddingEnd="12dp"
android:paddingBottom="5dp"
android:requiresFadingEdge="horizontal">
<com.google.android.material.chip.ChipGroup
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<com.google.android.material.chip.Chip
android:id="@+id/home_type_watching_btt"
style="@style/ChipFilled"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:nextFocusLeft="@id/nav_rail_view"
android:nextFocusRight="@id/home_plan_to_watch_btt"
android:text="@string/type_watching" />
<com.google.android.material.chip.Chip
android:id="@+id/home_plan_to_watch_btt"
style="@style/ChipFilled"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:nextFocusLeft="@id/home_type_watching_btt"
android:nextFocusRight="@id/home_type_on_hold_btt"
android:text="@string/type_plan_to_watch" />
<com.google.android.material.chip.Chip
android:id="@+id/home_type_on_hold_btt"
style="@style/ChipFilled"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:nextFocusLeft="@id/home_plan_to_watch_btt"
android:nextFocusRight="@id/home_type_dropped_btt"
android:text="@string/type_on_hold" />
<com.google.android.material.chip.Chip
android:id="@+id/home_type_dropped_btt"
style="@style/ChipFilled"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:nextFocusLeft="@id/home_type_on_hold_btt"
android:nextFocusRight="@id/home_type_completed_btt"
android:text="@string/type_dropped" />
<com.google.android.material.chip.Chip
android:id="@+id/home_type_completed_btt"
style="@style/ChipFilled"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:nextFocusLeft="@id/home_type_dropped_btt"
android:text="@string/type_completed" />
</com.google.android.material.chip.ChipGroup>
</HorizontalScrollView>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/home_bookmarked_child_recyclerview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:clipToPadding="false"
android:descendantFocusability="afterDescendants"
android:orientation="horizontal"
android:paddingEnd="5dp"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
tools:listitem="@layout/home_result_grid" />
</LinearLayout>
</LinearLayout>

View file

@ -0,0 +1,248 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout android:orientation="vertical"
android:id="@+id/home_preview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/primaryBlackBackground"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/home_preview_viewpager"
android:layout_width="match_parent"
android:layout_height="400dp"
android:orientation="horizontal">
</androidx.viewpager2.widget.ViewPager2>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="5dp">
<com.google.android.material.button.MaterialButton
android:id="@+id/home_preview_change_api"
style="@style/BlackButton"
android:layout_width="wrap_content"
android:layout_gravity="top|start"
android:layout_marginStart="@dimen/navbar_width"
android:backgroundTint="@color/semiWhite"
android:minWidth="150dp" />
</FrameLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="bottom"
android:layout_marginStart="@dimen/navbar_width"
android:gravity="bottom"
android:orientation="vertical"
android:padding="10dp">
<TextView
android:id="@+id/home_preview_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="end"
android:maxLines="1"
android:textSize="25sp"
android:textStyle="bold"
tools:text="The Perfect Run" />
<TextView
android:id="@+id/home_preview_description"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="end"
android:maxLines="5"
android:paddingBottom="5dp"
android:textSize="15sp"
tools:text="very nice tv series" />
<com.google.android.material.chip.ChipGroup
android:id="@+id/home_preview_tags"
style="@style/ChipParent"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dp">
<View
android:id="@+id/home_preview_hidden_prev_focus"
android:layout_width="1dp"
android:layout_height="1dp"
android:focusable="true" />
<com.google.android.material.button.MaterialButton
android:id="@+id/home_preview_play_btt"
style="@style/WhiteButton"
android:layout_width="wrap_content"
android:layout_margin="0dp"
android:minWidth="150dp"
android:nextFocusLeft="@id/home_preview_hidden_prev_focus"
android:nextFocusRight="@id/home_preview_info_btt"
android:nextFocusUp="@id/home_preview_change_api"
android:nextFocusDown="@id/home_watch_parent_item_title"
android:text="@string/home_play"
app:icon="@drawable/ic_baseline_play_arrow_24" />
<com.google.android.material.button.MaterialButton
android:id="@+id/home_preview_info_btt"
style="@style/BlackButton"
android:layout_width="wrap_content"
android:minWidth="150dp"
android:nextFocusLeft="@id/home_preview_play_btt"
android:nextFocusRight="@id/home_preview_hidden_next_focus"
android:nextFocusUp="@id/home_preview_change_api"
android:nextFocusDown="@id/home_watch_parent_item_title"
android:text="@string/home_info"
app:icon="@drawable/ic_outline_info_24" />
<View
android:id="@+id/home_preview_hidden_next_focus"
android:layout_width="1dp"
android:layout_height="1dp"
android:focusable="true" />
</LinearLayout>
</LinearLayout>
</FrameLayout>
<LinearLayout
android:id="@+id/home_watch_holder"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:visibility="gone"
tools:visibility="visible">
<TextView
android:id="@+id/home_watch_parent_item_title"
style="@style/WatchHeaderText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/navbar_width"
android:layout_marginEnd="0dp"
android:padding="12dp"
android:text="@string/continue_watching" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/home_watch_child_recyclerview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:clipToPadding="false"
android:descendantFocusability="afterDescendants"
android:orientation="horizontal"
android:paddingStart="@dimen/navbar_width"
android:paddingEnd="5dp"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
tools:listitem="@layout/home_result_grid" />
</LinearLayout>
<LinearLayout
android:id="@+id/home_bookmarked_holder"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:visibility="gone"
tools:visibility="visible">
<HorizontalScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fadingEdge="horizontal"
android:foreground="?android:attr/selectableItemBackgroundBorderless"
android:nextFocusLeft="@id/nav_rail_view"
android:nextFocusUp="@id/home_watch_child_recyclerview"
android:nextFocusForward="@id/home_bookmarked_child_recyclerview"
android:paddingStart="12dp"
android:paddingTop="5dp"
android:paddingEnd="12dp"
android:paddingBottom="5dp"
android:requiresFadingEdge="horizontal">
<com.google.android.material.chip.ChipGroup
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/navbar_width"
android:orientation="horizontal">
<com.google.android.material.chip.Chip
android:id="@+id/home_type_watching_btt"
style="@style/ChipFilled"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:nextFocusLeft="@id/nav_rail_view"
android:nextFocusRight="@id/home_plan_to_watch_btt"
android:text="@string/type_watching" />
<com.google.android.material.chip.Chip
android:id="@+id/home_plan_to_watch_btt"
style="@style/ChipFilled"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:nextFocusLeft="@id/home_type_watching_btt"
android:nextFocusRight="@id/home_type_on_hold_btt"
android:text="@string/type_plan_to_watch" />
<com.google.android.material.chip.Chip
android:id="@+id/home_type_on_hold_btt"
style="@style/ChipFilled"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:nextFocusLeft="@id/home_plan_to_watch_btt"
android:nextFocusRight="@id/home_type_dropped_btt"
android:text="@string/type_on_hold" />
<com.google.android.material.chip.Chip
android:id="@+id/home_type_dropped_btt"
style="@style/ChipFilled"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:nextFocusLeft="@id/home_type_on_hold_btt"
android:nextFocusRight="@id/home_type_completed_btt"
android:text="@string/type_dropped" />
<com.google.android.material.chip.Chip
android:id="@+id/home_type_completed_btt"
style="@style/ChipFilled"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:nextFocusLeft="@id/home_type_dropped_btt"
android:text="@string/type_completed" />
</com.google.android.material.chip.ChipGroup>
</HorizontalScrollView>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/home_bookmarked_child_recyclerview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:clipToPadding="false"
android:descendantFocusability="afterDescendants"
android:orientation="horizontal"
android:paddingStart="@dimen/navbar_width"
android:paddingEnd="5dp"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
tools:listitem="@layout/home_result_grid" />
</LinearLayout>
</LinearLayout>

View file

@ -2,38 +2,39 @@
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/home_root" android:id="@+id/home_root"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.home.HomeFragment"> tools:context=".ui.home.HomeFragment">
<FrameLayout <FrameLayout
android:visibility="gone"
tools:visibility="gone"
android:id="@+id/home_loading" android:id="@+id/home_loading"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent"
android:layout_marginStart="@dimen/navbar_width"
android:visibility="gone"
tools:visibility="gone">
<ProgressBar <ProgressBar
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_gravity="center" android:layout_gravity="center"
android:visibility="gone" android:visibility="gone"
tools:visibility="gone" tools:visibility="gone" />
android:layout_width="50dp"
android:layout_height="50dp" />
<com.facebook.shimmer.ShimmerFrameLayout <com.facebook.shimmer.ShimmerFrameLayout
android:id="@+id/home_loading_shimmer" android:id="@+id/home_loading_shimmer"
app:shimmer_base_alpha="0.2"
app:shimmer_highlight_alpha="0.3"
app:shimmer_duration="@integer/loading_time"
app:shimmer_auto_start="true"
android:paddingTop="40dp"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_gravity="center" android:layout_gravity="center"
android:layout_marginTop="15dp" android:layout_marginTop="15dp"
android:orientation="vertical"> android:orientation="vertical"
android:paddingTop="40dp"
app:shimmer_auto_start="true"
app:shimmer_base_alpha="0.2"
app:shimmer_duration="@integer/loading_time"
app:shimmer_highlight_alpha="0.3">
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
@ -41,47 +42,47 @@
android:orientation="vertical"> android:orientation="vertical">
<FrameLayout <FrameLayout
android:orientation="horizontal"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content"> android:layout_height="wrap_content"
android:orientation="horizontal">
<androidx.cardview.widget.CardView <androidx.cardview.widget.CardView
android:layout_margin="@dimen/loading_margin" android:layout_width="125dp"
android:layout_height="200dp"
android:layout_gravity="center" android:layout_gravity="center"
app:cardCornerRadius="@dimen/loading_radius" android:layout_margin="@dimen/loading_margin"
android:background="@color/grayShimmer" android:background="@color/grayShimmer"
android:translationX="-164dp" android:translationX="-164dp"
android:layout_width="125dp" app:cardCornerRadius="@dimen/loading_radius" />
android:layout_height="200dp" />
<androidx.cardview.widget.CardView <androidx.cardview.widget.CardView
android:layout_margin="@dimen/loading_margin"
android:layout_gravity="center"
app:cardCornerRadius="@dimen/loading_radius"
android:background="@color/grayShimmer"
android:layout_width="148dp" android:layout_width="148dp"
android:layout_height="234dp" /> android:layout_height="234dp"
android:layout_gravity="center"
android:layout_margin="@dimen/loading_margin"
android:background="@color/grayShimmer"
app:cardCornerRadius="@dimen/loading_radius" />
<androidx.cardview.widget.CardView <androidx.cardview.widget.CardView
android:layout_margin="@dimen/loading_margin" android:layout_width="125dp"
android:layout_height="200dp"
android:layout_gravity="center" android:layout_gravity="center"
app:cardCornerRadius="@dimen/loading_radius" android:layout_margin="@dimen/loading_margin"
android:background="@color/grayShimmer" android:background="@color/grayShimmer"
android:translationX="164dp" android:translationX="164dp"
android:layout_width="125dp" app:cardCornerRadius="@dimen/loading_radius" />
android:layout_height="200dp" />
</FrameLayout> </FrameLayout>
<include layout="@layout/loading_line_short_center" /> <include layout="@layout/loading_line_short_center" />
<LinearLayout <LinearLayout
android:orientation="vertical"
android:layout_marginTop="@dimen/result_padding"
android:layout_marginStart="@dimen/result_padding"
android:layout_marginEnd="@dimen/result_padding"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content"> android:layout_height="wrap_content"
android:layout_marginStart="@dimen/result_padding"
android:layout_marginTop="@dimen/result_padding"
android:layout_marginEnd="@dimen/result_padding"
android:orientation="vertical">
<include layout="@layout/loading_list" /> <include layout="@layout/loading_list" />
@ -99,349 +100,76 @@
<ImageView <ImageView
android:id="@+id/home_change_api_loading" android:id="@+id/home_change_api_loading"
android:layout_margin="10dp"
android:layout_gravity="center_vertical|end"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:src="@drawable/ic_baseline_keyboard_arrow_down_24"
android:layout_width="30dp" android:layout_width="30dp"
android:layout_height="30dp" android:layout_height="30dp"
android:contentDescription="@string/home_change_provider_img_des" /> android:layout_gravity="center_vertical|end"
android:layout_margin="10dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:contentDescription="@string/home_change_provider_img_des"
android:src="@drawable/ic_baseline_keyboard_arrow_down_24" />
</FrameLayout> </FrameLayout>
</FrameLayout> </FrameLayout>
<LinearLayout <LinearLayout
android:visibility="gone"
tools:visibility="gone"
android:id="@+id/home_loading_error" android:id="@+id/home_loading_error"
android:orientation="vertical"
android:layout_gravity="center"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content"> android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginStart="@dimen/navbar_width"
android:orientation="vertical"
android:visibility="gone"
tools:visibility="gone">
<com.google.android.material.button.MaterialButton <com.google.android.material.button.MaterialButton
android:layout_gravity="center" android:id="@+id/home_reload_connectionerror"
style="@style/WhiteButton" style="@style/WhiteButton"
android:layout_margin="5dp"
app:icon="@drawable/ic_baseline_autorenew_24"
android:text="@string/reload_error"
android:id="@+id/home_reload_connectionerror"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:minWidth="200dp" />
android:layout_gravity="center"
android:layout_margin="5dp"
android:minWidth="200dp"
android:text="@string/reload_error"
app:icon="@drawable/ic_baseline_autorenew_24" />
<com.google.android.material.button.MaterialButton <com.google.android.material.button.MaterialButton
android:layout_gravity="center" android:id="@+id/home_reload_connection_open_in_browser"
style="@style/BlackButton" style="@style/BlackButton"
android:layout_margin="5dp"
app:icon="@drawable/ic_baseline_public_24"
android:text="@string/result_open_in_browser"
android:id="@+id/home_reload_connection_open_in_browser"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:minWidth="200dp" />
android:layout_gravity="center"
android:layout_margin="5dp"
android:minWidth="200dp"
android:text="@string/result_open_in_browser"
app:icon="@drawable/ic_baseline_public_24" />
<TextView <TextView
android:id="@+id/result_error_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_margin="5dp" android:layout_margin="5dp"
android:gravity="center" android:gravity="center"
android:layout_gravity="center" android:textColor="?attr/textColor" />
android:id="@+id/result_error_text"
android:textColor="?attr/textColor"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout> </LinearLayout>
<androidx.core.widget.NestedScrollView
android:background="?attr/primaryBlackBackground"
tools:visibility="visible"
android:visibility="gone"
android:id="@+id/home_loaded"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<View
android:background="?attr/primaryGrayBackground"
android:id="@+id/home_statusbar"
android:layout_height="wrap_content"
android:layout_width="match_parent" />
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:scaleType="centerCrop"
tools:src="@drawable/example_poster"
android:id="@+id/home_blur_poster"
android:layout_width="match_parent"
android:layout_height="200dp" />
<ImageView
android:id="@+id/shadow_overlay"
android:layout_width="match_parent"
android:layout_height="200dp"
android:background="@drawable/background_shadow" />
<LinearLayout
android:layout_marginTop="100dp"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:paddingTop="10dp"
android:paddingBottom="10dp"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="100dp">
<!--
<androidx.cardview.widget.CardView
android:id="@+id/home_profile_picture_holder"
android:layout_marginEnd="20dp"
app:cardCornerRadius="100dp"
android:layout_gravity="center_vertical"
android:layout_width="35dp"
android:layout_height="35dp">
<ImageView
android:id="@+id/home_profile_picture"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:ignore="ContentDescription" />
</androidx.cardview.widget.CardView>-->
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:nextFocusDown="@id/home_main_poster_recyclerview"
android:nextFocusUp="@id/nav_rail_view"
android:nextFocusLeft="@id/nav_rail_view"
android:layout_gravity="center_vertical"
android:id="@+id/home_change_api"
android:layout_margin="10dp"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:foreground="@drawable/outline_drawable"
android:src="@drawable/ic_baseline_filter_list_24"
android:layout_width="30dp"
android:layout_height="30dp"
android:contentDescription="@string/home_change_provider_img_des">
<requestFocus />
</ImageView>
<TextView
android:maxLines="1"
android:ellipsize="end"
android:gravity="center_vertical"
android:layout_gravity="center_vertical"
android:textStyle="bold"
android:textSize="25sp"
tools:text="The Perfect Run"
android:id="@+id/home_focus_text"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
<LinearLayout
android:layout_marginStart="12dp"
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView
android:gravity="center_vertical"
android:id="@+id/home_provider_name"
android:textColor="?attr/grayTextColor"
android:textSize="20sp"
android:paddingEnd="10dp"
tools:text="Hello World"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:gravity="center_vertical"
android:id="@+id/home_provider_meta_info"
android:textColor="?attr/grayTextColor"
android:textSize="20sp"
tools:text="Hello World"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
<androidx.recyclerview.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
android:paddingHorizontal="5dp"
android:clipToPadding="false"
android:descendantFocusability="afterDescendants"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
android:id="@+id/home_main_poster_recyclerview"
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:listitem="@layout/home_result_grid" />
</LinearLayout>
</FrameLayout>
<LinearLayout
android:id="@+id/home_watch_holder"
android:orientation="vertical"
android:visibility="gone"
tools:visibility="visible"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/home_watch_parent_item_title"
android:padding="12dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="@style/WatchHeaderText"
android:layout_marginEnd="0dp"
android:text="@string/continue_watching">
</TextView>
<androidx.recyclerview.widget.RecyclerView
android:paddingHorizontal="5dp"
android:clipToPadding="false"
android:descendantFocusability="afterDescendants"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
android:id="@+id/home_watch_child_recyclerview"
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:listitem="@layout/home_result_grid" />
</LinearLayout>
<LinearLayout
android:id="@+id/home_bookmarked_holder"
android:orientation="vertical"
android:visibility="gone"
tools:visibility="visible"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<HorizontalScrollView
android:nextFocusLeft="@id/nav_rail_view"
android:nextFocusUp="@id/home_watch_child_recyclerview"
android:nextFocusForward="@id/home_bookmarked_child_recyclerview"
android:foreground="?android:attr/selectableItemBackgroundBorderless"
android:paddingTop="5dp"
android:paddingBottom="5dp"
android:paddingStart="12dp"
android:paddingEnd="12dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fadingEdge="horizontal"
android:requiresFadingEdge="horizontal">
<com.google.android.material.chip.ChipGroup
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<com.google.android.material.chip.Chip
android:id="@+id/home_type_watching_btt"
style="@style/ChipFilled"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:nextFocusLeft="@id/nav_rail_view"
android:nextFocusRight="@id/home_plan_to_watch_btt"
android:text="@string/type_watching" />
<com.google.android.material.chip.Chip
android:id="@+id/home_plan_to_watch_btt"
style="@style/ChipFilled"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:nextFocusLeft="@id/home_type_watching_btt"
android:nextFocusRight="@id/home_type_on_hold_btt"
android:text="@string/type_plan_to_watch" />
<com.google.android.material.chip.Chip
android:id="@+id/home_type_on_hold_btt"
style="@style/ChipFilled"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:nextFocusLeft="@id/home_plan_to_watch_btt"
android:nextFocusRight="@id/home_type_dropped_btt"
android:text="@string/type_on_hold" />
<com.google.android.material.chip.Chip
android:id="@+id/home_type_dropped_btt"
style="@style/ChipFilled"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:nextFocusLeft="@id/home_type_on_hold_btt"
android:nextFocusRight="@id/home_type_completed_btt"
android:text="@string/type_dropped" />
<com.google.android.material.chip.Chip
android:id="@+id/home_type_completed_btt"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
style="@style/ChipFilled"
android:nextFocusLeft="@id/home_type_dropped_btt"
android:text="@string/type_completed" />
</com.google.android.material.chip.ChipGroup> </HorizontalScrollView>
<androidx.recyclerview.widget.RecyclerView
android:paddingHorizontal="5dp"
android:clipToPadding="false"
android:descendantFocusability="afterDescendants"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
android:id="@+id/home_bookmarked_child_recyclerview"
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:listitem="@layout/home_result_grid" />
</LinearLayout>
<androidx.recyclerview.widget.RecyclerView
android:nextFocusLeft="@id/nav_rail_view"
android:descendantFocusability="afterDescendants"
android:id="@+id/home_master_recycler" android:id="@+id/home_master_recycler"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="wrap_content"
android:descendantFocusability="afterDescendants"
android:nextFocusLeft="@id/nav_rail_view"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
tools:listitem="@layout/homepage_parent_tv" /> tools:listitem="@layout/homepage_parent_tv" />
</LinearLayout>
</androidx.core.widget.NestedScrollView>
<com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton <com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
android:visibility="gone"
tools:visibility="visible"
android:id="@+id/home_api_fab" android:id="@+id/home_api_fab"
app:icon="@drawable/ic_baseline_filter_list_24"
style="@style/ExtendedFloatingActionButton" style="@style/ExtendedFloatingActionButton"
tools:ignore="ContentDescription" /> android:visibility="gone"
app:icon="@drawable/ic_baseline_filter_list_24"
tools:ignore="ContentDescription"
tools:visibility="visible" />
</FrameLayout> </FrameLayout>

View file

@ -516,6 +516,7 @@
android:visibility="gone" /> android:visibility="gone" />
<com.google.android.material.chip.ChipGroup <com.google.android.material.chip.ChipGroup
style="@style/ChipParent"
android:id="@+id/result_tag" android:id="@+id/result_tag"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" /> android:layout_height="wrap_content" />

View file

@ -385,6 +385,7 @@
<com.google.android.material.chip.ChipGroup <com.google.android.material.chip.ChipGroup
style="@style/ChipParent"
android:id="@+id/result_tag" android:id="@+id/result_tag"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" /> android:layout_height="wrap_content" />

View file

@ -10,6 +10,12 @@
android:orientation="vertical" android:orientation="vertical"
tools:context=".ui.search.SearchFragment"> tools:context=".ui.search.SearchFragment">
<LinearLayout
android:paddingBottom="10dp"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<FrameLayout <FrameLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="40dp" android:layout_height="40dp"
@ -83,6 +89,7 @@
</FrameLayout> </FrameLayout>
<include layout="@layout/tvtypes_chips_scroll" /> <include layout="@layout/tvtypes_chips_scroll" />
</LinearLayout>
<com.lagradost.cloudstream3.ui.AutofitRecyclerView <com.lagradost.cloudstream3.ui.AutofitRecyclerView
@ -112,6 +119,7 @@
android:nextFocusLeft="@id/nav_rail_view" android:nextFocusLeft="@id/nav_rail_view"
android:visibility="gone" android:visibility="gone"
tools:listitem="@layout/homepage_parent" /> tools:listitem="@layout/homepage_parent" />
<FrameLayout <FrameLayout
android:id="@+id/search_history_holder" android:id="@+id/search_history_holder"
android:layout_width="match_parent" android:layout_width="match_parent"

View file

@ -0,0 +1,155 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/searchRoot"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="@dimen/navbar_height"
android:background="?attr/primaryGrayBackground"
android:orientation="vertical"
tools:context=".ui.search.SearchFragment">
<LinearLayout
android:layout_marginStart="@dimen/navbar_width"
android:paddingBottom="10dp"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="40dp"
android:layout_margin="10dp"
android:background="@drawable/search_background"
android:visibility="visible">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="30dp"
android:layout_gravity="center_vertical"
android:layout_marginEnd="30dp">
<androidx.appcompat.widget.SearchView
android:id="@+id/main_search"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center_vertical"
android:iconifiedByDefault="false"
android:imeOptions="actionSearch"
android:inputType="text"
android:nextFocusLeft="@id/nav_rail_view"
android:nextFocusRight="@id/search_filter"
android:nextFocusUp="@id/nav_rail_view"
android:nextFocusDown="@id/search_autofit_results"
android:paddingStart="-10dp"
app:iconifiedByDefault="false"
app:queryBackground="@color/transparent"
app:queryHint="@string/search_hint"
app:searchIcon="@drawable/search_icon"
tools:ignore="RtlSymmetry">
<requestFocus />
<androidx.core.widget.ContentLoadingProgressBar
android:id="@+id/search_loading_bar"
style="@style/Widget.AppCompat.ProgressBar"
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_gravity="center"
android:layout_marginStart="-35dp"
android:foregroundTint="@color/white"
android:progressTint="@color/white">
</androidx.core.widget.ContentLoadingProgressBar>
<!--app:queryHint="@string/search_hint"
android:background="@color/grayBackground" @color/itemBackground
app:searchHintIcon="@drawable/search_white"
-->
</androidx.appcompat.widget.SearchView>
</FrameLayout>
<ImageView
android:id="@+id/search_filter"
android:layout_width="25dp"
android:layout_height="25dp"
android:layout_gravity="end|center_vertical"
android:layout_margin="10dp"
android:background="?selectableItemBackgroundBorderless"
android:contentDescription="@string/change_providers_img_des"
android:nextFocusLeft="@id/main_search"
android:nextFocusRight="@id/main_search"
android:nextFocusUp="@id/nav_rail_view"
android:nextFocusDown="@id/search_autofit_results"
android:src="@drawable/ic_baseline_tune_24"
app:tint="?attr/textColor" />
</FrameLayout>
<include layout="@layout/tvtypes_chips_scroll" />
</LinearLayout>
<com.lagradost.cloudstream3.ui.AutofitRecyclerView
android:id="@+id/search_autofit_results"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/primaryBlackBackground"
android:clipToPadding="false"
android:descendantFocusability="afterDescendants"
android:nextFocusLeft="@id/nav_rail_view"
android:orientation="vertical"
android:paddingStart="8dp"
android:paddingTop="5dp"
android:paddingEnd="8dp"
android:visibility="gone"
app:spanCount="3"
tools:listitem="@layout/search_result_grid" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/search_master_recycler"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/primaryBlackBackground"
android:descendantFocusability="afterDescendants"
android:nextFocusLeft="@id/nav_rail_view"
android:visibility="gone"
tools:listitem="@layout/homepage_parent" />
<FrameLayout
android:id="@+id/search_history_holder"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.recyclerview.widget.RecyclerView
android:paddingStart="@dimen/navbar_width"
android:id="@+id/search_history_recycler"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/primaryBlackBackground"
android:descendantFocusability="afterDescendants"
android:nextFocusLeft="@id/nav_rail_view"
android:visibility="visible"
android:paddingBottom="50dp"
tools:listitem="@layout/search_history_item" />
<com.google.android.material.button.MaterialButton
android:id="@+id/search_clear_call_history"
style="@style/BlackButton"
android:layout_gravity="bottom"
android:padding="0dp"
app:cornerRadius="0dp"
android:layout_margin="0dp"
android:text="@string/clear_history"
app:icon="@drawable/delete_all"
android:layout_width="match_parent"
android:layout_height="50dp" />
</FrameLayout>
</LinearLayout>

View file

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:background="?attr/primaryGrayBackground"
android:layout_height="match_parent">
<ImageView
android:id="@+id/home_scroll_preview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
tools:src="@drawable/example_poster" />
<View
android:id="@+id/title_shadow"
android:layout_width="match_parent"
android:layout_height="300dp"
android:layout_gravity="bottom"
android:background="@drawable/background_shadow" />
</FrameLayout>

View file

@ -7,18 +7,20 @@
android:layout_height="wrap_content"> android:layout_height="wrap_content">
<TextView <TextView
android:layout_marginStart="@dimen/navbar_width"
android:id="@+id/home_parent_item_title" android:id="@+id/home_parent_item_title"
android:padding="12dp" android:padding="12dp"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
style="@style/WatchHeaderText" style="@style/WatchHeaderText"
android:layout_marginEnd="0dp" android:layout_marginEnd="0dp"
tools:text="Trending"> tools:text="Trending" />
</TextView>
<androidx.recyclerview.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
android:nextFocusUp="@id/home_child_more_info" android:nextFocusUp="@id/home_child_more_info"
android:paddingHorizontal="5dp"
android:paddingEnd="5dp"
android:paddingStart="@dimen/navbar_width"
android:clipToPadding="false" android:clipToPadding="false"
android:descendantFocusability="afterDescendants" android:descendantFocusability="afterDescendants"

View file

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<com.google.android.material.chip.ChipGroup android:layout_width="match_parent" <com.google.android.material.chip.ChipGroup android:layout_width="match_parent"
style="@style/ChipParent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
android:paddingStart="8dp" android:paddingStart="8dp"

View file

@ -13,6 +13,7 @@
<color name="boxItemBackground">#161616</color> <!-- 17171B 1B1B20--> <color name="boxItemBackground">#161616</color> <!-- 17171B 1B1B20-->
<color name="textColor">#e9eaee</color> <!--FFF--> <color name="textColor">#e9eaee</color> <!--FFF-->
<color name="semiWhite">#1AFFFFFF</color> <!--FFF-->
<color name="grayTextColor">#9ba0a4</color> <!-- 5e5f62--> <color name="grayTextColor">#9ba0a4</color> <!-- 5e5f62-->
<color name="grayShimmer">#DCDCDC</color> <!-- 5e5f62--> <color name="grayShimmer">#DCDCDC</color> <!-- 5e5f62-->

View file

@ -16,4 +16,5 @@
<integer name="loading_time">2000</integer> <integer name="loading_time">2000</integer>
<dimen name="storage_radius">3dp</dimen> <dimen name="storage_radius">3dp</dimen>
<dimen name="navbar_width">62dp</dimen>
</resources> </resources>

View file

@ -88,6 +88,16 @@
<item name="fontFamily">@font/google_sans</item> <item name="fontFamily">@font/google_sans</item>
<item name="chipIconTint">@color/chip_color_text</item> <item name="chipIconTint">@color/chip_color_text</item>
<item name="android:fontFamily">@font/google_sans</item> <item name="android:fontFamily">@font/google_sans</item>
<item name="chipMinTouchTargetSize">0dp</item>
</style>
<style name="ChipFilledSemiTransparent" parent="@style/ChipFilled">
<item name="chipBackgroundColor">@color/transparent</item>
<item name="chipSurfaceColor">@color/semiWhite</item>
<item name="backgroundColor">@color/transparent</item>
</style>
<style name="ChipParent">
<item name="chipSpacingVertical">5dp</item>
<item name="chipSpacingHorizontal">5dp</item>
</style> </style>
<style name="AmoledMode"> <style name="AmoledMode">