mirror of
https://github.com/recloudstream/cloudstream.git
synced 2024-08-15 01:53:11 +00:00
migrated some items to viewbindings + removed Some<T>
This commit is contained in:
parent
927453d9fe
commit
05a0d3cd81
46 changed files with 1565 additions and 1264 deletions
|
@ -28,6 +28,11 @@ android {
|
||||||
testOptions {
|
testOptions {
|
||||||
unitTests.isReturnDefaultValues = true
|
unitTests.isReturnDefaultValues = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
viewBinding {
|
||||||
|
enable = true
|
||||||
|
}
|
||||||
|
|
||||||
signingConfigs {
|
signingConfigs {
|
||||||
create("prerelease") {
|
create("prerelease") {
|
||||||
if (prereleaseStoreFile != null) {
|
if (prereleaseStoreFile != null) {
|
||||||
|
|
|
@ -57,32 +57,6 @@ fun <T> LifecycleOwner.observeNullable(liveData: LiveData<T>, action: (t: T) ->
|
||||||
liveData.observe(this) { action(it) }
|
liveData.observe(this) { action(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
inline fun <reified T : Any> some(value: T?): Some<T> {
|
|
||||||
return if (value == null) {
|
|
||||||
Some.None
|
|
||||||
} else {
|
|
||||||
Some.Success(value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sealed class Some<out T> {
|
|
||||||
data class Success<out T>(val value: T) : Some<T>()
|
|
||||||
object None : Some<Nothing>()
|
|
||||||
|
|
||||||
override fun toString(): String {
|
|
||||||
return when (this) {
|
|
||||||
is None -> "None"
|
|
||||||
is Success -> "Some(${value.toString()})"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sealed class ResourceSome<out T> {
|
|
||||||
data class Success<out T>(val value: T) : ResourceSome<T>()
|
|
||||||
object None : ResourceSome<Nothing>()
|
|
||||||
data class Loading(val data: Any? = null) : ResourceSome<Nothing>()
|
|
||||||
}
|
|
||||||
|
|
||||||
sealed class Resource<out T> {
|
sealed class Resource<out T> {
|
||||||
data class Success<out T>(val value: T) : Resource<T>()
|
data class Success<out T>(val value: T) : Resource<T>()
|
||||||
data class Failure(
|
data class Failure(
|
||||||
|
|
|
@ -8,6 +8,7 @@ import androidx.fragment.app.Fragment
|
||||||
import androidx.recyclerview.widget.GridLayoutManager
|
import androidx.recyclerview.widget.GridLayoutManager
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import com.lagradost.cloudstream3.R
|
import com.lagradost.cloudstream3.R
|
||||||
|
import com.lagradost.cloudstream3.databinding.FragmentChildDownloadsBinding
|
||||||
import com.lagradost.cloudstream3.ui.download.DownloadButtonSetup.handleDownloadClick
|
import com.lagradost.cloudstream3.ui.download.DownloadButtonSetup.handleDownloadClick
|
||||||
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
|
||||||
|
@ -15,13 +16,12 @@ import com.lagradost.cloudstream3.utils.DataStore.getKeys
|
||||||
import com.lagradost.cloudstream3.utils.UIHelper.fixPaddingStatusbar
|
import com.lagradost.cloudstream3.utils.UIHelper.fixPaddingStatusbar
|
||||||
import com.lagradost.cloudstream3.utils.VideoDownloadHelper
|
import com.lagradost.cloudstream3.utils.VideoDownloadHelper
|
||||||
import com.lagradost.cloudstream3.utils.VideoDownloadManager
|
import com.lagradost.cloudstream3.utils.VideoDownloadManager
|
||||||
import kotlinx.android.synthetic.main.fragment_child_downloads.*
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
|
|
||||||
class DownloadChildFragment : Fragment() {
|
class DownloadChildFragment : Fragment() {
|
||||||
companion object {
|
companion object {
|
||||||
fun newInstance(headerName: String, folder: String) : Bundle {
|
fun newInstance(headerName: String, folder: String): Bundle {
|
||||||
return Bundle().apply {
|
return Bundle().apply {
|
||||||
putString("folder", folder)
|
putString("folder", folder)
|
||||||
putString("name", headerName)
|
putString("name", headerName)
|
||||||
|
@ -30,13 +30,21 @@ class DownloadChildFragment : Fragment() {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDestroyView() {
|
override fun onDestroyView() {
|
||||||
(download_child_list?.adapter as DownloadChildAdapter?)?.killAdapter()
|
(binding?.downloadChildList?.adapter as DownloadChildAdapter?)?.killAdapter()
|
||||||
downloadDeleteEventListener?.let { VideoDownloadManager.downloadDeleteEvent -= it }
|
downloadDeleteEventListener?.let { VideoDownloadManager.downloadDeleteEvent -= it }
|
||||||
|
binding = null
|
||||||
super.onDestroyView()
|
super.onDestroyView()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
var binding: FragmentChildDownloadsBinding? = null
|
||||||
return inflater.inflate(R.layout.fragment_child_downloads, container, false)
|
override fun onCreateView(
|
||||||
|
inflater: LayoutInflater,
|
||||||
|
container: ViewGroup?,
|
||||||
|
savedInstanceState: Bundle?
|
||||||
|
): View {
|
||||||
|
val localBinding = FragmentChildDownloadsBinding.inflate(inflater, container, false)
|
||||||
|
binding = localBinding
|
||||||
|
return localBinding.root//inflater.inflate(R.layout.fragment_child_downloads, container, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateList(folder: String) = main {
|
private fun updateList(folder: String) = main {
|
||||||
|
@ -50,14 +58,15 @@ class DownloadChildFragment : Fragment() {
|
||||||
?: return@mapNotNull null
|
?: return@mapNotNull null
|
||||||
VisualDownloadChildCached(info.fileLength, info.totalBytes, it)
|
VisualDownloadChildCached(info.fileLength, info.totalBytes, it)
|
||||||
}
|
}
|
||||||
}.sortedBy { it.data.episode + (it.data.season?: 0)*100000 }
|
}.sortedBy { it.data.episode + (it.data.season ?: 0) * 100000 }
|
||||||
if (eps.isEmpty()) {
|
if (eps.isEmpty()) {
|
||||||
activity?.onBackPressed()
|
activity?.onBackPressed()
|
||||||
return@main
|
return@main
|
||||||
}
|
}
|
||||||
|
|
||||||
(download_child_list?.adapter as DownloadChildAdapter? ?: return@main).cardList = eps
|
(binding?.downloadChildList?.adapter as DownloadChildAdapter? ?: return@main).cardList =
|
||||||
download_child_list?.adapter?.notifyDataSetChanged()
|
eps
|
||||||
|
binding?.downloadChildList?.adapter?.notifyDataSetChanged()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,14 +81,17 @@ class DownloadChildFragment : Fragment() {
|
||||||
activity?.onBackPressed() // TODO FIX
|
activity?.onBackPressed() // TODO FIX
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
context?.fixPaddingStatusbar(download_child_root)
|
fixPaddingStatusbar(binding?.downloadChildRoot)
|
||||||
|
|
||||||
download_child_toolbar.title = name
|
binding?.downloadChildToolbar?.apply {
|
||||||
download_child_toolbar.setNavigationIcon(R.drawable.ic_baseline_arrow_back_24)
|
title = name
|
||||||
download_child_toolbar.setNavigationOnClickListener {
|
setNavigationIcon(R.drawable.ic_baseline_arrow_back_24)
|
||||||
activity?.onBackPressed()
|
setNavigationOnClickListener {
|
||||||
|
activity?.onBackPressed()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
val adapter: RecyclerView.Adapter<RecyclerView.ViewHolder> =
|
val adapter: RecyclerView.Adapter<RecyclerView.ViewHolder> =
|
||||||
DownloadChildAdapter(
|
DownloadChildAdapter(
|
||||||
ArrayList(),
|
ArrayList(),
|
||||||
|
@ -88,7 +100,7 @@ class DownloadChildFragment : Fragment() {
|
||||||
}
|
}
|
||||||
|
|
||||||
downloadDeleteEventListener = { id: Int ->
|
downloadDeleteEventListener = { id: Int ->
|
||||||
val list = (download_child_list?.adapter as DownloadChildAdapter?)?.cardList
|
val list = (binding?.downloadChildList?.adapter as DownloadChildAdapter?)?.cardList
|
||||||
if (list != null) {
|
if (list != null) {
|
||||||
if (list.any { it.data.id == id }) {
|
if (list.any { it.data.id == id }) {
|
||||||
updateList(folder)
|
updateList(folder)
|
||||||
|
@ -98,8 +110,8 @@ class DownloadChildFragment : Fragment() {
|
||||||
|
|
||||||
downloadDeleteEventListener?.let { VideoDownloadManager.downloadDeleteEvent += it }
|
downloadDeleteEventListener?.let { VideoDownloadManager.downloadDeleteEvent += it }
|
||||||
|
|
||||||
download_child_list.adapter = adapter
|
binding?.downloadChildList?.adapter = adapter
|
||||||
download_child_list.layoutManager = GridLayoutManager(context, 1)
|
binding?.downloadChildList?.layoutManager = GridLayoutManager(context, 1)
|
||||||
|
|
||||||
updateList(folder)
|
updateList(folder)
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,10 +34,10 @@ 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.VideoDownloadHelper
|
import com.lagradost.cloudstream3.utils.VideoDownloadHelper
|
||||||
import com.lagradost.cloudstream3.utils.VideoDownloadManager
|
import com.lagradost.cloudstream3.utils.VideoDownloadManager
|
||||||
import kotlinx.android.synthetic.main.fragment_downloads.*
|
|
||||||
import kotlinx.android.synthetic.main.stream_input.*
|
|
||||||
import android.text.format.Formatter.formatShortFileSize
|
import android.text.format.Formatter.formatShortFileSize
|
||||||
import androidx.core.widget.doOnTextChanged
|
import androidx.core.widget.doOnTextChanged
|
||||||
|
import com.lagradost.cloudstream3.databinding.FragmentDownloadsBinding
|
||||||
|
import com.lagradost.cloudstream3.databinding.StreamInputBinding
|
||||||
import com.lagradost.cloudstream3.mvvm.normalSafeApiCall
|
import com.lagradost.cloudstream3.mvvm.normalSafeApiCall
|
||||||
import com.lagradost.cloudstream3.ui.player.BasicLink
|
import com.lagradost.cloudstream3.ui.player.BasicLink
|
||||||
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTrueTvSettings
|
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTrueTvSettings
|
||||||
|
@ -60,8 +60,8 @@ class DownloadFragment : Fragment() {
|
||||||
|
|
||||||
private fun setList(list: List<VisualDownloadHeaderCached>) {
|
private fun setList(list: List<VisualDownloadHeaderCached>) {
|
||||||
main {
|
main {
|
||||||
(download_list?.adapter as DownloadHeaderAdapter?)?.cardList = list
|
(binding?.downloadList?.adapter as DownloadHeaderAdapter?)?.cardList = list
|
||||||
download_list?.adapter?.notifyDataSetChanged()
|
binding?.downloadList?.adapter?.notifyDataSetChanged()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,10 +70,13 @@ class DownloadFragment : Fragment() {
|
||||||
VideoDownloadManager.downloadDeleteEvent -= downloadDeleteEventListener!!
|
VideoDownloadManager.downloadDeleteEvent -= downloadDeleteEventListener!!
|
||||||
downloadDeleteEventListener = null
|
downloadDeleteEventListener = null
|
||||||
}
|
}
|
||||||
(download_list?.adapter as DownloadHeaderAdapter?)?.killAdapter()
|
(binding?.downloadList?.adapter as DownloadHeaderAdapter?)?.killAdapter()
|
||||||
|
binding = null
|
||||||
super.onDestroyView()
|
super.onDestroyView()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var binding : FragmentDownloadsBinding? = null
|
||||||
|
|
||||||
override fun onCreateView(
|
override fun onCreateView(
|
||||||
inflater: LayoutInflater,
|
inflater: LayoutInflater,
|
||||||
container: ViewGroup?,
|
container: ViewGroup?,
|
||||||
|
@ -82,7 +85,9 @@ class DownloadFragment : Fragment() {
|
||||||
downloadsViewModel =
|
downloadsViewModel =
|
||||||
ViewModelProvider(this)[DownloadViewModel::class.java]
|
ViewModelProvider(this)[DownloadViewModel::class.java]
|
||||||
|
|
||||||
return inflater.inflate(R.layout.fragment_downloads, container, false)
|
val localBinding = FragmentDownloadsBinding.inflate(inflater, container, false)
|
||||||
|
binding = localBinding
|
||||||
|
return localBinding.root//inflater.inflate(R.layout.fragment_downloads, container, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
private var downloadDeleteEventListener: ((Int) -> Unit)? = null
|
private var downloadDeleteEventListener: ((Int) -> Unit)? = null
|
||||||
|
@ -92,36 +97,40 @@ class DownloadFragment : Fragment() {
|
||||||
hideKeyboard()
|
hideKeyboard()
|
||||||
|
|
||||||
observe(downloadsViewModel.noDownloadsText) {
|
observe(downloadsViewModel.noDownloadsText) {
|
||||||
text_no_downloads.text = it
|
binding?.textNoDownloads?.text = it
|
||||||
}
|
}
|
||||||
observe(downloadsViewModel.headerCards) {
|
observe(downloadsViewModel.headerCards) {
|
||||||
setList(it)
|
setList(it)
|
||||||
download_loading.isVisible = false
|
binding?.downloadLoading?.isVisible = false
|
||||||
}
|
}
|
||||||
observe(downloadsViewModel.availableBytes) {
|
observe(downloadsViewModel.availableBytes) {
|
||||||
download_free_txt?.text =
|
binding?.downloadFreeTxt?.text =
|
||||||
getString(R.string.storage_size_format).format(
|
getString(R.string.storage_size_format).format(
|
||||||
getString(R.string.free_storage),
|
getString(R.string.free_storage),
|
||||||
formatShortFileSize(view.context, it)
|
formatShortFileSize(view.context, it)
|
||||||
)
|
)
|
||||||
download_free?.setLayoutWidth(it)
|
binding?.downloadFree?.setLayoutWidth(it)
|
||||||
}
|
}
|
||||||
observe(downloadsViewModel.usedBytes) {
|
observe(downloadsViewModel.usedBytes) {
|
||||||
download_used_txt?.text =
|
binding?.apply {
|
||||||
getString(R.string.storage_size_format).format(
|
downloadUsedTxt.text =
|
||||||
getString(R.string.used_storage),
|
getString(R.string.storage_size_format).format(
|
||||||
formatShortFileSize(view.context, it)
|
getString(R.string.used_storage),
|
||||||
)
|
formatShortFileSize(view.context, it)
|
||||||
download_used?.setLayoutWidth(it)
|
)
|
||||||
download_storage_appbar?.isVisible = it > 0
|
downloadUsed.setLayoutWidth(it)
|
||||||
|
downloadStorageAppbar.isVisible = it > 0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
observe(downloadsViewModel.downloadBytes) {
|
observe(downloadsViewModel.downloadBytes) {
|
||||||
download_app_txt?.text =
|
binding?.apply {
|
||||||
getString(R.string.storage_size_format).format(
|
downloadAppTxt.text =
|
||||||
getString(R.string.app_storage),
|
getString(R.string.storage_size_format).format(
|
||||||
formatShortFileSize(view.context, it)
|
getString(R.string.app_storage),
|
||||||
)
|
formatShortFileSize(view.context, it)
|
||||||
download_app?.setLayoutWidth(it)
|
)
|
||||||
|
downloadApp.setLayoutWidth(it)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val adapter: RecyclerView.Adapter<RecyclerView.ViewHolder> =
|
val adapter: RecyclerView.Adapter<RecyclerView.ViewHolder> =
|
||||||
|
@ -164,7 +173,7 @@ class DownloadFragment : Fragment() {
|
||||||
)
|
)
|
||||||
|
|
||||||
downloadDeleteEventListener = { id ->
|
downloadDeleteEventListener = { id ->
|
||||||
val list = (download_list?.adapter as DownloadHeaderAdapter?)?.cardList
|
val list = (binding?.downloadList?.adapter as DownloadHeaderAdapter?)?.cardList
|
||||||
if (list != null) {
|
if (list != null) {
|
||||||
if (list.any { it.data.id == id }) {
|
if (list.any { it.data.id == id }) {
|
||||||
context?.let { ctx ->
|
context?.let { ctx ->
|
||||||
|
@ -177,31 +186,36 @@ class DownloadFragment : Fragment() {
|
||||||
|
|
||||||
downloadDeleteEventListener?.let { VideoDownloadManager.downloadDeleteEvent += it }
|
downloadDeleteEventListener?.let { VideoDownloadManager.downloadDeleteEvent += it }
|
||||||
|
|
||||||
download_list?.adapter = adapter
|
binding?.downloadList?.apply {
|
||||||
download_list?.layoutManager = GridLayoutManager(context, 1)
|
this.adapter = adapter
|
||||||
|
layoutManager = GridLayoutManager(context, 1)
|
||||||
|
}
|
||||||
|
|
||||||
// Should be visible in emulator layout
|
// Should be visible in emulator layout
|
||||||
download_stream_button?.isGone = isTrueTvSettings()
|
binding?.downloadStreamButton?.isGone = isTrueTvSettings()
|
||||||
download_stream_button?.setOnClickListener {
|
binding?.downloadStreamButton?.setOnClickListener {
|
||||||
val dialog =
|
val dialog =
|
||||||
Dialog(it.context ?: return@setOnClickListener, R.style.AlertDialogCustom)
|
Dialog(it.context ?: return@setOnClickListener, R.style.AlertDialogCustom)
|
||||||
dialog.setContentView(R.layout.stream_input)
|
|
||||||
|
val binding = StreamInputBinding.inflate(dialog.layoutInflater)
|
||||||
|
|
||||||
|
dialog.setContentView(binding.root)
|
||||||
|
|
||||||
dialog.show()
|
dialog.show()
|
||||||
|
|
||||||
// If user has clicked the switch do not interfere
|
// If user has clicked the switch do not interfere
|
||||||
var preventAutoSwitching = false
|
var preventAutoSwitching = false
|
||||||
dialog.hls_switch?.setOnClickListener {
|
binding.hlsSwitch.setOnClickListener {
|
||||||
preventAutoSwitching = true
|
preventAutoSwitching = true
|
||||||
}
|
}
|
||||||
|
|
||||||
fun activateSwitchOnHls(text: String?) {
|
fun activateSwitchOnHls(text: String?) {
|
||||||
dialog.hls_switch?.isChecked = normalSafeApiCall {
|
binding.hlsSwitch.isChecked = normalSafeApiCall {
|
||||||
URI(text).path?.substringAfterLast(".")?.contains("m3u")
|
URI(text).path?.substringAfterLast(".")?.contains("m3u")
|
||||||
} == true
|
} == true
|
||||||
}
|
}
|
||||||
|
|
||||||
dialog.stream_referer?.doOnTextChanged { text, _, _, _ ->
|
binding.streamReferer.doOnTextChanged { text, _, _, _ ->
|
||||||
if (!preventAutoSwitching)
|
if (!preventAutoSwitching)
|
||||||
activateSwitchOnHls(text?.toString())
|
activateSwitchOnHls(text?.toString())
|
||||||
}
|
}
|
||||||
|
@ -210,16 +224,16 @@ class DownloadFragment : Fragment() {
|
||||||
0
|
0
|
||||||
)?.text?.toString()?.let { copy ->
|
)?.text?.toString()?.let { copy ->
|
||||||
val fixedText = copy.trim()
|
val fixedText = copy.trim()
|
||||||
dialog.stream_url?.setText(fixedText)
|
binding.streamUrl.setText(fixedText)
|
||||||
activateSwitchOnHls(fixedText)
|
activateSwitchOnHls(fixedText)
|
||||||
}
|
}
|
||||||
|
|
||||||
dialog.apply_btt?.setOnClickListener {
|
binding.applyBtt.setOnClickListener {
|
||||||
val url = dialog.stream_url.text?.toString()
|
val url = binding.streamUrl.text?.toString()
|
||||||
if (url.isNullOrEmpty()) {
|
if (url.isNullOrEmpty()) {
|
||||||
showToast(activity, R.string.error_invalid_url, Toast.LENGTH_SHORT)
|
showToast(activity, R.string.error_invalid_url, Toast.LENGTH_SHORT)
|
||||||
} else {
|
} else {
|
||||||
val referer = dialog.stream_referer.text?.toString()
|
val referer = binding.streamReferer.text?.toString()
|
||||||
|
|
||||||
activity?.navigate(
|
activity?.navigate(
|
||||||
R.id.global_to_navigation_player,
|
R.id.global_to_navigation_player,
|
||||||
|
@ -228,7 +242,7 @@ class DownloadFragment : Fragment() {
|
||||||
listOf(BasicLink(url)),
|
listOf(BasicLink(url)),
|
||||||
extract = true,
|
extract = true,
|
||||||
referer = referer,
|
referer = referer,
|
||||||
isM3u8 = dialog.hls_switch?.isChecked
|
isM3u8 = binding.hlsSwitch.isChecked
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
@ -237,22 +251,22 @@ class DownloadFragment : Fragment() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dialog.cancel_btt?.setOnClickListener {
|
binding.cancelBtt.setOnClickListener {
|
||||||
dialog.dismissSafe(activity)
|
dialog.dismissSafe(activity)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||||
download_list?.setOnScrollChangeListener { _, _, scrollY, _, oldScrollY ->
|
binding?.downloadList?.setOnScrollChangeListener { _, _, scrollY, _, oldScrollY ->
|
||||||
val dy = scrollY - oldScrollY
|
val dy = scrollY - oldScrollY
|
||||||
if (dy > 0) { //check for scroll down
|
if (dy > 0) { //check for scroll down
|
||||||
download_stream_button?.shrink() // hide
|
binding?.downloadStreamButton?.shrink() // hide
|
||||||
} else if (dy < -5) {
|
} else if (dy < -5) {
|
||||||
download_stream_button?.extend() // show
|
binding?.downloadStreamButton?.extend() // show
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
downloadsViewModel.updateList(requireContext())
|
downloadsViewModel.updateList(requireContext())
|
||||||
|
|
||||||
context?.fixPaddingStatusbar(download_root)
|
fixPaddingStatusbar(binding?.downloadRoot)
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -34,12 +34,15 @@ import com.lagradost.cloudstream3.AcraApplication.Companion.getKey
|
||||||
import com.lagradost.cloudstream3.MainActivity.Companion.afterPluginsLoadedEvent
|
import com.lagradost.cloudstream3.MainActivity.Companion.afterPluginsLoadedEvent
|
||||||
import com.lagradost.cloudstream3.MainActivity.Companion.bookmarksUpdatedEvent
|
import com.lagradost.cloudstream3.MainActivity.Companion.bookmarksUpdatedEvent
|
||||||
import com.lagradost.cloudstream3.MainActivity.Companion.mainPluginsLoadedEvent
|
import com.lagradost.cloudstream3.MainActivity.Companion.mainPluginsLoadedEvent
|
||||||
|
import com.lagradost.cloudstream3.databinding.FragmentHomeBinding
|
||||||
|
import com.lagradost.cloudstream3.databinding.HomeEpisodesExpandedBinding
|
||||||
|
import com.lagradost.cloudstream3.databinding.HomeSelectMainpageBinding
|
||||||
|
import com.lagradost.cloudstream3.databinding.TvtypesChipsBinding
|
||||||
import com.lagradost.cloudstream3.mvvm.Resource
|
import com.lagradost.cloudstream3.mvvm.Resource
|
||||||
import com.lagradost.cloudstream3.mvvm.logError
|
import com.lagradost.cloudstream3.mvvm.logError
|
||||||
import com.lagradost.cloudstream3.mvvm.observe
|
import com.lagradost.cloudstream3.mvvm.observe
|
||||||
import com.lagradost.cloudstream3.ui.APIRepository.Companion.noneApi
|
import com.lagradost.cloudstream3.ui.APIRepository.Companion.noneApi
|
||||||
import com.lagradost.cloudstream3.ui.APIRepository.Companion.randomApi
|
import com.lagradost.cloudstream3.ui.APIRepository.Companion.randomApi
|
||||||
import com.lagradost.cloudstream3.ui.AutofitRecyclerView
|
|
||||||
import com.lagradost.cloudstream3.ui.WatchType
|
import com.lagradost.cloudstream3.ui.WatchType
|
||||||
import com.lagradost.cloudstream3.ui.quicksearch.QuickSearchFragment
|
import com.lagradost.cloudstream3.ui.quicksearch.QuickSearchFragment
|
||||||
import com.lagradost.cloudstream3.ui.search.*
|
import com.lagradost.cloudstream3.ui.search.*
|
||||||
|
@ -64,24 +67,7 @@ import com.lagradost.cloudstream3.utils.UIHelper.fixPaddingStatusbar
|
||||||
import com.lagradost.cloudstream3.utils.UIHelper.getSpanCount
|
import com.lagradost.cloudstream3.utils.UIHelper.getSpanCount
|
||||||
import com.lagradost.cloudstream3.utils.UIHelper.popupMenuNoIconsAndNoStringRes
|
import com.lagradost.cloudstream3.utils.UIHelper.popupMenuNoIconsAndNoStringRes
|
||||||
import com.lagradost.cloudstream3.utils.USER_SELECTED_HOMEPAGE_API
|
import com.lagradost.cloudstream3.utils.USER_SELECTED_HOMEPAGE_API
|
||||||
import kotlinx.android.synthetic.main.activity_main_tv.*
|
|
||||||
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_change_api_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_shimmer
|
|
||||||
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_reload_connection_open_in_browser
|
|
||||||
import kotlinx.android.synthetic.main.fragment_home.home_reload_connectionerror
|
|
||||||
import kotlinx.android.synthetic.main.fragment_home.result_error_text
|
|
||||||
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.home_episodes_expanded.*
|
|
||||||
import kotlinx.android.synthetic.main.tvtypes_chips.*
|
|
||||||
import kotlinx.android.synthetic.main.tvtypes_chips.view.*
|
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
|
|
||||||
|
@ -125,22 +111,26 @@ class HomeFragment : Fragment() {
|
||||||
expand: HomeViewModel.ExpandableHomepageList,
|
expand: HomeViewModel.ExpandableHomepageList,
|
||||||
deleteCallback: (() -> Unit)? = null,
|
deleteCallback: (() -> Unit)? = null,
|
||||||
expandCallback: (suspend (String) -> HomeViewModel.ExpandableHomepageList?)? = null,
|
expandCallback: (suspend (String) -> HomeViewModel.ExpandableHomepageList?)? = null,
|
||||||
dismissCallback : (() -> Unit),
|
dismissCallback: (() -> Unit),
|
||||||
): BottomSheetDialog {
|
): BottomSheetDialog {
|
||||||
val context = this
|
val context = this
|
||||||
val bottomSheetDialogBuilder = BottomSheetDialog(context)
|
val bottomSheetDialogBuilder = BottomSheetDialog(context)
|
||||||
|
val binding: HomeEpisodesExpandedBinding = HomeEpisodesExpandedBinding.inflate(
|
||||||
bottomSheetDialogBuilder.setContentView(R.layout.home_episodes_expanded)
|
bottomSheetDialogBuilder.layoutInflater,
|
||||||
val title = bottomSheetDialogBuilder.findViewById<TextView>(R.id.home_expanded_text)!!
|
null,
|
||||||
|
false
|
||||||
|
)
|
||||||
|
bottomSheetDialogBuilder.setContentView(binding.root)
|
||||||
|
//val title = bottomSheetDialogBuilder.findViewById<TextView>(R.id.home_expanded_text)!!
|
||||||
|
|
||||||
//title.findViewTreeLifecycleOwner().lifecycle.addObserver()
|
//title.findViewTreeLifecycleOwner().lifecycle.addObserver()
|
||||||
|
|
||||||
val item = expand.list
|
val item = expand.list
|
||||||
title.text = item.name
|
binding.homeExpandedText.text = item.name
|
||||||
val recycle =
|
// val recycle =
|
||||||
bottomSheetDialogBuilder.findViewById<AutofitRecyclerView>(R.id.home_expanded_recycler)!!
|
// bottomSheetDialogBuilder.findViewById<AutofitRecyclerView>(R.id.home_expanded_recycler)!!
|
||||||
val titleHolder =
|
//val titleHolder =
|
||||||
bottomSheetDialogBuilder.findViewById<FrameLayout>(R.id.home_expanded_drag_down)!!
|
// bottomSheetDialogBuilder.findViewById<FrameLayout>(R.id.home_expanded_drag_down)!!
|
||||||
|
|
||||||
// main {
|
// main {
|
||||||
//(bottomSheetDialogBuilder.ownerActivity as androidx.fragment.app.FragmentActivity?)?.supportFragmentManager?.fragments?.lastOrNull()?.viewLifecycleOwner?.apply {
|
//(bottomSheetDialogBuilder.ownerActivity as androidx.fragment.app.FragmentActivity?)?.supportFragmentManager?.fragments?.lastOrNull()?.viewLifecycleOwner?.apply {
|
||||||
|
@ -159,10 +149,10 @@ class HomeFragment : Fragment() {
|
||||||
// })
|
// })
|
||||||
//}
|
//}
|
||||||
// }
|
// }
|
||||||
val delete = bottomSheetDialogBuilder.home_expanded_delete
|
//val delete = bottomSheetDialogBuilder.home_expanded_delete
|
||||||
delete.isGone = deleteCallback == null
|
binding.homeExpandedDelete.isGone = deleteCallback == null
|
||||||
if (deleteCallback != null) {
|
if (deleteCallback != null) {
|
||||||
delete.setOnClickListener {
|
binding.homeExpandedDelete.setOnClickListener {
|
||||||
try {
|
try {
|
||||||
val builder: AlertDialog.Builder = AlertDialog.Builder(context)
|
val builder: AlertDialog.Builder = AlertDialog.Builder(context)
|
||||||
val dialogClickListener =
|
val dialogClickListener =
|
||||||
|
@ -172,6 +162,7 @@ class HomeFragment : Fragment() {
|
||||||
deleteCallback.invoke()
|
deleteCallback.invoke()
|
||||||
bottomSheetDialogBuilder.dismissSafe(this)
|
bottomSheetDialogBuilder.dismissSafe(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
DialogInterface.BUTTON_NEGATIVE -> {}
|
DialogInterface.BUTTON_NEGATIVE -> {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -191,26 +182,27 @@ class HomeFragment : Fragment() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
binding.homeExpandedDragDown.setOnClickListener {
|
||||||
titleHolder.setOnClickListener {
|
|
||||||
bottomSheetDialogBuilder.dismissSafe(this)
|
bottomSheetDialogBuilder.dismissSafe(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Span settings
|
// Span settings
|
||||||
recycle.spanCount = currentSpan
|
binding.homeExpandedRecycler.spanCount = currentSpan
|
||||||
|
|
||||||
recycle.adapter = SearchAdapter(item.list.toMutableList(), recycle) { callback ->
|
binding.homeExpandedRecycler.adapter =
|
||||||
handleSearchClickCallback(this, callback)
|
SearchAdapter(item.list.toMutableList(), binding.homeExpandedRecycler) { callback ->
|
||||||
if (callback.action == SEARCH_ACTION_LOAD || callback.action == SEARCH_ACTION_PLAY_FILE) {
|
handleSearchClickCallback(this, callback)
|
||||||
bottomSheetDialogBuilder.ownHide() // we hide here because we want to resume it later
|
if (callback.action == SEARCH_ACTION_LOAD || callback.action == SEARCH_ACTION_PLAY_FILE) {
|
||||||
//bottomSheetDialogBuilder.dismissSafe(this)
|
bottomSheetDialogBuilder.ownHide() // we hide here because we want to resume it later
|
||||||
|
//bottomSheetDialogBuilder.dismissSafe(this)
|
||||||
|
}
|
||||||
|
}.apply {
|
||||||
|
hasNext = expand.hasNext
|
||||||
}
|
}
|
||||||
}.apply {
|
|
||||||
hasNext = expand.hasNext
|
|
||||||
}
|
|
||||||
|
|
||||||
recycle.addOnScrollListener(object : RecyclerView.OnScrollListener() {
|
binding.homeExpandedRecycler.addOnScrollListener(object :
|
||||||
|
RecyclerView.OnScrollListener() {
|
||||||
var expandCount = 0
|
var expandCount = 0
|
||||||
val name = expand.list.name
|
val name = expand.list.name
|
||||||
|
|
||||||
|
@ -238,7 +230,7 @@ class HomeFragment : Fragment() {
|
||||||
})
|
})
|
||||||
|
|
||||||
val spanListener = { span: Int ->
|
val spanListener = { span: Int ->
|
||||||
recycle.spanCount = span
|
binding.homeExpandedRecycler.spanCount = span
|
||||||
//(recycle.adapter as SearchAdapter).notifyDataSetChanged()
|
//(recycle.adapter as SearchAdapter).notifyDataSetChanged()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -280,19 +272,19 @@ class HomeFragment : Fragment() {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getPairList(header: ChipGroup) = getPairList(
|
private fun getPairList(header: TvtypesChipsBinding) = getPairList(
|
||||||
header.home_select_anime,
|
header.homeSelectAnime,
|
||||||
header.home_select_cartoons,
|
header.homeSelectCartoons,
|
||||||
header.home_select_tv_series,
|
header.homeSelectTvSeries,
|
||||||
header.home_select_documentaries,
|
header.homeSelectDocumentaries,
|
||||||
header.home_select_movies,
|
header.homeSelectMovies,
|
||||||
header.home_select_asian,
|
header.homeSelectAsian,
|
||||||
header.home_select_livestreams,
|
header.homeSelectLivestreams,
|
||||||
header.home_select_nsfw,
|
header.homeSelectNsfw,
|
||||||
header.home_select_others
|
header.homeSelectOthers
|
||||||
)
|
)
|
||||||
|
|
||||||
fun validateChips(header: ChipGroup?, validTypes: List<TvType>) {
|
fun validateChips(header: TvtypesChipsBinding?, validTypes: List<TvType>) {
|
||||||
if (header == null) return
|
if (header == null) return
|
||||||
val pairList = getPairList(header)
|
val pairList = getPairList(header)
|
||||||
for ((button, types) in pairList) {
|
for ((button, types) in pairList) {
|
||||||
|
@ -301,7 +293,7 @@ class HomeFragment : Fragment() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun updateChips(header: ChipGroup?, selectedTypes: List<TvType>) {
|
fun updateChips(header: TvtypesChipsBinding?, selectedTypes: List<TvType>) {
|
||||||
if (header == null) return
|
if (header == null) return
|
||||||
val pairList = getPairList(header)
|
val pairList = getPairList(header)
|
||||||
for ((button, types) in pairList) {
|
for ((button, types) in pairList) {
|
||||||
|
@ -311,7 +303,7 @@ class HomeFragment : Fragment() {
|
||||||
}
|
}
|
||||||
|
|
||||||
fun bindChips(
|
fun bindChips(
|
||||||
header: ChipGroup?,
|
header: TvtypesChipsBinding?,
|
||||||
selectedTypes: List<TvType>,
|
selectedTypes: List<TvType>,
|
||||||
validTypes: List<TvType>,
|
validTypes: List<TvType>,
|
||||||
callback: (List<TvType>) -> Unit
|
callback: (List<TvType>) -> Unit
|
||||||
|
@ -344,7 +336,13 @@ class HomeFragment : Fragment() {
|
||||||
BottomSheetDialog(this)
|
BottomSheetDialog(this)
|
||||||
|
|
||||||
builder.behavior.state = BottomSheetBehavior.STATE_EXPANDED
|
builder.behavior.state = BottomSheetBehavior.STATE_EXPANDED
|
||||||
builder.setContentView(R.layout.home_select_mainpage)
|
val binding: HomeSelectMainpageBinding = HomeSelectMainpageBinding.inflate(
|
||||||
|
builder.layoutInflater,
|
||||||
|
null,
|
||||||
|
false
|
||||||
|
)
|
||||||
|
|
||||||
|
builder.setContentView(binding.root)
|
||||||
builder.show()
|
builder.show()
|
||||||
builder.let { dialog ->
|
builder.let { dialog ->
|
||||||
val isMultiLang = getApiProviderLangSettings().let { set ->
|
val isMultiLang = getApiProviderLangSettings().let { set ->
|
||||||
|
@ -408,7 +406,7 @@ class HomeFragment : Fragment() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bindChips(
|
bindChips(
|
||||||
dialog.home_select_group,
|
binding.tvtypesChipsScroll.tvtypesChips,
|
||||||
preSelectedTypes,
|
preSelectedTypes,
|
||||||
validAPIs.flatMap { it.supportedTypes }.distinct()
|
validAPIs.flatMap { it.supportedTypes }.distinct()
|
||||||
) { list ->
|
) { list ->
|
||||||
|
@ -423,6 +421,9 @@ class HomeFragment : Fragment() {
|
||||||
|
|
||||||
private val homeViewModel: HomeViewModel by activityViewModels()
|
private val homeViewModel: HomeViewModel by activityViewModels()
|
||||||
|
|
||||||
|
var binding: FragmentHomeBinding? = null
|
||||||
|
|
||||||
|
|
||||||
override fun onCreateView(
|
override fun onCreateView(
|
||||||
inflater: LayoutInflater,
|
inflater: LayoutInflater,
|
||||||
container: ViewGroup?,
|
container: ViewGroup?,
|
||||||
|
@ -433,11 +434,24 @@ class HomeFragment : Fragment() {
|
||||||
bottomSheetDialog?.ownShow()
|
bottomSheetDialog?.ownShow()
|
||||||
val layout =
|
val layout =
|
||||||
if (isTvSettings()) R.layout.fragment_home_tv else R.layout.fragment_home
|
if (isTvSettings()) R.layout.fragment_home_tv else R.layout.fragment_home
|
||||||
return inflater.inflate(layout, container, false)
|
|
||||||
|
/* val binding = FragmentHomeTvBinding.inflate(layout, container, false)
|
||||||
|
binding.homeLoadingError
|
||||||
|
|
||||||
|
val binding2 = FragmentHomeBinding.inflate(layout, container, false)
|
||||||
|
binding2.homeLoadingError*/
|
||||||
|
val root = inflater.inflate(layout, container, false)
|
||||||
|
binding = FragmentHomeBinding.bind(root)
|
||||||
|
//val localBinding = FragmentHomeBinding.inflate(inflater)
|
||||||
|
//binding = localBinding
|
||||||
|
return root
|
||||||
|
|
||||||
|
//return inflater.inflate(layout, container, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDestroyView() {
|
override fun onDestroyView() {
|
||||||
bottomSheetDialog?.ownHide()
|
bottomSheetDialog?.ownHide()
|
||||||
|
binding = null
|
||||||
super.onDestroyView()
|
super.onDestroyView()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -467,7 +481,7 @@ class HomeFragment : Fragment() {
|
||||||
fixGrid()
|
fixGrid()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun bookmarksUpdated(_data : Boolean) {
|
fun bookmarksUpdated(_data: Boolean) {
|
||||||
reloadStored()
|
reloadStored()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -525,14 +539,18 @@ class HomeFragment : Fragment() {
|
||||||
|
|
||||||
private var bottomSheetDialog: BottomSheetDialog? = null
|
private var bottomSheetDialog: BottomSheetDialog? = null
|
||||||
|
|
||||||
|
|
||||||
@SuppressLint("SetTextI18n")
|
@SuppressLint("SetTextI18n")
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
fixGrid()
|
fixGrid()
|
||||||
|
|
||||||
home_change_api_loading?.setOnClickListener(apiChangeClickListener)
|
binding?.homeChangeApiLoading?.setOnClickListener(apiChangeClickListener)
|
||||||
home_api_fab?.setOnClickListener(apiChangeClickListener)
|
|
||||||
home_random?.setOnClickListener {
|
|
||||||
|
binding?.homeChangeApiLoading?.setOnClickListener(apiChangeClickListener)
|
||||||
|
binding?.homeApiFab?.setOnClickListener(apiChangeClickListener)
|
||||||
|
binding?.homeRandom?.setOnClickListener {
|
||||||
if (listHomepageItems.isNotEmpty()) {
|
if (listHomepageItems.isNotEmpty()) {
|
||||||
activity.loadSearchResult(listHomepageItems.random())
|
activity.loadSearchResult(listHomepageItems.random())
|
||||||
}
|
}
|
||||||
|
@ -542,91 +560,100 @@ class HomeFragment : Fragment() {
|
||||||
context?.let {
|
context?.let {
|
||||||
val settingsManager = PreferenceManager.getDefaultSharedPreferences(it)
|
val settingsManager = PreferenceManager.getDefaultSharedPreferences(it)
|
||||||
toggleRandomButton =
|
toggleRandomButton =
|
||||||
settingsManager.getBoolean(getString(R.string.random_button_key), false)
|
settingsManager.getBoolean(
|
||||||
home_random?.visibility = View.GONE
|
getString(R.string.random_button_key),
|
||||||
|
false
|
||||||
|
) && !isTvSettings()
|
||||||
|
binding?.homeRandom?.visibility = View.GONE
|
||||||
}
|
}
|
||||||
|
|
||||||
observe(homeViewModel.preview) { preview ->
|
observe(homeViewModel.preview) { preview ->
|
||||||
(home_master_recycler?.adapter as? HomeParentItemAdapterPreview?)?.setPreviewData(
|
(binding?.homeMasterRecycler?.adapter as? HomeParentItemAdapterPreview?)?.setPreviewData(
|
||||||
preview
|
preview
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
observe(homeViewModel.apiName) { apiName ->
|
observe(homeViewModel.apiName) { apiName ->
|
||||||
currentApiName = apiName
|
currentApiName = apiName
|
||||||
home_api_fab?.text = apiName
|
binding?.homeApiFab?.text = apiName
|
||||||
(home_master_recycler?.adapter as? HomeParentItemAdapterPreview?)?.setApiName(
|
(binding?.homeMasterRecycler?.adapter as? HomeParentItemAdapterPreview?)?.setApiName(
|
||||||
apiName
|
apiName
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
observe(homeViewModel.page) { data ->
|
observe(homeViewModel.page) { data ->
|
||||||
when (data) {
|
binding?.apply {
|
||||||
is Resource.Success -> {
|
when (data) {
|
||||||
home_loading_shimmer?.stopShimmer()
|
is Resource.Success -> {
|
||||||
|
homeLoadingShimmer.stopShimmer()
|
||||||
|
|
||||||
val d = data.value
|
val d = data.value
|
||||||
val mutableListOfResponse = mutableListOf<SearchResponse>()
|
val mutableListOfResponse = mutableListOf<SearchResponse>()
|
||||||
listHomepageItems.clear()
|
listHomepageItems.clear()
|
||||||
|
|
||||||
(home_master_recycler?.adapter as? ParentItemAdapter)?.updateList(
|
(homeMasterRecycler.adapter as? ParentItemAdapter)?.updateList(
|
||||||
d.values.toMutableList(),
|
d.values.toMutableList(),
|
||||||
home_master_recycler
|
homeMasterRecycler
|
||||||
)
|
)
|
||||||
|
|
||||||
home_loading?.isVisible = false
|
homeLoading.isVisible = false
|
||||||
home_loading_error?.isVisible = false
|
homeLoadingError.isVisible = false
|
||||||
home_master_recycler?.isVisible = true
|
homeMasterRecycler.isVisible = true
|
||||||
//home_loaded?.isVisible = true
|
//home_loaded?.isVisible = true
|
||||||
if (toggleRandomButton) {
|
if (toggleRandomButton) {
|
||||||
//Flatten list
|
//Flatten list
|
||||||
d.values.forEach { dlist ->
|
d.values.forEach { dlist ->
|
||||||
mutableListOfResponse.addAll(dlist.list.list)
|
mutableListOfResponse.addAll(dlist.list.list)
|
||||||
|
}
|
||||||
|
listHomepageItems.addAll(mutableListOfResponse.distinctBy { it.url })
|
||||||
|
|
||||||
|
homeRandom.isVisible = listHomepageItems.isNotEmpty()
|
||||||
|
} else {
|
||||||
|
homeRandom.isGone = true
|
||||||
}
|
}
|
||||||
listHomepageItems.addAll(mutableListOfResponse.distinctBy { it.url })
|
|
||||||
home_random?.isVisible = listHomepageItems.isNotEmpty()
|
|
||||||
} else {
|
|
||||||
home_random?.isGone = true
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
is Resource.Failure -> {
|
|
||||||
home_loading_shimmer?.stopShimmer()
|
|
||||||
|
|
||||||
result_error_text.text = data.errorString
|
is Resource.Failure -> {
|
||||||
|
|
||||||
home_reload_connectionerror.setOnClickListener(apiChangeClickListener)
|
homeLoadingShimmer.stopShimmer()
|
||||||
|
|
||||||
home_reload_connection_open_in_browser.setOnClickListener { view ->
|
resultErrorText.text = data.errorString
|
||||||
val validAPIs = apis//.filter { api -> api.hasMainPage }
|
|
||||||
|
|
||||||
view.popupMenuNoIconsAndNoStringRes(validAPIs.mapIndexed { index, api ->
|
homeReloadConnectionerror.setOnClickListener(apiChangeClickListener)
|
||||||
Pair(
|
|
||||||
index,
|
homeReloadConnectionOpenInBrowser.setOnClickListener { view ->
|
||||||
api.name
|
val validAPIs = apis//.filter { api -> api.hasMainPage }
|
||||||
)
|
|
||||||
}) {
|
view.popupMenuNoIconsAndNoStringRes(validAPIs.mapIndexed { index, api ->
|
||||||
try {
|
Pair(
|
||||||
val i = Intent(Intent.ACTION_VIEW)
|
index,
|
||||||
i.data = Uri.parse(validAPIs[itemId].mainUrl)
|
api.name
|
||||||
startActivity(i)
|
)
|
||||||
} catch (e: Exception) {
|
}) {
|
||||||
logError(e)
|
try {
|
||||||
|
val i = Intent(Intent.ACTION_VIEW)
|
||||||
|
i.data = Uri.parse(validAPIs[itemId].mainUrl)
|
||||||
|
startActivity(i)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
logError(e)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
homeLoading.isVisible = false
|
||||||
|
homeLoadingError.isVisible = true
|
||||||
|
homeMasterRecycler.isVisible = false
|
||||||
|
//home_loaded?.isVisible = false
|
||||||
}
|
}
|
||||||
|
|
||||||
home_loading?.isVisible = false
|
is Resource.Loading -> {
|
||||||
home_loading_error?.isVisible = true
|
(homeMasterRecycler.adapter as? ParentItemAdapter)?.updateList(listOf())
|
||||||
home_master_recycler?.isVisible = false
|
homeLoadingShimmer.startShimmer()
|
||||||
//home_loaded?.isVisible = false
|
homeLoading.isVisible = true
|
||||||
}
|
homeLoadingError.isVisible = false
|
||||||
is Resource.Loading -> {
|
homeMasterRecycler.isVisible = false
|
||||||
(home_master_recycler?.adapter as? ParentItemAdapter)?.updateList(listOf())
|
//home_loaded?.isVisible = false
|
||||||
home_loading_shimmer?.startShimmer()
|
}
|
||||||
home_loading?.isVisible = true
|
|
||||||
home_loading_error?.isVisible = false
|
|
||||||
home_master_recycler?.isVisible = false
|
|
||||||
//home_loaded?.isVisible = false
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -638,19 +665,19 @@ class HomeFragment : Fragment() {
|
||||||
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(
|
(binding?.homeMasterRecycler?.adapter as? HomeParentItemAdapterPreview?)?.setAvailableWatchStatusTypes(
|
||||||
availableWatchStatusTypes
|
availableWatchStatusTypes
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
observe(homeViewModel.bookmarks) { data ->
|
observe(homeViewModel.bookmarks) { data ->
|
||||||
(home_master_recycler?.adapter as? HomeParentItemAdapterPreview?)?.setBookmarkData(
|
(binding?.homeMasterRecycler?.adapter as? HomeParentItemAdapterPreview?)?.setBookmarkData(
|
||||||
data
|
data
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
observe(homeViewModel.resumeWatching) { resumeWatching ->
|
observe(homeViewModel.resumeWatching) { resumeWatching ->
|
||||||
(home_master_recycler?.adapter as? HomeParentItemAdapterPreview?)?.setResumeWatchingData(
|
(binding?.homeMasterRecycler?.adapter as? HomeParentItemAdapterPreview?)?.setResumeWatchingData(
|
||||||
resumeWatching
|
resumeWatching
|
||||||
)
|
)
|
||||||
if (isTrueTvSettings()) {
|
if (isTrueTvSettings()) {
|
||||||
|
@ -665,9 +692,9 @@ class HomeFragment : Fragment() {
|
||||||
|
|
||||||
//context?.fixPaddingStatusbarView(home_statusbar)
|
//context?.fixPaddingStatusbarView(home_statusbar)
|
||||||
//context?.fixPaddingStatusbar(home_padding)
|
//context?.fixPaddingStatusbar(home_padding)
|
||||||
context?.fixPaddingStatusbar(home_loading_statusbar)
|
fixPaddingStatusbar(binding?.homeLoadingStatusbar)
|
||||||
|
|
||||||
home_master_recycler?.adapter =
|
binding?.homeMasterRecycler?.adapter =
|
||||||
HomeParentItemAdapterPreview(mutableListOf(), { callback ->
|
HomeParentItemAdapterPreview(mutableListOf(), { callback ->
|
||||||
homeHandleSearch(callback)
|
homeHandleSearch(callback)
|
||||||
}, { item ->
|
}, { item ->
|
||||||
|
@ -699,18 +726,22 @@ class HomeFragment : Fragment() {
|
||||||
|
|
||||||
reloadStored()
|
reloadStored()
|
||||||
loadHomePage(false)
|
loadHomePage(false)
|
||||||
home_master_recycler?.addOnScrollListener(object : RecyclerView.OnScrollListener() {
|
binding?.homeMasterRecycler?.addOnScrollListener(object : RecyclerView.OnScrollListener() {
|
||||||
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
|
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
|
||||||
if (dy > 0) { //check for scroll down
|
|
||||||
home_api_fab?.shrink() // hide
|
binding?.apply {
|
||||||
home_random?.shrink()
|
if (dy > 0) { //check for scroll down
|
||||||
} else if (dy < -5) {
|
homeApiFab.shrink() // hide
|
||||||
if (!isTvSettings()) {
|
homeRandom.shrink()
|
||||||
home_api_fab?.extend() // show
|
} else if (dy < -5) {
|
||||||
home_random?.extend()
|
if (!isTvSettings()) {
|
||||||
|
homeApiFab.extend() // show
|
||||||
|
homeRandom.extend()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
super.onScrolled(recyclerView, dx, dy)
|
super.onScrolled(recyclerView, dx, dy)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -718,18 +749,20 @@ 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()) {
|
binding?.apply {
|
||||||
home_api_fab?.isVisible = false
|
if (isTvSettings()) {
|
||||||
if (isTrueTvSettings()) {
|
homeApiFab.isVisible = false
|
||||||
home_change_api_loading?.isVisible = true
|
if (isTrueTvSettings()) {
|
||||||
home_change_api_loading?.isFocusable = true
|
homeChangeApiLoading.isVisible = true
|
||||||
home_change_api_loading?.isFocusableInTouchMode = true
|
homeChangeApiLoading.isFocusable = true
|
||||||
|
homeChangeApiLoading.isFocusableInTouchMode = true
|
||||||
|
}
|
||||||
|
// home_bookmark_select?.isFocusable = true
|
||||||
|
// home_bookmark_select?.isFocusableInTouchMode = true
|
||||||
|
} else {
|
||||||
|
homeApiFab.isVisible = true
|
||||||
|
homeChangeApiLoading.isVisible = false
|
||||||
}
|
}
|
||||||
// home_bookmark_select?.isFocusable = true
|
|
||||||
// home_bookmark_select?.isFocusableInTouchMode = true
|
|
||||||
} else {
|
|
||||||
home_api_fab?.isVisible = true
|
|
||||||
home_change_api_loading?.isVisible = false
|
|
||||||
}
|
}
|
||||||
//TODO READD THIS
|
//TODO READD THIS
|
||||||
/*for (syncApi in OAuth2Apis) {
|
/*for (syncApi in OAuth2Apis) {
|
||||||
|
|
|
@ -544,7 +544,7 @@ class HomeParentItemAdapterPreview(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
itemView.home_search?.context?.fixPaddingStatusbar(itemView.home_search)
|
fixPaddingStatusbar(itemView.home_search)
|
||||||
|
|
||||||
itemView.home_search?.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
|
itemView.home_search?.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
|
||||||
override fun onQueryTextSubmit(query: String): Boolean {
|
override fun onQueryTextSubmit(query: String): Boolean {
|
||||||
|
@ -575,7 +575,7 @@ class HomeParentItemAdapterPreview(
|
||||||
layoutParams = params
|
layoutParams = params
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
itemView.home_none_padding?.context?.fixPaddingStatusbarView(itemView.home_none_padding)
|
fixPaddingStatusbarView(itemView.home_none_padding)
|
||||||
}
|
}
|
||||||
when (preview) {
|
when (preview) {
|
||||||
is Resource.Success -> {
|
is Resource.Success -> {
|
||||||
|
|
|
@ -6,7 +6,6 @@ import android.content.res.Configuration
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
import android.os.Looper
|
import android.os.Looper
|
||||||
import androidx.fragment.app.Fragment
|
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
|
@ -14,6 +13,7 @@ import android.view.animation.AlphaAnimation
|
||||||
import androidx.annotation.StringRes
|
import androidx.annotation.StringRes
|
||||||
import androidx.appcompat.widget.SearchView
|
import androidx.appcompat.widget.SearchView
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.fragment.app.activityViewModels
|
import androidx.fragment.app.activityViewModels
|
||||||
import com.google.android.material.tabs.TabLayoutMediator
|
import com.google.android.material.tabs.TabLayoutMediator
|
||||||
import com.lagradost.cloudstream3.APIHolder
|
import com.lagradost.cloudstream3.APIHolder
|
||||||
|
@ -22,6 +22,7 @@ import com.lagradost.cloudstream3.AcraApplication.Companion.getKey
|
||||||
import com.lagradost.cloudstream3.AcraApplication.Companion.openBrowser
|
import com.lagradost.cloudstream3.AcraApplication.Companion.openBrowser
|
||||||
import com.lagradost.cloudstream3.AcraApplication.Companion.setKey
|
import com.lagradost.cloudstream3.AcraApplication.Companion.setKey
|
||||||
import com.lagradost.cloudstream3.R
|
import com.lagradost.cloudstream3.R
|
||||||
|
import com.lagradost.cloudstream3.databinding.FragmentLibraryBinding
|
||||||
import com.lagradost.cloudstream3.mvvm.Resource
|
import com.lagradost.cloudstream3.mvvm.Resource
|
||||||
import com.lagradost.cloudstream3.mvvm.debugAssert
|
import com.lagradost.cloudstream3.mvvm.debugAssert
|
||||||
import com.lagradost.cloudstream3.mvvm.observe
|
import com.lagradost.cloudstream3.mvvm.observe
|
||||||
|
@ -37,7 +38,6 @@ import com.lagradost.cloudstream3.utils.AppUtils.reduceDragSensitivity
|
||||||
import com.lagradost.cloudstream3.utils.SingleSelectionHelper.showBottomDialog
|
import com.lagradost.cloudstream3.utils.SingleSelectionHelper.showBottomDialog
|
||||||
import com.lagradost.cloudstream3.utils.UIHelper.fixPaddingStatusbar
|
import com.lagradost.cloudstream3.utils.UIHelper.fixPaddingStatusbar
|
||||||
import com.lagradost.cloudstream3.utils.UIHelper.getSpanCount
|
import com.lagradost.cloudstream3.utils.UIHelper.getSpanCount
|
||||||
import kotlinx.android.synthetic.main.fragment_library.*
|
|
||||||
import kotlin.math.abs
|
import kotlin.math.abs
|
||||||
|
|
||||||
const val LIBRARY_FOLDER = "library_folder"
|
const val LIBRARY_FOLDER = "library_folder"
|
||||||
|
@ -73,14 +73,25 @@ class LibraryFragment : Fragment() {
|
||||||
|
|
||||||
private val libraryViewModel: LibraryViewModel by activityViewModels()
|
private val libraryViewModel: LibraryViewModel by activityViewModels()
|
||||||
|
|
||||||
|
var binding: FragmentLibraryBinding? = null
|
||||||
|
|
||||||
override fun onCreateView(
|
override fun onCreateView(
|
||||||
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
|
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
|
||||||
): View? {
|
): View {
|
||||||
return inflater.inflate(R.layout.fragment_library, container, false)
|
val localBinding = FragmentLibraryBinding.inflate(inflater, container, false)
|
||||||
|
binding = localBinding
|
||||||
|
return localBinding.root
|
||||||
|
|
||||||
|
//return inflater.inflate(R.layout.fragment_library, container, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDestroyView() {
|
||||||
|
binding = null
|
||||||
|
super.onDestroyView()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onSaveInstanceState(outState: Bundle) {
|
override fun onSaveInstanceState(outState: Bundle) {
|
||||||
viewpager?.currentItem?.let { currentItem ->
|
binding?.viewpager?.currentItem?.let { currentItem ->
|
||||||
outState.putInt(VIEWPAGER_ITEM_KEY, currentItem)
|
outState.putInt(VIEWPAGER_ITEM_KEY, currentItem)
|
||||||
}
|
}
|
||||||
super.onSaveInstanceState(outState)
|
super.onSaveInstanceState(outState)
|
||||||
|
@ -88,9 +99,9 @@ class LibraryFragment : Fragment() {
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
context?.fixPaddingStatusbar(search_status_bar_padding)
|
fixPaddingStatusbar(binding?.searchStatusBarPadding)
|
||||||
|
|
||||||
sort_fab?.setOnClickListener {
|
binding?.sortFab?.setOnClickListener {
|
||||||
val methods = libraryViewModel.sortingMethods.map {
|
val methods = libraryViewModel.sortingMethods.map {
|
||||||
txt(it.stringRes).asString(view.context)
|
txt(it.stringRes).asString(view.context)
|
||||||
}
|
}
|
||||||
|
@ -106,7 +117,7 @@ class LibraryFragment : Fragment() {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
main_search?.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
|
binding?.mainSearch?.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
|
||||||
override fun onQueryTextSubmit(query: String?): Boolean {
|
override fun onQueryTextSubmit(query: String?): Boolean {
|
||||||
libraryViewModel.sort(ListSorting.Query, query)
|
libraryViewModel.sort(ListSorting.Query, query)
|
||||||
return true
|
return true
|
||||||
|
@ -129,7 +140,7 @@ class LibraryFragment : Fragment() {
|
||||||
|
|
||||||
libraryViewModel.reloadPages(false)
|
libraryViewModel.reloadPages(false)
|
||||||
|
|
||||||
list_selector?.setOnClickListener {
|
binding?.listSelector?.setOnClickListener {
|
||||||
val items = libraryViewModel.availableApiNames
|
val items = libraryViewModel.availableApiNames
|
||||||
val currentItem = libraryViewModel.currentApiName.value
|
val currentItem = libraryViewModel.currentApiName.value
|
||||||
|
|
||||||
|
@ -209,20 +220,22 @@ class LibraryFragment : Fragment() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
provider_selector?.setOnClickListener {
|
binding?.providerSelector?.setOnClickListener {
|
||||||
val syncName = libraryViewModel.currentSyncApi?.syncIdName ?: return@setOnClickListener
|
val syncName = libraryViewModel.currentSyncApi?.syncIdName ?: return@setOnClickListener
|
||||||
activity?.showPluginSelectionDialog(syncName.name, syncName)
|
activity?.showPluginSelectionDialog(syncName.name, syncName)
|
||||||
}
|
}
|
||||||
|
|
||||||
viewpager?.setPageTransformer(LibraryScrollTransformer())
|
binding?.viewpager?.setPageTransformer(LibraryScrollTransformer())
|
||||||
viewpager?.adapter =
|
binding?.viewpager?.adapter =
|
||||||
viewpager.adapter ?: ViewpagerAdapter(mutableListOf(), { isScrollingDown: Boolean ->
|
binding?.viewpager?.adapter ?: ViewpagerAdapter(
|
||||||
if (isScrollingDown) {
|
mutableListOf(),
|
||||||
sort_fab?.shrink()
|
{ isScrollingDown: Boolean ->
|
||||||
} else {
|
if (isScrollingDown) {
|
||||||
sort_fab?.extend()
|
binding?.sortFab?.shrink()
|
||||||
}
|
} else {
|
||||||
}) callback@{ searchClickCallback ->
|
binding?.sortFab?.extend()
|
||||||
|
}
|
||||||
|
}) callback@{ searchClickCallback ->
|
||||||
// To prevent future accidents
|
// To prevent future accidents
|
||||||
debugAssert({
|
debugAssert({
|
||||||
searchClickCallback.card !is SyncAPI.LibraryItem
|
searchClickCallback.card !is SyncAPI.LibraryItem
|
||||||
|
@ -267,6 +280,7 @@ class LibraryFragment : Fragment() {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LibraryOpenerType.None -> {}
|
LibraryOpenerType.None -> {}
|
||||||
LibraryOpenerType.Provider ->
|
LibraryOpenerType.Provider ->
|
||||||
savedSelection.providerData?.apiName?.let { apiName ->
|
savedSelection.providerData?.apiName?.let { apiName ->
|
||||||
|
@ -275,8 +289,10 @@ class LibraryFragment : Fragment() {
|
||||||
apiName,
|
apiName,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
LibraryOpenerType.Browser ->
|
LibraryOpenerType.Browser ->
|
||||||
openBrowser(searchClickCallback.card.url)
|
openBrowser(searchClickCallback.card.url)
|
||||||
|
|
||||||
LibraryOpenerType.Search -> {
|
LibraryOpenerType.Search -> {
|
||||||
QuickSearchFragment.pushSearch(
|
QuickSearchFragment.pushSearch(
|
||||||
activity,
|
activity,
|
||||||
|
@ -288,22 +304,28 @@ class LibraryFragment : Fragment() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
viewpager?.offscreenPageLimit = 2
|
binding?.apply {
|
||||||
viewpager?.reduceDragSensitivity()
|
viewpager.offscreenPageLimit = 2
|
||||||
|
viewpager.reduceDragSensitivity()
|
||||||
|
}
|
||||||
|
|
||||||
val startLoading = Runnable {
|
val startLoading = Runnable {
|
||||||
gridview?.numColumns = context?.getSpanCount() ?: 3
|
binding?.apply {
|
||||||
gridview?.adapter =
|
gridview.numColumns = context?.getSpanCount() ?: 3
|
||||||
context?.let { LoadingPosterAdapter(it, 6 * 3) }
|
gridview.adapter =
|
||||||
library_loading_overlay?.isVisible = true
|
context?.let { LoadingPosterAdapter(it, 6 * 3) }
|
||||||
library_loading_shimmer?.startShimmer()
|
libraryLoadingOverlay.isVisible = true
|
||||||
empty_list_textview?.isVisible = false
|
libraryLoadingShimmer.startShimmer()
|
||||||
|
emptyListTextview.isVisible = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val stopLoading = Runnable {
|
val stopLoading = Runnable {
|
||||||
gridview?.adapter = null
|
binding?.apply {
|
||||||
library_loading_overlay?.isVisible = false
|
gridview.adapter = null
|
||||||
library_loading_shimmer?.stopShimmer()
|
libraryLoadingOverlay.isVisible = false
|
||||||
|
libraryLoadingShimmer.stopShimmer()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val handler = Handler(Looper.getMainLooper())
|
val handler = Handler(Looper.getMainLooper())
|
||||||
|
@ -314,65 +336,75 @@ class LibraryFragment : Fragment() {
|
||||||
handler.removeCallbacks(startLoading)
|
handler.removeCallbacks(startLoading)
|
||||||
val pages = resource.value
|
val pages = resource.value
|
||||||
val showNotice = pages.all { it.items.isEmpty() }
|
val showNotice = pages.all { it.items.isEmpty() }
|
||||||
empty_list_textview?.isVisible = showNotice
|
|
||||||
if (showNotice) {
|
|
||||||
if (libraryViewModel.availableApiNames.size > 1) {
|
binding?.apply {
|
||||||
empty_list_textview?.setText(R.string.empty_library_logged_in_message)
|
emptyListTextview.isVisible = showNotice
|
||||||
} else {
|
if (showNotice) {
|
||||||
empty_list_textview?.setText(R.string.empty_library_no_accounts_message)
|
if (libraryViewModel.availableApiNames.size > 1) {
|
||||||
|
emptyListTextview.setText(R.string.empty_library_logged_in_message)
|
||||||
|
} else {
|
||||||
|
emptyListTextview.setText(R.string.empty_library_no_accounts_message)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
(viewpager.adapter as? ViewpagerAdapter)?.pages = pages
|
||||||
|
// Using notifyItemRangeChanged keeps the animations when sorting
|
||||||
|
viewpager.adapter?.notifyItemRangeChanged(
|
||||||
|
0,
|
||||||
|
viewpager.adapter?.itemCount ?: 0
|
||||||
|
)
|
||||||
|
|
||||||
|
// Only stop loading after 300ms to hide the fade effect the viewpager produces when updating
|
||||||
|
// Without this there would be a flashing effect:
|
||||||
|
// loading -> show old viewpager -> black screen -> show new viewpager
|
||||||
|
handler.postDelayed(stopLoading, 300)
|
||||||
|
|
||||||
|
savedInstanceState?.getInt(VIEWPAGER_ITEM_KEY)?.let { currentPos ->
|
||||||
|
if (currentPos < 0) return@let
|
||||||
|
viewpager.setCurrentItem(currentPos, false)
|
||||||
|
// Using remove() sets the key to 0 instead of removing it
|
||||||
|
savedInstanceState.putInt(VIEWPAGER_ITEM_KEY, -1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Since the animation to scroll multiple items is so much its better to just hide
|
||||||
|
// the viewpager a bit while the fastest animation is running
|
||||||
|
fun hideViewpager(distance: Int) {
|
||||||
|
if (distance < 3) return
|
||||||
|
|
||||||
|
val hideAnimation = AlphaAnimation(1f, 0f).apply {
|
||||||
|
duration = distance * 50L
|
||||||
|
fillAfter = true
|
||||||
|
}
|
||||||
|
val showAnimation = AlphaAnimation(0f, 1f).apply {
|
||||||
|
duration = distance * 50L
|
||||||
|
startOffset = distance * 100L
|
||||||
|
fillAfter = true
|
||||||
|
}
|
||||||
|
viewpager.startAnimation(hideAnimation)
|
||||||
|
viewpager.startAnimation(showAnimation)
|
||||||
|
}
|
||||||
|
|
||||||
|
TabLayoutMediator(
|
||||||
|
libraryTabLayout,
|
||||||
|
viewpager,
|
||||||
|
) { tab, position ->
|
||||||
|
tab.text = pages.getOrNull(position)?.title?.asStringNull(context)
|
||||||
|
tab.view.setOnClickListener {
|
||||||
|
val currentItem =
|
||||||
|
binding?.viewpager?.currentItem ?: return@setOnClickListener
|
||||||
|
val distance = abs(position - currentItem)
|
||||||
|
hideViewpager(distance)
|
||||||
|
}
|
||||||
|
}.attach()
|
||||||
}
|
}
|
||||||
|
|
||||||
(viewpager.adapter as? ViewpagerAdapter)?.pages = pages
|
|
||||||
// Using notifyItemRangeChanged keeps the animations when sorting
|
|
||||||
viewpager.adapter?.notifyItemRangeChanged(0, viewpager.adapter?.itemCount ?: 0)
|
|
||||||
|
|
||||||
// Only stop loading after 300ms to hide the fade effect the viewpager produces when updating
|
|
||||||
// Without this there would be a flashing effect:
|
|
||||||
// loading -> show old viewpager -> black screen -> show new viewpager
|
|
||||||
handler.postDelayed(stopLoading, 300)
|
|
||||||
|
|
||||||
savedInstanceState?.getInt(VIEWPAGER_ITEM_KEY)?.let { currentPos ->
|
|
||||||
if (currentPos < 0) return@let
|
|
||||||
viewpager?.setCurrentItem(currentPos, false)
|
|
||||||
// Using remove() sets the key to 0 instead of removing it
|
|
||||||
savedInstanceState.putInt(VIEWPAGER_ITEM_KEY, -1)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Since the animation to scroll multiple items is so much its better to just hide
|
|
||||||
// the viewpager a bit while the fastest animation is running
|
|
||||||
fun hideViewpager(distance: Int) {
|
|
||||||
if (distance < 3) return
|
|
||||||
|
|
||||||
val hideAnimation = AlphaAnimation(1f, 0f).apply {
|
|
||||||
duration = distance * 50L
|
|
||||||
fillAfter = true
|
|
||||||
}
|
|
||||||
val showAnimation = AlphaAnimation(0f, 1f).apply {
|
|
||||||
duration = distance * 50L
|
|
||||||
startOffset = distance * 100L
|
|
||||||
fillAfter = true
|
|
||||||
}
|
|
||||||
viewpager?.startAnimation(hideAnimation)
|
|
||||||
viewpager?.startAnimation(showAnimation)
|
|
||||||
}
|
|
||||||
|
|
||||||
TabLayoutMediator(
|
|
||||||
library_tab_layout,
|
|
||||||
viewpager,
|
|
||||||
) { tab, position ->
|
|
||||||
tab.text = pages.getOrNull(position)?.title?.asStringNull(context)
|
|
||||||
tab.view.setOnClickListener {
|
|
||||||
val currentItem = viewpager?.currentItem ?: return@setOnClickListener
|
|
||||||
val distance = abs(position - currentItem)
|
|
||||||
hideViewpager(distance)
|
|
||||||
}
|
|
||||||
}.attach()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
is Resource.Loading -> {
|
is Resource.Loading -> {
|
||||||
// Only start loading after 200ms to prevent loading cached lists
|
// Only start loading after 200ms to prevent loading cached lists
|
||||||
handler.postDelayed(startLoading, 200)
|
handler.postDelayed(startLoading, 200)
|
||||||
}
|
}
|
||||||
|
|
||||||
is Resource.Failure -> {
|
is Resource.Failure -> {
|
||||||
stopLoading.run()
|
stopLoading.run()
|
||||||
// No user indication it failed :(
|
// No user indication it failed :(
|
||||||
|
@ -383,7 +415,7 @@ class LibraryFragment : Fragment() {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onConfigurationChanged(newConfig: Configuration) {
|
override fun onConfigurationChanged(newConfig: Configuration) {
|
||||||
(viewpager.adapter as? ViewpagerAdapter)?.rebind()
|
(binding?.viewpager?.adapter as? ViewpagerAdapter)?.rebind()
|
||||||
super.onConfigurationChanged(newConfig)
|
super.onConfigurationChanged(newConfig)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,6 @@ import com.lagradost.cloudstream3.mvvm.Resource
|
||||||
import com.lagradost.cloudstream3.syncproviders.AccountManager.Companion.SyncApis
|
import com.lagradost.cloudstream3.syncproviders.AccountManager.Companion.SyncApis
|
||||||
import com.lagradost.cloudstream3.syncproviders.SyncAPI
|
import com.lagradost.cloudstream3.syncproviders.SyncAPI
|
||||||
import com.lagradost.cloudstream3.utils.Coroutines.ioSafe
|
import com.lagradost.cloudstream3.utils.Coroutines.ioSafe
|
||||||
import kotlinx.coroutines.delay
|
|
||||||
|
|
||||||
enum class ListSorting(@StringRes val stringRes: Int) {
|
enum class ListSorting(@StringRes val stringRes: Int) {
|
||||||
Query(R.string.none),
|
Query(R.string.none),
|
||||||
|
|
|
@ -3,23 +3,21 @@ package com.lagradost.cloudstream3.ui.library
|
||||||
import android.content.res.ColorStateList
|
import android.content.res.ColorStateList
|
||||||
import android.graphics.Color
|
import android.graphics.Color
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.FrameLayout
|
import android.widget.FrameLayout
|
||||||
import android.widget.ImageView
|
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.core.graphics.ColorUtils
|
import androidx.core.graphics.ColorUtils
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import com.lagradost.cloudstream3.AcraApplication
|
import com.lagradost.cloudstream3.AcraApplication
|
||||||
import com.lagradost.cloudstream3.R
|
import com.lagradost.cloudstream3.R
|
||||||
|
import com.lagradost.cloudstream3.databinding.SearchResultGridExpandedBinding
|
||||||
import com.lagradost.cloudstream3.syncproviders.SyncAPI
|
import com.lagradost.cloudstream3.syncproviders.SyncAPI
|
||||||
import com.lagradost.cloudstream3.ui.AutofitRecyclerView
|
import com.lagradost.cloudstream3.ui.AutofitRecyclerView
|
||||||
import com.lagradost.cloudstream3.ui.search.SearchClickCallback
|
import com.lagradost.cloudstream3.ui.search.SearchClickCallback
|
||||||
import com.lagradost.cloudstream3.ui.search.SearchResultBuilder
|
import com.lagradost.cloudstream3.ui.search.SearchResultBuilder
|
||||||
import com.lagradost.cloudstream3.utils.AppUtils
|
import com.lagradost.cloudstream3.utils.AppUtils
|
||||||
import com.lagradost.cloudstream3.utils.UIHelper.toPx
|
import com.lagradost.cloudstream3.utils.UIHelper.toPx
|
||||||
import kotlinx.android.synthetic.main.search_result_grid_expanded.view.*
|
|
||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
|
|
||||||
|
@ -32,8 +30,7 @@ class PageAdapter(
|
||||||
|
|
||||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
||||||
return LibraryItemViewHolder(
|
return LibraryItemViewHolder(
|
||||||
LayoutInflater.from(parent.context)
|
SearchResultGridExpandedBinding.inflate(LayoutInflater.from(parent.context), parent, false)
|
||||||
.inflate(R.layout.search_result_grid_expanded, parent, false)
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,8 +54,7 @@ class PageAdapter(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inner class LibraryItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
|
inner class LibraryItemViewHolder(val binding : SearchResultGridExpandedBinding) : RecyclerView.ViewHolder(binding.root) {
|
||||||
val cardView: ImageView = itemView.imageView
|
|
||||||
|
|
||||||
private val compactView = false//itemView.context.getGridIsCompact()
|
private val compactView = false//itemView.context.getGridIsCompact()
|
||||||
private val coverHeight: Int =
|
private val coverHeight: Int =
|
||||||
|
@ -85,11 +81,11 @@ class PageAdapter(
|
||||||
|
|
||||||
val fg =
|
val fg =
|
||||||
getDifferentColor(bg)//palette.getVibrantColor(ContextCompat.getColor(ctx,R.color.ratingColor))
|
getDifferentColor(bg)//palette.getVibrantColor(ContextCompat.getColor(ctx,R.color.ratingColor))
|
||||||
itemView.text_rating.apply {
|
binding.textRating.apply {
|
||||||
setTextColor(ColorStateList.valueOf(fg))
|
setTextColor(ColorStateList.valueOf(fg))
|
||||||
}
|
}
|
||||||
itemView.text_rating_holder?.backgroundTintList = ColorStateList.valueOf(bg)
|
binding.textRatingHolder.backgroundTintList = ColorStateList.valueOf(bg)
|
||||||
itemView.watchProgress?.apply {
|
binding.watchProgress.apply {
|
||||||
progressTintList = ColorStateList.valueOf(fg)
|
progressTintList = ColorStateList.valueOf(fg)
|
||||||
progressBackgroundTintList = ColorStateList.valueOf(bg)
|
progressBackgroundTintList = ColorStateList.valueOf(bg)
|
||||||
}
|
}
|
||||||
|
@ -99,7 +95,7 @@ class PageAdapter(
|
||||||
|
|
||||||
// See searchAdaptor for this, it basically fixes the height
|
// See searchAdaptor for this, it basically fixes the height
|
||||||
if (!compactView) {
|
if (!compactView) {
|
||||||
cardView.apply {
|
binding.imageView.apply {
|
||||||
layoutParams = FrameLayout.LayoutParams(
|
layoutParams = FrameLayout.LayoutParams(
|
||||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||||
coverHeight
|
coverHeight
|
||||||
|
@ -108,22 +104,22 @@ class PageAdapter(
|
||||||
}
|
}
|
||||||
|
|
||||||
val showProgress = item.episodesCompleted != null && item.episodesTotal != null
|
val showProgress = item.episodesCompleted != null && item.episodesTotal != null
|
||||||
itemView.watchProgress.isVisible = showProgress
|
binding.watchProgress.isVisible = showProgress
|
||||||
if (showProgress) {
|
if (showProgress) {
|
||||||
itemView.watchProgress.max = item.episodesTotal!!
|
binding.watchProgress.max = item.episodesTotal!!
|
||||||
itemView.watchProgress.progress = item.episodesCompleted!!
|
binding.watchProgress.progress = item.episodesCompleted!!
|
||||||
}
|
}
|
||||||
|
|
||||||
itemView.imageText.text = item.name
|
binding.imageText.text = item.name
|
||||||
|
|
||||||
val showRating = (item.personalRating ?: 0) != 0
|
val showRating = (item.personalRating ?: 0) != 0
|
||||||
itemView.text_rating_holder.isVisible = showRating
|
binding.textRatingHolder.isVisible = showRating
|
||||||
if (showRating) {
|
if (showRating) {
|
||||||
// We want to show 8.5 but not 8.0 hence the replace
|
// We want to show 8.5 but not 8.0 hence the replace
|
||||||
val rating = ((item.personalRating ?: 0).toDouble() / 10).toString()
|
val rating = ((item.personalRating ?: 0).toDouble() / 10).toString()
|
||||||
.replace(".0", "")
|
.replace(".0", "")
|
||||||
|
|
||||||
itemView.text_rating.text = "★ $rating"
|
binding.textRating.text = "★ $rating"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,16 +2,14 @@ package com.lagradost.cloudstream3.ui.library
|
||||||
|
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.core.view.doOnAttach
|
import androidx.core.view.doOnAttach
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import androidx.recyclerview.widget.RecyclerView.OnFlingListener
|
import androidx.recyclerview.widget.RecyclerView.OnFlingListener
|
||||||
import com.lagradost.cloudstream3.R
|
import com.lagradost.cloudstream3.databinding.LibraryViewpagerPageBinding
|
||||||
import com.lagradost.cloudstream3.syncproviders.SyncAPI
|
import com.lagradost.cloudstream3.syncproviders.SyncAPI
|
||||||
import com.lagradost.cloudstream3.ui.search.SearchClickCallback
|
import com.lagradost.cloudstream3.ui.search.SearchClickCallback
|
||||||
import com.lagradost.cloudstream3.utils.UIHelper.getSpanCount
|
import com.lagradost.cloudstream3.utils.UIHelper.getSpanCount
|
||||||
import kotlinx.android.synthetic.main.library_viewpager_page.view.*
|
|
||||||
|
|
||||||
class ViewpagerAdapter(
|
class ViewpagerAdapter(
|
||||||
var pages: List<SyncAPI.Page>,
|
var pages: List<SyncAPI.Page>,
|
||||||
|
@ -20,8 +18,7 @@ class ViewpagerAdapter(
|
||||||
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
|
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
|
||||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
||||||
return PageViewHolder(
|
return PageViewHolder(
|
||||||
LayoutInflater.from(parent.context)
|
LibraryViewpagerPageBinding.inflate(LayoutInflater.from(parent.context), parent, false)
|
||||||
.inflate(R.layout.library_viewpager_page, parent, false)
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,6 +31,7 @@ class ViewpagerAdapter(
|
||||||
}
|
}
|
||||||
|
|
||||||
private val unbound = mutableSetOf<Int>()
|
private val unbound = mutableSetOf<Int>()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used to mark all pages for re-binding and forces all items to be refreshed
|
* Used to mark all pages for re-binding and forces all items to be refreshed
|
||||||
* Without this the pages will still use the same adapters
|
* Without this the pages will still use the same adapters
|
||||||
|
@ -43,44 +41,46 @@ class ViewpagerAdapter(
|
||||||
this.notifyItemRangeChanged(0, pages.size)
|
this.notifyItemRangeChanged(0, pages.size)
|
||||||
}
|
}
|
||||||
|
|
||||||
inner class PageViewHolder(private val itemViewTest: View) :
|
inner class PageViewHolder(private val binding: LibraryViewpagerPageBinding) :
|
||||||
RecyclerView.ViewHolder(itemViewTest) {
|
RecyclerView.ViewHolder(binding.root) {
|
||||||
fun bind(page: SyncAPI.Page, rebind: Boolean) {
|
fun bind(page: SyncAPI.Page, rebind: Boolean) {
|
||||||
itemView.page_recyclerview?.spanCount =
|
binding.pageRecyclerview.apply {
|
||||||
this@PageViewHolder.itemView.context.getSpanCount() ?: 3
|
spanCount =
|
||||||
|
this@PageViewHolder.itemView.context.getSpanCount() ?: 3
|
||||||
if (itemViewTest.page_recyclerview?.adapter == null || rebind) {
|
if (adapter == null || rebind) {
|
||||||
// Only add the items after it has been attached since the items rely on ItemWidth
|
// Only add the items after it has been attached since the items rely on ItemWidth
|
||||||
// Which is only determined after the recyclerview is attached.
|
// Which is only determined after the recyclerview is attached.
|
||||||
// If this fails then item height becomes 0 when there is only one item
|
// If this fails then item height becomes 0 when there is only one item
|
||||||
itemViewTest.page_recyclerview?.doOnAttach {
|
doOnAttach {
|
||||||
itemViewTest.page_recyclerview?.adapter = PageAdapter(
|
adapter = PageAdapter(
|
||||||
page.items.toMutableList(),
|
page.items.toMutableList(),
|
||||||
itemViewTest.page_recyclerview,
|
this,
|
||||||
clickCallback
|
clickCallback
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
(adapter as? PageAdapter)?.updateList(page.items)
|
||||||
|
scrollToPosition(0)
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
(itemViewTest.page_recyclerview?.adapter as? PageAdapter)?.updateList(page.items)
|
|
||||||
itemViewTest.page_recyclerview?.scrollToPosition(0)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||||
itemViewTest.page_recyclerview.setOnScrollChangeListener { v, scrollX, scrollY, oldScrollX, oldScrollY ->
|
setOnScrollChangeListener { v, scrollX, scrollY, oldScrollX, oldScrollY ->
|
||||||
val diff = scrollY - oldScrollY
|
val diff = scrollY - oldScrollY
|
||||||
if (diff == 0) return@setOnScrollChangeListener
|
if (diff == 0) return@setOnScrollChangeListener
|
||||||
|
|
||||||
scrollCallback.invoke(diff > 0)
|
scrollCallback.invoke(diff > 0)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
itemViewTest.page_recyclerview.onFlingListener = object : OnFlingListener() {
|
onFlingListener = object : OnFlingListener() {
|
||||||
override fun onFling(velocityX: Int, velocityY: Int): Boolean {
|
override fun onFling(velocityX: Int, velocityY: Int): Boolean {
|
||||||
scrollCallback.invoke(velocityY > 0)
|
scrollCallback.invoke(velocityY > 0)
|
||||||
return false
|
return false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@ import com.lagradost.cloudstream3.APIHolder.filterSearchResultByFilmQuality
|
||||||
import com.lagradost.cloudstream3.APIHolder.getApiFromNameNull
|
import com.lagradost.cloudstream3.APIHolder.getApiFromNameNull
|
||||||
import com.lagradost.cloudstream3.HomePageList
|
import com.lagradost.cloudstream3.HomePageList
|
||||||
import com.lagradost.cloudstream3.R
|
import com.lagradost.cloudstream3.R
|
||||||
|
import com.lagradost.cloudstream3.databinding.QuickSearchBinding
|
||||||
import com.lagradost.cloudstream3.mvvm.Resource
|
import com.lagradost.cloudstream3.mvvm.Resource
|
||||||
import com.lagradost.cloudstream3.mvvm.logError
|
import com.lagradost.cloudstream3.mvvm.logError
|
||||||
import com.lagradost.cloudstream3.mvvm.observe
|
import com.lagradost.cloudstream3.mvvm.observe
|
||||||
|
@ -37,7 +38,6 @@ import com.lagradost.cloudstream3.utils.UIHelper.fixPaddingStatusbar
|
||||||
import com.lagradost.cloudstream3.utils.UIHelper.getSpanCount
|
import com.lagradost.cloudstream3.utils.UIHelper.getSpanCount
|
||||||
import com.lagradost.cloudstream3.utils.UIHelper.navigate
|
import com.lagradost.cloudstream3.utils.UIHelper.navigate
|
||||||
import com.lagradost.cloudstream3.utils.UIHelper.popCurrentPage
|
import com.lagradost.cloudstream3.utils.UIHelper.popCurrentPage
|
||||||
import kotlinx.android.synthetic.main.quick_search.*
|
|
||||||
import java.util.concurrent.locks.ReentrantLock
|
import java.util.concurrent.locks.ReentrantLock
|
||||||
|
|
||||||
class QuickSearchFragment : Fragment() {
|
class QuickSearchFragment : Fragment() {
|
||||||
|
@ -72,6 +72,8 @@ class QuickSearchFragment : Fragment() {
|
||||||
|
|
||||||
private var providers: Set<String>? = null
|
private var providers: Set<String>? = null
|
||||||
private lateinit var searchViewModel: SearchViewModel
|
private lateinit var searchViewModel: SearchViewModel
|
||||||
|
var binding: QuickSearchBinding? = null
|
||||||
|
|
||||||
|
|
||||||
private var bottomSheetDialog: BottomSheetDialog? = null
|
private var bottomSheetDialog: BottomSheetDialog? = null
|
||||||
|
|
||||||
|
@ -79,13 +81,21 @@ class QuickSearchFragment : Fragment() {
|
||||||
inflater: LayoutInflater,
|
inflater: LayoutInflater,
|
||||||
container: ViewGroup?,
|
container: ViewGroup?,
|
||||||
savedInstanceState: Bundle?
|
savedInstanceState: Bundle?
|
||||||
): View? {
|
): View {
|
||||||
activity?.window?.setSoftInputMode(
|
activity?.window?.setSoftInputMode(
|
||||||
WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE
|
WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE
|
||||||
)
|
)
|
||||||
searchViewModel = ViewModelProvider(this)[SearchViewModel::class.java]
|
searchViewModel = ViewModelProvider(this)[SearchViewModel::class.java]
|
||||||
bottomSheetDialog?.ownShow()
|
bottomSheetDialog?.ownShow()
|
||||||
return inflater.inflate(R.layout.quick_search, container, false)
|
val localBinding = QuickSearchBinding.inflate(inflater, container, false)
|
||||||
|
binding = localBinding
|
||||||
|
return localBinding.root
|
||||||
|
//return inflater.inflate(R.layout.quick_search, container, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDestroyView() {
|
||||||
|
binding = null
|
||||||
|
super.onDestroyView()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDestroy() {
|
override fun onDestroy() {
|
||||||
|
@ -111,7 +121,7 @@ class QuickSearchFragment : Fragment() {
|
||||||
activity?.getSpanCount()?.let {
|
activity?.getSpanCount()?.let {
|
||||||
HomeFragment.currentSpan = it
|
HomeFragment.currentSpan = it
|
||||||
}
|
}
|
||||||
quick_search_autofit_results.spanCount = HomeFragment.currentSpan
|
binding?.quickSearchAutofitResults?.spanCount = HomeFragment.currentSpan
|
||||||
HomeFragment.currentSpan = HomeFragment.currentSpan
|
HomeFragment.currentSpan = HomeFragment.currentSpan
|
||||||
HomeFragment.configEvent.invoke(HomeFragment.currentSpan)
|
HomeFragment.configEvent.invoke(HomeFragment.currentSpan)
|
||||||
}
|
}
|
||||||
|
@ -123,7 +133,7 @@ class QuickSearchFragment : Fragment() {
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
context?.fixPaddingStatusbar(quick_search_root)
|
fixPaddingStatusbar(binding?.quickSearchRoot)
|
||||||
fixGrid()
|
fixGrid()
|
||||||
|
|
||||||
arguments?.getStringArray(PROVIDER_KEY)?.let {
|
arguments?.getStringArray(PROVIDER_KEY)?.let {
|
||||||
|
@ -136,21 +146,22 @@ class QuickSearchFragment : Fragment() {
|
||||||
} else false
|
} else false
|
||||||
|
|
||||||
if (isSingleProvider) {
|
if (isSingleProvider) {
|
||||||
quick_search_autofit_results.adapter = activity?.let {
|
binding?.quickSearchAutofitResults?.apply {
|
||||||
SearchAdapter(
|
adapter = SearchAdapter(
|
||||||
ArrayList(),
|
ArrayList(),
|
||||||
quick_search_autofit_results,
|
this,
|
||||||
) { callback ->
|
) { callback ->
|
||||||
SearchHelper.handleSearchClickCallback(activity, callback)
|
SearchHelper.handleSearchClickCallback(activity, callback)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
quick_search?.queryHint = getString(R.string.search_hint_site).format(providers?.first())
|
binding?.quickSearch?.queryHint = getString(R.string.search_hint_site).format(providers?.first())
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
logError(e)
|
logError(e)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
quick_search_master_recycler?.adapter =
|
binding?.quickSearchMasterRecycler?.adapter =
|
||||||
ParentItemAdapter(mutableListOf(), { callback ->
|
ParentItemAdapter(mutableListOf(), { callback ->
|
||||||
SearchHelper.handleSearchClickCallback(activity, callback)
|
SearchHelper.handleSearchClickCallback(activity, callback)
|
||||||
//when (callback.action) {
|
//when (callback.action) {
|
||||||
|
@ -164,18 +175,17 @@ class QuickSearchFragment : Fragment() {
|
||||||
bottomSheetDialog = null
|
bottomSheetDialog = null
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
quick_search_master_recycler?.layoutManager = GridLayoutManager(context, 1)
|
binding?.quickSearchMasterRecycler?.layoutManager = GridLayoutManager(context, 1)
|
||||||
}
|
}
|
||||||
|
binding?.quickSearchAutofitResults?.isVisible = isSingleProvider
|
||||||
quick_search_autofit_results?.isVisible = isSingleProvider
|
binding?.quickSearchMasterRecycler?.isGone = isSingleProvider
|
||||||
quick_search_master_recycler?.isGone = isSingleProvider
|
|
||||||
|
|
||||||
val listLock = ReentrantLock()
|
val listLock = ReentrantLock()
|
||||||
observe(searchViewModel.currentSearch) { list ->
|
observe(searchViewModel.currentSearch) { list ->
|
||||||
try {
|
try {
|
||||||
// https://stackoverflow.com/questions/6866238/concurrent-modification-exception-adding-to-an-arraylist
|
// https://stackoverflow.com/questions/6866238/concurrent-modification-exception-adding-to-an-arraylist
|
||||||
listLock.lock()
|
listLock.lock()
|
||||||
(quick_search_master_recycler?.adapter as ParentItemAdapter?)?.apply {
|
(binding?.quickSearchMasterRecycler?.adapter as ParentItemAdapter?)?.apply {
|
||||||
updateList(list.map { ongoing ->
|
updateList(list.map { ongoing ->
|
||||||
val ongoingList = HomePageList(
|
val ongoingList = HomePageList(
|
||||||
ongoing.apiName,
|
ongoing.apiName,
|
||||||
|
@ -192,19 +202,18 @@ class QuickSearchFragment : Fragment() {
|
||||||
}
|
}
|
||||||
|
|
||||||
val searchExitIcon =
|
val searchExitIcon =
|
||||||
quick_search?.findViewById<ImageView>(androidx.appcompat.R.id.search_close_btn)
|
binding?.quickSearch?.findViewById<ImageView>(androidx.appcompat.R.id.search_close_btn)
|
||||||
|
|
||||||
//val searchMagIcon =
|
//val searchMagIcon =
|
||||||
// quick_search?.findViewById<ImageView>(androidx.appcompat.R.id.search_mag_icon)
|
// binding.quickSearch.findViewById<ImageView>(androidx.appcompat.R.id.search_mag_icon)
|
||||||
|
|
||||||
//searchMagIcon?.scaleX = 0.65f
|
//searchMagIcon?.scaleX = 0.65f
|
||||||
//searchMagIcon?.scaleY = 0.65f
|
//searchMagIcon?.scaleY = 0.65f
|
||||||
|
|
||||||
|
binding?.quickSearch?.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
|
||||||
quick_search?.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
|
|
||||||
override fun onQueryTextSubmit(query: String): Boolean {
|
override fun onQueryTextSubmit(query: String): Boolean {
|
||||||
if (search(context, query, false))
|
if (search(context, query, false))
|
||||||
UIHelper.hideKeyboard(quick_search)
|
UIHelper.hideKeyboard(binding?.quickSearch)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -214,27 +223,26 @@ class QuickSearchFragment : Fragment() {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
binding?.quickSearchLoadingBar?.alpha = 0f
|
||||||
quick_search_loading_bar.alpha = 0f
|
|
||||||
observe(searchViewModel.searchResponse) {
|
observe(searchViewModel.searchResponse) {
|
||||||
when (it) {
|
when (it) {
|
||||||
is Resource.Success -> {
|
is Resource.Success -> {
|
||||||
it.value.let { data ->
|
it.value.let { data ->
|
||||||
(quick_search_autofit_results?.adapter as? SearchAdapter)?.updateList(
|
(binding?.quickSearchAutofitResults?.adapter as? SearchAdapter)?.updateList(
|
||||||
context?.filterSearchResultByFilmQuality(data) ?: data
|
context?.filterSearchResultByFilmQuality(data) ?: data
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
searchExitIcon?.alpha = 1f
|
searchExitIcon?.alpha = 1f
|
||||||
quick_search_loading_bar?.alpha = 0f
|
binding?.quickSearchLoadingBar?.alpha = 0f
|
||||||
}
|
}
|
||||||
is Resource.Failure -> {
|
is Resource.Failure -> {
|
||||||
// Toast.makeText(activity, "Server error", Toast.LENGTH_LONG).show()
|
// Toast.makeText(activity, "Server error", Toast.LENGTH_LONG).show()
|
||||||
searchExitIcon?.alpha = 1f
|
searchExitIcon?.alpha = 1f
|
||||||
quick_search_loading_bar?.alpha = 0f
|
binding?.quickSearchLoadingBar?.alpha = 0f
|
||||||
}
|
}
|
||||||
is Resource.Loading -> {
|
is Resource.Loading -> {
|
||||||
searchExitIcon?.alpha = 0f
|
searchExitIcon?.alpha = 0f
|
||||||
quick_search_loading_bar?.alpha = 1f
|
binding?.quickSearchLoadingBar?.alpha = 1f
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -246,13 +254,12 @@ class QuickSearchFragment : Fragment() {
|
||||||
// UIHelper.showInputMethod(view.findFocus())
|
// UIHelper.showInputMethod(view.findFocus())
|
||||||
// }
|
// }
|
||||||
//}
|
//}
|
||||||
|
binding?.quickSearchBack?.setOnClickListener {
|
||||||
quick_search_back.setOnClickListener {
|
|
||||||
activity?.popCurrentPage()
|
activity?.popCurrentPage()
|
||||||
}
|
}
|
||||||
|
|
||||||
arguments?.getString(AUTOSEARCH_KEY)?.let {
|
arguments?.getString(AUTOSEARCH_KEY)?.let {
|
||||||
quick_search?.setQuery(it, true)
|
binding?.quickSearch?.setQuery(it, true)
|
||||||
arguments?.remove(AUTOSEARCH_KEY)
|
arguments?.remove(AUTOSEARCH_KEY)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,20 +1,17 @@
|
||||||
package com.lagradost.cloudstream3.ui.result
|
package com.lagradost.cloudstream3.ui.result
|
||||||
|
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.ImageView
|
|
||||||
import android.widget.TextView
|
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import androidx.recyclerview.widget.DiffUtil
|
import androidx.recyclerview.widget.DiffUtil
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import com.lagradost.cloudstream3.ActorData
|
import com.lagradost.cloudstream3.ActorData
|
||||||
import com.lagradost.cloudstream3.ActorRole
|
import com.lagradost.cloudstream3.ActorRole
|
||||||
import com.lagradost.cloudstream3.R
|
import com.lagradost.cloudstream3.R
|
||||||
|
import com.lagradost.cloudstream3.databinding.CastItemBinding
|
||||||
import com.lagradost.cloudstream3.utils.UIHelper.setImage
|
import com.lagradost.cloudstream3.utils.UIHelper.setImage
|
||||||
import kotlinx.android.synthetic.main.cast_item.view.*
|
|
||||||
|
|
||||||
class ActorAdaptor() : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
|
class ActorAdaptor : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
|
||||||
data class ActorMetaData(
|
data class ActorMetaData(
|
||||||
var isInverted: Boolean,
|
var isInverted: Boolean,
|
||||||
val actor: ActorData,
|
val actor: ActorData,
|
||||||
|
@ -24,7 +21,7 @@ class ActorAdaptor() : 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.cast_item, parent, false),
|
CastItemBinding.inflate(LayoutInflater.from(parent.context), parent, false)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,15 +65,9 @@ class ActorAdaptor() : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
|
||||||
|
|
||||||
private class CardViewHolder
|
private class CardViewHolder
|
||||||
constructor(
|
constructor(
|
||||||
itemView: View,
|
val binding: CastItemBinding,
|
||||||
) :
|
) :
|
||||||
RecyclerView.ViewHolder(itemView) {
|
RecyclerView.ViewHolder(binding.root) {
|
||||||
private val actorImage: ImageView = itemView.actor_image
|
|
||||||
private val actorName: TextView = itemView.actor_name
|
|
||||||
private val actorExtra: TextView = itemView.actor_extra
|
|
||||||
private val voiceActorImage: ImageView = itemView.voice_actor_image
|
|
||||||
private val voiceActorImageHolder: View = itemView.voice_actor_image_holder
|
|
||||||
private val voiceActorName: TextView = itemView.voice_actor_name
|
|
||||||
|
|
||||||
fun bind(actor: ActorData, isInverted: Boolean, position: Int, callback: (Int) -> Unit) {
|
fun bind(actor: ActorData, isInverted: Boolean, position: Int, callback: (Int) -> Unit) {
|
||||||
val (mainImg, vaImage) = if (!isInverted || actor.voiceActor?.image.isNullOrBlank()) {
|
val (mainImg, vaImage) = if (!isInverted || actor.voiceActor?.image.isNullOrBlank()) {
|
||||||
|
@ -89,39 +80,43 @@ class ActorAdaptor() : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
|
||||||
callback(position)
|
callback(position)
|
||||||
}
|
}
|
||||||
|
|
||||||
actorImage.setImage(mainImg)
|
binding.apply {
|
||||||
|
actorImage.setImage(mainImg)
|
||||||
|
|
||||||
actorName.text = actor.actor.name
|
actorName.text = actor.actor.name
|
||||||
actor.role?.let {
|
actor.role?.let {
|
||||||
actorExtra.context?.getString(
|
actorExtra.context?.getString(
|
||||||
when (it) {
|
when (it) {
|
||||||
ActorRole.Main -> {
|
ActorRole.Main -> {
|
||||||
R.string.actor_main
|
R.string.actor_main
|
||||||
}
|
}
|
||||||
ActorRole.Supporting -> {
|
|
||||||
R.string.actor_supporting
|
ActorRole.Supporting -> {
|
||||||
}
|
R.string.actor_supporting
|
||||||
ActorRole.Background -> {
|
}
|
||||||
R.string.actor_background
|
|
||||||
|
ActorRole.Background -> {
|
||||||
|
R.string.actor_background
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
)?.let { text ->
|
||||||
|
actorExtra.isVisible = true
|
||||||
|
actorExtra.text = text
|
||||||
}
|
}
|
||||||
)?.let { text ->
|
} ?: actor.roleString?.let {
|
||||||
actorExtra.isVisible = true
|
actorExtra.isVisible = true
|
||||||
actorExtra.text = text
|
actorExtra.text = it
|
||||||
|
} ?: run {
|
||||||
|
actorExtra.isVisible = false
|
||||||
}
|
}
|
||||||
} ?: actor.roleString?.let {
|
|
||||||
actorExtra.isVisible = true
|
|
||||||
actorExtra.text = it
|
|
||||||
} ?: run {
|
|
||||||
actorExtra.isVisible = false
|
|
||||||
}
|
|
||||||
|
|
||||||
if (actor.voiceActor == null) {
|
if (actor.voiceActor == null) {
|
||||||
voiceActorImageHolder.isVisible = false
|
voiceActorImageHolder.isVisible = false
|
||||||
voiceActorName.isVisible = false
|
voiceActorName.isVisible = false
|
||||||
} else {
|
} else {
|
||||||
voiceActorName.text = actor.voiceActor.name
|
voiceActorName.text = actor.voiceActor.name
|
||||||
voiceActorImageHolder.isVisible = voiceActorImage.setImage(vaImage)
|
voiceActorImageHolder.isVisible = voiceActorImage.setImage(vaImage)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,34 +3,25 @@ package com.lagradost.cloudstream3.ui.result
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.ImageView
|
|
||||||
import android.widget.TextView
|
|
||||||
import androidx.core.view.isGone
|
import androidx.core.view.isGone
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import androidx.core.widget.ContentLoadingProgressBar
|
|
||||||
import androidx.preference.PreferenceManager
|
import androidx.preference.PreferenceManager
|
||||||
import androidx.recyclerview.widget.DiffUtil
|
import androidx.recyclerview.widget.DiffUtil
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import com.google.android.material.button.MaterialButton
|
|
||||||
import com.lagradost.cloudstream3.R
|
import com.lagradost.cloudstream3.R
|
||||||
|
import com.lagradost.cloudstream3.databinding.ResultEpisodeBinding
|
||||||
|
import com.lagradost.cloudstream3.databinding.ResultEpisodeLargeBinding
|
||||||
import com.lagradost.cloudstream3.ui.download.DOWNLOAD_ACTION_DOWNLOAD
|
import com.lagradost.cloudstream3.ui.download.DOWNLOAD_ACTION_DOWNLOAD
|
||||||
import com.lagradost.cloudstream3.ui.download.DownloadButtonViewHolder
|
import com.lagradost.cloudstream3.ui.download.DownloadButtonViewHolder
|
||||||
import com.lagradost.cloudstream3.ui.download.DownloadClickEvent
|
import com.lagradost.cloudstream3.ui.download.DownloadClickEvent
|
||||||
import com.lagradost.cloudstream3.ui.download.EasyDownloadButton
|
import com.lagradost.cloudstream3.ui.download.EasyDownloadButton
|
||||||
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.AppUtils.html
|
import com.lagradost.cloudstream3.utils.AppUtils.html
|
||||||
import com.lagradost.cloudstream3.utils.UIHelper.setImage
|
import com.lagradost.cloudstream3.utils.UIHelper.setImage
|
||||||
import com.lagradost.cloudstream3.utils.VideoDownloadHelper
|
import com.lagradost.cloudstream3.utils.VideoDownloadHelper
|
||||||
import com.lagradost.cloudstream3.utils.VideoDownloadManager
|
import com.lagradost.cloudstream3.utils.VideoDownloadManager
|
||||||
import kotlinx.android.synthetic.main.result_episode.view.*
|
|
||||||
import kotlinx.android.synthetic.main.result_episode.view.episode_text
|
|
||||||
import kotlinx.android.synthetic.main.result_episode_large.view.*
|
|
||||||
import kotlinx.android.synthetic.main.result_episode_large.view.episode_filler
|
|
||||||
import kotlinx.android.synthetic.main.result_episode_large.view.episode_progress
|
|
||||||
import kotlinx.android.synthetic.main.result_episode_large.view.result_episode_download
|
|
||||||
import kotlinx.android.synthetic.main.result_episode_large.view.result_episode_progress_downloaded
|
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
const val ACTION_PLAY_EPISODE_IN_PLAYER = 1
|
const val ACTION_PLAY_EPISODE_IN_PLAYER = 1
|
||||||
|
@ -144,26 +135,52 @@ class EpisodeAdapter(
|
||||||
diffResult.dispatchUpdatesTo(this)
|
diffResult.dispatchUpdatesTo(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
var layout = R.layout.result_episode_both
|
fun getItem(position: Int) : ResultEpisode {
|
||||||
|
return cardList[position]
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getItemViewType(position: Int): Int {
|
||||||
|
val item = getItem(position)
|
||||||
|
return if(item.poster.isNullOrBlank()) 0 else 1
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// private val layout = R.layout.result_episode_both
|
||||||
|
|
||||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
||||||
/*val layout = if (cardList.filter { it.poster != null }.size >= cardList.size / 2)
|
/*val layout = if (cardList.filter { it.poster != null }.size >= cardList.size / 2)
|
||||||
R.layout.result_episode_large
|
R.layout.result_episode_large
|
||||||
else R.layout.result_episode*/
|
else R.layout.result_episode*/
|
||||||
|
|
||||||
return EpisodeCardViewHolder(
|
return when(viewType) {
|
||||||
LayoutInflater.from(parent.context)
|
0 -> {
|
||||||
.inflate(layout, parent, false),
|
EpisodeCardViewHolderSmall(
|
||||||
hasDownloadSupport,
|
ResultEpisodeBinding.inflate(LayoutInflater.from(parent.context), parent, false),
|
||||||
clickCallback,
|
hasDownloadSupport,
|
||||||
downloadClickCallback
|
clickCallback,
|
||||||
)
|
downloadClickCallback
|
||||||
|
)
|
||||||
|
}
|
||||||
|
1 -> {
|
||||||
|
EpisodeCardViewHolderLarge(
|
||||||
|
ResultEpisodeLargeBinding.inflate(LayoutInflater.from(parent.context), parent, false),
|
||||||
|
hasDownloadSupport,
|
||||||
|
clickCallback,
|
||||||
|
downloadClickCallback
|
||||||
|
)
|
||||||
|
}
|
||||||
|
else -> throw NotImplementedError()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
|
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
|
||||||
when (holder) {
|
when (holder) {
|
||||||
is EpisodeCardViewHolder -> {
|
is EpisodeCardViewHolderLarge -> {
|
||||||
holder.bind(cardList[position])
|
holder.bind(getItem(position))
|
||||||
|
mBoundViewHolders.add(holder)
|
||||||
|
}
|
||||||
|
is EpisodeCardViewHolderSmall -> {
|
||||||
|
holder.bind(getItem(position))
|
||||||
mBoundViewHolders.add(holder)
|
mBoundViewHolders.add(holder)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -173,94 +190,81 @@ class EpisodeAdapter(
|
||||||
return cardList.size
|
return cardList.size
|
||||||
}
|
}
|
||||||
|
|
||||||
class EpisodeCardViewHolder
|
class EpisodeCardViewHolderLarge
|
||||||
constructor(
|
constructor(
|
||||||
itemView: View,
|
val binding : ResultEpisodeLargeBinding,
|
||||||
private val hasDownloadSupport: Boolean,
|
private val hasDownloadSupport: Boolean,
|
||||||
private val clickCallback: (EpisodeClickEvent) -> Unit,
|
private val clickCallback: (EpisodeClickEvent) -> Unit,
|
||||||
private val downloadClickCallback: (DownloadClickEvent) -> Unit,
|
private val downloadClickCallback: (DownloadClickEvent) -> Unit,
|
||||||
) : RecyclerView.ViewHolder(itemView), DownloadButtonViewHolder {
|
) : RecyclerView.ViewHolder(binding.root), DownloadButtonViewHolder {
|
||||||
override var downloadButton = EasyDownloadButton()
|
override var downloadButton = EasyDownloadButton()
|
||||||
|
|
||||||
var episodeDownloadBar: ContentLoadingProgressBar? = null
|
// TODO TV
|
||||||
var episodeDownloadImage: ImageView? = null
|
|
||||||
var localCard: ResultEpisode? = null
|
var localCard: ResultEpisode? = null
|
||||||
|
|
||||||
@SuppressLint("SetTextI18n")
|
@SuppressLint("SetTextI18n")
|
||||||
fun bind(card: ResultEpisode) {
|
fun bind(card: ResultEpisode) {
|
||||||
localCard = card
|
localCard = card
|
||||||
|
|
||||||
|
binding.episodeLinHolder.layoutParams.apply {
|
||||||
|
width = if(isTvSettings()) ViewGroup.LayoutParams.WRAP_CONTENT else ViewGroup.LayoutParams.MATCH_PARENT
|
||||||
|
}
|
||||||
|
|
||||||
val isTrueTv = isTrueTvSettings()
|
val isTrueTv = isTrueTvSettings()
|
||||||
|
|
||||||
val (parentView, otherView) = if (card.poster == null) {
|
binding.apply {
|
||||||
itemView.episode_holder to itemView.episode_holder_large
|
|
||||||
} else {
|
|
||||||
itemView.episode_holder_large to itemView.episode_holder
|
|
||||||
}
|
|
||||||
parentView.isVisible = true
|
|
||||||
otherView.isVisible = false
|
|
||||||
|
|
||||||
val episodeText: TextView = parentView.episode_text
|
val name =
|
||||||
val episodeFiller: MaterialButton? = parentView.episode_filler
|
if (card.name == null) "${episodeText.context.getString(R.string.episode)} ${card.episode}" else "${card.episode}. ${card.name}"
|
||||||
val episodeRating: TextView? = parentView.episode_rating
|
episodeFiller.isVisible = card.isFiller == true
|
||||||
val episodeDescript: TextView? = parentView.episode_descript
|
episodeText.text =
|
||||||
val episodeProgress: ContentLoadingProgressBar? = parentView.episode_progress
|
name//if(card.isFiller == true) episodeText.context.getString(R.string.filler).format(name) else name
|
||||||
val episodePoster: ImageView? = parentView.episode_poster
|
episodeText.isSelected = true // is needed for text repeating
|
||||||
|
|
||||||
episodeDownloadBar =
|
if (card.videoWatchState == VideoWatchState.Watched) {
|
||||||
parentView.result_episode_progress_downloaded
|
// This cannot be done in getDisplayPosition() as when you have not watched something
|
||||||
episodeDownloadImage = parentView.result_episode_download
|
// the duration and position is 0
|
||||||
|
episodeProgress.max = 1
|
||||||
val name =
|
episodeProgress.progress = 1
|
||||||
if (card.name == null) "${episodeText.context.getString(R.string.episode)} ${card.episode}" else "${card.episode}. ${card.name}"
|
episodeProgress.isVisible = true
|
||||||
episodeFiller?.isVisible = card.isFiller == true
|
} else {
|
||||||
episodeText.text =
|
val displayPos = card.getDisplayPosition()
|
||||||
name//if(card.isFiller == true) episodeText.context.getString(R.string.filler).format(name) else name
|
episodeProgress.max = (card.duration / 1000).toInt()
|
||||||
episodeText.isSelected = true // is needed for text repeating
|
episodeProgress.progress = (displayPos / 1000).toInt()
|
||||||
|
episodeProgress.isVisible = displayPos > 0L
|
||||||
if (card.videoWatchState == VideoWatchState.Watched) {
|
|
||||||
// This cannot be done in getDisplayPosition() as when you have not watched something
|
|
||||||
// the duration and position is 0
|
|
||||||
episodeProgress?.max = 1
|
|
||||||
episodeProgress?.progress = 1
|
|
||||||
episodeProgress?.isVisible = true
|
|
||||||
} else {
|
|
||||||
val displayPos = card.getDisplayPosition()
|
|
||||||
episodeProgress?.max = (card.duration / 1000).toInt()
|
|
||||||
episodeProgress?.progress = (displayPos / 1000).toInt()
|
|
||||||
episodeProgress?.isVisible = displayPos > 0L
|
|
||||||
}
|
|
||||||
|
|
||||||
episodePoster?.isVisible = episodePoster?.setImage(card.poster) == true
|
|
||||||
|
|
||||||
if (card.rating != null) {
|
|
||||||
episodeRating?.text = episodeRating?.context?.getString(R.string.rated_format)
|
|
||||||
?.format(card.rating.toFloat() / 10f)
|
|
||||||
} else {
|
|
||||||
episodeRating?.text = ""
|
|
||||||
}
|
|
||||||
|
|
||||||
episodeRating?.isGone = episodeRating?.text.isNullOrBlank()
|
|
||||||
|
|
||||||
episodeDescript?.apply {
|
|
||||||
text = card.description.html()
|
|
||||||
isGone = text.isNullOrBlank()
|
|
||||||
setOnClickListener {
|
|
||||||
clickCallback.invoke(EpisodeClickEvent(ACTION_SHOW_DESCRIPTION, card))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isTrueTv) {
|
|
||||||
episodePoster?.setOnClickListener {
|
|
||||||
clickCallback.invoke(EpisodeClickEvent(ACTION_CLICK_DEFAULT, card))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
episodePoster?.setOnLongClickListener {
|
episodePoster.isVisible = episodePoster.setImage(card.poster) == true
|
||||||
clickCallback.invoke(EpisodeClickEvent(ACTION_SHOW_TOAST, card))
|
|
||||||
return@setOnLongClickListener true
|
if (card.rating != null) {
|
||||||
|
episodeRating.text = episodeRating.context?.getString(R.string.rated_format)
|
||||||
|
?.format(card.rating.toFloat() / 10f)
|
||||||
|
} else {
|
||||||
|
episodeRating.text = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
episodeRating.isGone = episodeRating.text.isNullOrBlank()
|
||||||
|
|
||||||
|
episodeDescript.apply {
|
||||||
|
text = card.description.html()
|
||||||
|
isGone = text.isNullOrBlank()
|
||||||
|
setOnClickListener {
|
||||||
|
clickCallback.invoke(EpisodeClickEvent(ACTION_SHOW_DESCRIPTION, card))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isTrueTv) {
|
||||||
|
episodePoster.setOnClickListener {
|
||||||
|
clickCallback.invoke(EpisodeClickEvent(ACTION_CLICK_DEFAULT, card))
|
||||||
|
}
|
||||||
|
|
||||||
|
episodePoster.setOnLongClickListener {
|
||||||
|
clickCallback.invoke(EpisodeClickEvent(ACTION_SHOW_TOAST, card))
|
||||||
|
return@setOnLongClickListener true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
itemView.setOnClickListener {
|
itemView.setOnClickListener {
|
||||||
clickCallback.invoke(EpisodeClickEvent(ACTION_CLICK_DEFAULT, card))
|
clickCallback.invoke(EpisodeClickEvent(ACTION_CLICK_DEFAULT, card))
|
||||||
}
|
}
|
||||||
|
@ -276,8 +280,8 @@ class EpisodeAdapter(
|
||||||
return@setOnLongClickListener true
|
return@setOnLongClickListener true
|
||||||
}
|
}
|
||||||
|
|
||||||
episodeDownloadImage?.isVisible = hasDownloadSupport
|
binding.resultEpisodeDownload.isVisible = hasDownloadSupport
|
||||||
episodeDownloadBar?.isVisible = hasDownloadSupport
|
binding.resultEpisodeProgressDownloaded.isVisible = hasDownloadSupport
|
||||||
reattachDownloadButton()
|
reattachDownloadButton()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -285,9 +289,6 @@ class EpisodeAdapter(
|
||||||
downloadButton.dispose()
|
downloadButton.dispose()
|
||||||
val card = localCard
|
val card = localCard
|
||||||
if (hasDownloadSupport && card != null) {
|
if (hasDownloadSupport && card != null) {
|
||||||
if (episodeDownloadBar == null ||
|
|
||||||
episodeDownloadImage == null
|
|
||||||
) return
|
|
||||||
val downloadInfo = VideoDownloadManager.getDownloadFileInfoAndUpdateSettings(
|
val downloadInfo = VideoDownloadManager.getDownloadFileInfoAndUpdateSettings(
|
||||||
itemView.context,
|
itemView.context,
|
||||||
card.id
|
card.id
|
||||||
|
@ -296,8 +297,109 @@ class EpisodeAdapter(
|
||||||
downloadButton.setUpButton(
|
downloadButton.setUpButton(
|
||||||
downloadInfo?.fileLength,
|
downloadInfo?.fileLength,
|
||||||
downloadInfo?.totalBytes,
|
downloadInfo?.totalBytes,
|
||||||
episodeDownloadBar ?: return,
|
binding.resultEpisodeProgressDownloaded,
|
||||||
episodeDownloadImage ?: return,
|
binding.resultEpisodeDownload,
|
||||||
|
null,
|
||||||
|
VideoDownloadHelper.DownloadEpisodeCached(
|
||||||
|
card.name,
|
||||||
|
card.poster,
|
||||||
|
card.episode,
|
||||||
|
card.season,
|
||||||
|
card.id,
|
||||||
|
card.parentId,
|
||||||
|
card.rating,
|
||||||
|
card.description,
|
||||||
|
System.currentTimeMillis(),
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
if (it.action == DOWNLOAD_ACTION_DOWNLOAD) {
|
||||||
|
clickCallback.invoke(EpisodeClickEvent(ACTION_DOWNLOAD_EPISODE, card))
|
||||||
|
} else {
|
||||||
|
downloadClickCallback.invoke(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class EpisodeCardViewHolderSmall
|
||||||
|
constructor(
|
||||||
|
val binding : ResultEpisodeBinding,
|
||||||
|
private val hasDownloadSupport: Boolean,
|
||||||
|
private val clickCallback: (EpisodeClickEvent) -> Unit,
|
||||||
|
private val downloadClickCallback: (DownloadClickEvent) -> Unit,
|
||||||
|
) : RecyclerView.ViewHolder(binding.root), DownloadButtonViewHolder {
|
||||||
|
override var downloadButton = EasyDownloadButton()
|
||||||
|
|
||||||
|
var localCard: ResultEpisode? = null
|
||||||
|
|
||||||
|
@SuppressLint("SetTextI18n")
|
||||||
|
fun bind(card: ResultEpisode) {
|
||||||
|
localCard = card
|
||||||
|
|
||||||
|
val isTrueTv = isTrueTvSettings()
|
||||||
|
|
||||||
|
binding.episodeHolder.layoutParams.apply {
|
||||||
|
width = if(isTvSettings()) ViewGroup.LayoutParams.WRAP_CONTENT else ViewGroup.LayoutParams.MATCH_PARENT
|
||||||
|
}
|
||||||
|
|
||||||
|
binding.apply {
|
||||||
|
val name =
|
||||||
|
if (card.name == null) "${episodeText.context.getString(R.string.episode)} ${card.episode}" else "${card.episode}. ${card.name}"
|
||||||
|
episodeFiller.isVisible = card.isFiller == true
|
||||||
|
episodeText.text =
|
||||||
|
name//if(card.isFiller == true) episodeText.context.getString(R.string.filler).format(name) else name
|
||||||
|
episodeText.isSelected = true // is needed for text repeating
|
||||||
|
|
||||||
|
if (card.videoWatchState == VideoWatchState.Watched) {
|
||||||
|
// This cannot be done in getDisplayPosition() as when you have not watched something
|
||||||
|
// the duration and position is 0
|
||||||
|
episodeProgress.max = 1
|
||||||
|
episodeProgress.progress = 1
|
||||||
|
episodeProgress.isVisible = true
|
||||||
|
} else {
|
||||||
|
val displayPos = card.getDisplayPosition()
|
||||||
|
episodeProgress.max = (card.duration / 1000).toInt()
|
||||||
|
episodeProgress.progress = (displayPos / 1000).toInt()
|
||||||
|
episodeProgress.isVisible = displayPos > 0L
|
||||||
|
}
|
||||||
|
|
||||||
|
itemView.setOnClickListener {
|
||||||
|
clickCallback.invoke(EpisodeClickEvent(ACTION_CLICK_DEFAULT, card))
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isTrueTv) {
|
||||||
|
itemView.isFocusable = true
|
||||||
|
itemView.isFocusableInTouchMode = true
|
||||||
|
//itemView.touchscreenBlocksFocus = false
|
||||||
|
}
|
||||||
|
|
||||||
|
itemView.setOnLongClickListener {
|
||||||
|
clickCallback.invoke(EpisodeClickEvent(ACTION_SHOW_OPTIONS, card))
|
||||||
|
return@setOnLongClickListener true
|
||||||
|
}
|
||||||
|
|
||||||
|
binding.resultEpisodeDownload.isVisible = hasDownloadSupport
|
||||||
|
binding.resultEpisodeProgressDownloaded.isVisible = hasDownloadSupport
|
||||||
|
reattachDownloadButton()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun reattachDownloadButton() {
|
||||||
|
downloadButton.dispose()
|
||||||
|
val card = localCard
|
||||||
|
if (hasDownloadSupport && card != null) {
|
||||||
|
|
||||||
|
val downloadInfo = VideoDownloadManager.getDownloadFileInfoAndUpdateSettings(
|
||||||
|
itemView.context,
|
||||||
|
card.id
|
||||||
|
)
|
||||||
|
|
||||||
|
downloadButton.setUpButton(
|
||||||
|
downloadInfo?.fileLength,
|
||||||
|
downloadInfo?.totalBytes,
|
||||||
|
binding.resultEpisodeProgressDownloaded,
|
||||||
|
binding.resultEpisodeDownload,
|
||||||
null,
|
null,
|
||||||
VideoDownloadHelper.DownloadEpisodeCached(
|
VideoDownloadHelper.DownloadEpisodeCached(
|
||||||
card.name,
|
card.name,
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
package com.lagradost.cloudstream3.ui.result
|
package com.lagradost.cloudstream3.ui.result
|
||||||
|
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.ImageView
|
|
||||||
import androidx.recyclerview.widget.DiffUtil
|
import androidx.recyclerview.widget.DiffUtil
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import com.lagradost.cloudstream3.databinding.ResultMiniImageBinding
|
||||||
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTrueTvSettings
|
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTrueTvSettings
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -24,7 +23,6 @@ const val IMAGE_CLICK = 0
|
||||||
const val IMAGE_LONG_CLICK = 1
|
const val IMAGE_LONG_CLICK = 1
|
||||||
|
|
||||||
class ImageAdapter(
|
class ImageAdapter(
|
||||||
val layout: Int,
|
|
||||||
val clickCallback: ((Int) -> Unit)? = null,
|
val clickCallback: ((Int) -> Unit)? = null,
|
||||||
val nextFocusUp: Int? = null,
|
val nextFocusUp: Int? = null,
|
||||||
val nextFocusDown: Int? = null,
|
val nextFocusDown: Int? = null,
|
||||||
|
@ -34,7 +32,9 @@ class ImageAdapter(
|
||||||
|
|
||||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
||||||
return ImageViewHolder(
|
return ImageViewHolder(
|
||||||
LayoutInflater.from(parent.context).inflate(layout, parent, false)
|
//result_mini_image
|
||||||
|
ResultMiniImageBinding.inflate(LayoutInflater.from(parent.context), parent, false)
|
||||||
|
// LayoutInflater.from(parent.context).inflate(layout, parent, false)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,15 +66,15 @@ class ImageAdapter(
|
||||||
}
|
}
|
||||||
|
|
||||||
class ImageViewHolder
|
class ImageViewHolder
|
||||||
constructor(itemView: View) :
|
constructor(val binding: ResultMiniImageBinding) :
|
||||||
RecyclerView.ViewHolder(itemView) {
|
RecyclerView.ViewHolder(binding.root) {
|
||||||
fun bind(
|
fun bind(
|
||||||
img: Int,
|
img: Int,
|
||||||
clickCallback: ((Int) -> Unit)?,
|
clickCallback: ((Int) -> Unit)?,
|
||||||
nextFocusUp: Int?,
|
nextFocusUp: Int?,
|
||||||
nextFocusDown: Int?,
|
nextFocusDown: Int?,
|
||||||
) {
|
) {
|
||||||
(itemView as? ImageView?)?.apply {
|
binding.root.apply {
|
||||||
setImageResource(img)
|
setImageResource(img)
|
||||||
if (nextFocusDown != null) {
|
if (nextFocusDown != null) {
|
||||||
this.nextFocusDownId = nextFocusDown
|
this.nextFocusDownId = nextFocusDown
|
||||||
|
|
|
@ -310,6 +310,7 @@ open class ResultFragment : ResultTrailerPlayer() {
|
||||||
result_finish_loading?.isVisible = false
|
result_finish_loading?.isVisible = false
|
||||||
result_loading_error?.isVisible = false
|
result_loading_error?.isVisible = false
|
||||||
}
|
}
|
||||||
|
|
||||||
1 -> {
|
1 -> {
|
||||||
result_bookmark_fab?.isGone = true
|
result_bookmark_fab?.isGone = true
|
||||||
result_loading?.isVisible = false
|
result_loading?.isVisible = false
|
||||||
|
@ -317,6 +318,7 @@ open class ResultFragment : ResultTrailerPlayer() {
|
||||||
result_loading_error?.isVisible = true
|
result_loading_error?.isVisible = true
|
||||||
result_reload_connection_open_in_browser?.isVisible = true
|
result_reload_connection_open_in_browser?.isVisible = true
|
||||||
}
|
}
|
||||||
|
|
||||||
2 -> {
|
2 -> {
|
||||||
result_bookmark_fab?.isGone = isTrueTvSettings()
|
result_bookmark_fab?.isGone = isTrueTvSettings()
|
||||||
result_bookmark_fab?.extend()
|
result_bookmark_fab?.extend()
|
||||||
|
@ -350,9 +352,9 @@ open class ResultFragment : ResultTrailerPlayer() {
|
||||||
viewModel.reloadEpisodes()
|
viewModel.reloadEpisodes()
|
||||||
}
|
}
|
||||||
|
|
||||||
open fun updateMovie(data: ResourceSome<Pair<UiText, ResultEpisode>>) {
|
open fun updateMovie(data: Resource<Pair<UiText, ResultEpisode>>?) {
|
||||||
when (data) {
|
when (data) {
|
||||||
is ResourceSome.Success -> {
|
is Resource.Success -> {
|
||||||
data.value.let { (text, ep) ->
|
data.value.let { (text, ep) ->
|
||||||
result_play_movie.setText(text)
|
result_play_movie.setText(text)
|
||||||
result_play_movie?.setOnClickListener {
|
result_play_movie?.setOnClickListener {
|
||||||
|
@ -410,6 +412,7 @@ open class ResultFragment : ResultTrailerPlayer() {
|
||||||
EpisodeClickEvent(ACTION_DOWNLOAD_EPISODE, ep)
|
EpisodeClickEvent(ACTION_DOWNLOAD_EPISODE, ep)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> handleDownloadClick(activity, click)
|
else -> handleDownloadClick(activity, click)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -417,6 +420,7 @@ open class ResultFragment : ResultTrailerPlayer() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> {
|
else -> {
|
||||||
result_movie_progress_downloaded_holder?.isVisible = false
|
result_movie_progress_downloaded_holder?.isVisible = false
|
||||||
result_play_movie?.isVisible = false
|
result_play_movie?.isVisible = false
|
||||||
|
@ -424,17 +428,14 @@ open class ResultFragment : ResultTrailerPlayer() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
open fun updateEpisodes(episodes: ResourceSome<List<ResultEpisode>>) {
|
open fun updateEpisodes(episodes: Resource<List<ResultEpisode>>?) {
|
||||||
when (episodes) {
|
when (episodes) {
|
||||||
is ResourceSome.None -> {
|
is Resource.Loading -> {
|
||||||
result_episode_loading?.isVisible = false
|
|
||||||
result_episodes?.isVisible = false
|
|
||||||
}
|
|
||||||
is ResourceSome.Loading -> {
|
|
||||||
result_episode_loading?.isVisible = true
|
result_episode_loading?.isVisible = true
|
||||||
result_episodes?.isVisible = false
|
result_episodes?.isVisible = false
|
||||||
}
|
}
|
||||||
is ResourceSome.Success -> {
|
|
||||||
|
is Resource.Success -> {
|
||||||
result_episodes?.isVisible = true
|
result_episodes?.isVisible = true
|
||||||
result_episode_loading?.isVisible = false
|
result_episode_loading?.isVisible = false
|
||||||
|
|
||||||
|
@ -471,6 +472,11 @@ open class ResultFragment : ResultTrailerPlayer() {
|
||||||
result_episodes?.requestFocus()
|
result_episodes?.requestFocus()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
else -> {
|
||||||
|
result_episode_loading?.isVisible = false
|
||||||
|
result_episodes?.isVisible = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -565,7 +571,7 @@ open class ResultFragment : ResultTrailerPlayer() {
|
||||||
context?.updateHasTrailers()
|
context?.updateHasTrailers()
|
||||||
activity?.loadCache()
|
activity?.loadCache()
|
||||||
|
|
||||||
activity?.fixPaddingStatusbar(result_top_bar)
|
fixPaddingStatusbar(result_top_bar)
|
||||||
//activity?.fixPaddingStatusbar(result_barstatus)
|
//activity?.fixPaddingStatusbar(result_barstatus)
|
||||||
|
|
||||||
/* val backParameter = result_back.layoutParams as FrameLayout.LayoutParams
|
/* val backParameter = result_back.layoutParams as FrameLayout.LayoutParams
|
||||||
|
@ -588,7 +594,7 @@ open class ResultFragment : ResultTrailerPlayer() {
|
||||||
|
|
||||||
result_episodes?.adapter =
|
result_episodes?.adapter =
|
||||||
EpisodeAdapter(
|
EpisodeAdapter(
|
||||||
api?.hasDownloadSupport == true,
|
api?.hasDownloadSupport == true && !isTvSettings(),
|
||||||
{ episodeClick ->
|
{ episodeClick ->
|
||||||
viewModel.handleAction(activity, episodeClick)
|
viewModel.handleAction(activity, episodeClick)
|
||||||
},
|
},
|
||||||
|
@ -738,10 +744,12 @@ open class ResultFragment : ResultTrailerPlayer() {
|
||||||
|
|
||||||
viewModel.setMeta(d, syncModel.getSyncs())
|
viewModel.setMeta(d, syncModel.getSyncs())
|
||||||
}
|
}
|
||||||
|
|
||||||
is Resource.Loading -> {
|
is Resource.Loading -> {
|
||||||
result_sync_max_episodes?.text =
|
result_sync_max_episodes?.text =
|
||||||
result_sync_max_episodes?.context?.getString(R.string.sync_total_episodes_none)
|
result_sync_max_episodes?.context?.getString(R.string.sync_total_episodes_none)
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> {}
|
else -> {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -755,11 +763,13 @@ open class ResultFragment : ResultTrailerPlayer() {
|
||||||
result_sync_holder?.isVisible = false
|
result_sync_holder?.isVisible = false
|
||||||
closed = true
|
closed = true
|
||||||
}
|
}
|
||||||
|
|
||||||
is Resource.Loading -> {
|
is Resource.Loading -> {
|
||||||
result_sync_loading_shimmer?.startShimmer()
|
result_sync_loading_shimmer?.startShimmer()
|
||||||
result_sync_loading_shimmer?.isVisible = true
|
result_sync_loading_shimmer?.isVisible = true
|
||||||
result_sync_holder?.isVisible = false
|
result_sync_holder?.isVisible = false
|
||||||
}
|
}
|
||||||
|
|
||||||
is Resource.Success -> {
|
is Resource.Success -> {
|
||||||
result_sync_loading_shimmer?.stopShimmer()
|
result_sync_loading_shimmer?.stopShimmer()
|
||||||
result_sync_loading_shimmer?.isVisible = false
|
result_sync_loading_shimmer?.isVisible = false
|
||||||
|
@ -789,6 +799,7 @@ open class ResultFragment : ResultTrailerPlayer() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
null -> {
|
null -> {
|
||||||
closed = false
|
closed = false
|
||||||
}
|
}
|
||||||
|
@ -796,58 +807,56 @@ open class ResultFragment : ResultTrailerPlayer() {
|
||||||
result_overlapping_panels?.setStartPanelLockState(if (closed) OverlappingPanelsLayout.LockState.CLOSE else OverlappingPanelsLayout.LockState.UNLOCKED)
|
result_overlapping_panels?.setStartPanelLockState(if (closed) OverlappingPanelsLayout.LockState.CLOSE else OverlappingPanelsLayout.LockState.UNLOCKED)
|
||||||
}
|
}
|
||||||
|
|
||||||
observe(viewModel.resumeWatching) { resume ->
|
observeNullable(viewModel.resumeWatching) { resume ->
|
||||||
when (resume) {
|
if (resume == null) {
|
||||||
is Some.Success -> {
|
result_resume_parent?.isVisible = false
|
||||||
result_resume_parent?.isVisible = true
|
return@observeNullable
|
||||||
val value = resume.value
|
|
||||||
value.progress?.let { progress ->
|
|
||||||
result_resume_series_title?.apply {
|
|
||||||
isVisible = !value.isMovie
|
|
||||||
text =
|
|
||||||
if (value.isMovie) null else activity?.getNameFull(
|
|
||||||
value.result.name,
|
|
||||||
value.result.episode,
|
|
||||||
value.result.season
|
|
||||||
)
|
|
||||||
}
|
|
||||||
result_resume_series_progress_text.setText(progress.progressLeft)
|
|
||||||
result_resume_series_progress?.apply {
|
|
||||||
isVisible = true
|
|
||||||
this.max = progress.maxProgress
|
|
||||||
this.progress = progress.progress
|
|
||||||
}
|
|
||||||
result_resume_progress_holder?.isVisible = true
|
|
||||||
} ?: run {
|
|
||||||
result_resume_progress_holder?.isVisible = false
|
|
||||||
result_resume_series_progress?.isVisible = false
|
|
||||||
result_resume_series_title?.isVisible = false
|
|
||||||
result_resume_series_progress_text?.isVisible = false
|
|
||||||
}
|
|
||||||
|
|
||||||
result_resume_series_button?.isVisible = !value.isMovie
|
|
||||||
result_resume_series_button_play?.isVisible = !value.isMovie
|
|
||||||
|
|
||||||
val click = View.OnClickListener {
|
|
||||||
viewModel.handleAction(
|
|
||||||
activity,
|
|
||||||
EpisodeClickEvent(
|
|
||||||
storedData?.playerAction ?: ACTION_PLAY_EPISODE_IN_PLAYER,
|
|
||||||
value.result
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
result_resume_series_button?.setOnClickListener(click)
|
|
||||||
result_resume_series_button_play?.setOnClickListener(click)
|
|
||||||
}
|
|
||||||
is Some.None -> {
|
|
||||||
result_resume_parent?.isVisible = false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
result_resume_parent?.isVisible = true
|
||||||
|
resume.progress?.let { progress ->
|
||||||
|
result_resume_series_title?.apply {
|
||||||
|
isVisible = !resume.isMovie
|
||||||
|
text =
|
||||||
|
if (resume.isMovie) null else activity?.getNameFull(
|
||||||
|
resume.result.name,
|
||||||
|
resume.result.episode,
|
||||||
|
resume.result.season
|
||||||
|
)
|
||||||
|
}
|
||||||
|
result_resume_series_progress_text?.setText(progress.progressLeft)
|
||||||
|
result_resume_series_progress?.apply {
|
||||||
|
isVisible = true
|
||||||
|
this.max = progress.maxProgress
|
||||||
|
this.progress = progress.progress
|
||||||
|
}
|
||||||
|
result_resume_progress_holder?.isVisible = true
|
||||||
|
} ?: run {
|
||||||
|
result_resume_progress_holder?.isVisible = false
|
||||||
|
result_resume_series_progress?.isVisible = false
|
||||||
|
result_resume_series_title?.isVisible = false
|
||||||
|
result_resume_series_progress_text?.isVisible = false
|
||||||
|
}
|
||||||
|
|
||||||
|
result_resume_series_button?.isVisible = !resume.isMovie
|
||||||
|
result_resume_series_button_play?.isVisible = !resume.isMovie
|
||||||
|
|
||||||
|
val click = View.OnClickListener {
|
||||||
|
viewModel.handleAction(
|
||||||
|
activity,
|
||||||
|
EpisodeClickEvent(
|
||||||
|
storedData?.playerAction ?: ACTION_PLAY_EPISODE_IN_PLAYER,
|
||||||
|
resume.result
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
result_resume_series_button?.setOnClickListener(click)
|
||||||
|
result_resume_series_button_play?.setOnClickListener(click)
|
||||||
}
|
}
|
||||||
|
|
||||||
observe(viewModel.episodes) { episodes ->
|
|
||||||
|
|
||||||
|
observeNullable(viewModel.episodes) { episodes ->
|
||||||
updateEpisodes(episodes)
|
updateEpisodes(episodes)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -868,7 +877,7 @@ open class ResultFragment : ResultTrailerPlayer() {
|
||||||
setRecommendations(recommendations, null)
|
setRecommendations(recommendations, null)
|
||||||
}
|
}
|
||||||
|
|
||||||
observe(viewModel.movie) { data ->
|
observeNullable(viewModel.movie) { data ->
|
||||||
updateMovie(data)
|
updateMovie(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1046,10 +1055,12 @@ open class ResultFragment : ResultTrailerPlayer() {
|
||||||
}*/
|
}*/
|
||||||
//}
|
//}
|
||||||
}
|
}
|
||||||
|
|
||||||
is Resource.Failure -> {
|
is Resource.Failure -> {
|
||||||
result_error_text.text = storedData?.url?.plus("\n") + data.errorString
|
result_error_text.text = storedData?.url?.plus("\n") + data.errorString
|
||||||
updateVisStatus(1)
|
updateVisStatus(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
is Resource.Loading -> {
|
is Resource.Loading -> {
|
||||||
updateVisStatus(0)
|
updateVisStatus(0)
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,9 +20,9 @@ import com.google.android.gms.cast.framework.CastState
|
||||||
import com.google.android.material.bottomsheet.BottomSheetDialog
|
import com.google.android.material.bottomsheet.BottomSheetDialog
|
||||||
import com.lagradost.cloudstream3.*
|
import com.lagradost.cloudstream3.*
|
||||||
import com.lagradost.cloudstream3.APIHolder.updateHasTrailers
|
import com.lagradost.cloudstream3.APIHolder.updateHasTrailers
|
||||||
import com.lagradost.cloudstream3.mvvm.Some
|
|
||||||
import com.lagradost.cloudstream3.mvvm.logError
|
import com.lagradost.cloudstream3.mvvm.logError
|
||||||
import com.lagradost.cloudstream3.mvvm.observe
|
import com.lagradost.cloudstream3.mvvm.observe
|
||||||
|
import com.lagradost.cloudstream3.mvvm.observeNullable
|
||||||
import com.lagradost.cloudstream3.ui.player.CSPlayerEvent
|
import com.lagradost.cloudstream3.ui.player.CSPlayerEvent
|
||||||
import com.lagradost.cloudstream3.ui.search.SearchAdapter
|
import com.lagradost.cloudstream3.ui.search.SearchAdapter
|
||||||
import com.lagradost.cloudstream3.ui.search.SearchHelper
|
import com.lagradost.cloudstream3.ui.search.SearchHelper
|
||||||
|
@ -212,7 +212,6 @@ class ResultFragmentPhone : ResultFragment() {
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
result_mini_sync?.adapter = ImageAdapter(
|
result_mini_sync?.adapter = ImageAdapter(
|
||||||
R.layout.result_mini_image,
|
|
||||||
nextFocusDown = R.id.result_sync_set_score,
|
nextFocusDown = R.id.result_sync_set_score,
|
||||||
clickCallback = { action ->
|
clickCallback = { action ->
|
||||||
if (action == IMAGE_CLICK || action == IMAGE_LONG_CLICK) {
|
if (action == IMAGE_CLICK || action == IMAGE_LONG_CLICK) {
|
||||||
|
@ -271,73 +270,68 @@ class ResultFragmentPhone : ResultFragment() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
observe(viewModel.episodesCountText) { count ->
|
observeNullable(viewModel.episodesCountText) { count ->
|
||||||
result_episodes_text.setText(count)
|
result_episodes_text.setText(count)
|
||||||
}
|
}
|
||||||
|
|
||||||
observe(viewModel.selectPopup) { popup ->
|
observeNullable(viewModel.selectPopup) { popup ->
|
||||||
when (popup) {
|
if (popup == null) {
|
||||||
is Some.Success -> {
|
popupDialog?.dismissSafe(activity)
|
||||||
popupDialog?.dismissSafe(activity)
|
popupDialog = null
|
||||||
|
return@observeNullable
|
||||||
popupDialog = activity?.let { act ->
|
|
||||||
val pop = popup.value
|
|
||||||
val options = pop.getOptions(act)
|
|
||||||
val title = pop.getTitle(act)
|
|
||||||
|
|
||||||
act.showBottomDialogInstant(
|
|
||||||
options, title, {
|
|
||||||
popupDialog = null
|
|
||||||
pop.callback(null)
|
|
||||||
}, {
|
|
||||||
popupDialog = null
|
|
||||||
pop.callback(it)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
is Some.None -> {
|
|
||||||
popupDialog?.dismissSafe(activity)
|
|
||||||
popupDialog = null
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
popupDialog?.dismissSafe(activity)
|
||||||
|
|
||||||
|
popupDialog = activity?.let { act ->
|
||||||
|
val options = popup.getOptions(act)
|
||||||
|
val title = popup.getTitle(act)
|
||||||
|
|
||||||
|
act.showBottomDialogInstant(
|
||||||
|
options, title, {
|
||||||
|
popupDialog = null
|
||||||
|
popup.callback(null)
|
||||||
|
}, {
|
||||||
|
popupDialog = null
|
||||||
|
popup.callback(it)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
observe(viewModel.loadedLinks) { load ->
|
observe(viewModel.loadedLinks) { load ->
|
||||||
when (load) {
|
if (load == null) {
|
||||||
is Some.Success -> {
|
loadingDialog?.dismissSafe(activity)
|
||||||
if (loadingDialog?.isShowing != true) {
|
loadingDialog = null
|
||||||
loadingDialog?.dismissSafe(activity)
|
return@observe
|
||||||
loadingDialog = null
|
}
|
||||||
}
|
if (loadingDialog?.isShowing != true) {
|
||||||
loadingDialog = loadingDialog ?: context?.let { ctx ->
|
loadingDialog?.dismissSafe(activity)
|
||||||
val builder =
|
loadingDialog = null
|
||||||
BottomSheetDialog(ctx)
|
}
|
||||||
builder.setContentView(R.layout.bottom_loading)
|
loadingDialog = loadingDialog ?: context?.let { ctx ->
|
||||||
builder.setOnDismissListener {
|
val builder =
|
||||||
loadingDialog = null
|
BottomSheetDialog(ctx)
|
||||||
viewModel.cancelLinks()
|
builder.setContentView(R.layout.bottom_loading)
|
||||||
}
|
builder.setOnDismissListener {
|
||||||
//builder.setOnCancelListener {
|
|
||||||
// it?.dismiss()
|
|
||||||
//}
|
|
||||||
builder.setCanceledOnTouchOutside(true)
|
|
||||||
builder.show()
|
|
||||||
builder
|
|
||||||
}
|
|
||||||
}
|
|
||||||
is Some.None -> {
|
|
||||||
loadingDialog?.dismissSafe(activity)
|
|
||||||
loadingDialog = null
|
loadingDialog = null
|
||||||
|
viewModel.cancelLinks()
|
||||||
}
|
}
|
||||||
|
//builder.setOnCancelListener {
|
||||||
|
// it?.dismiss()
|
||||||
|
//}
|
||||||
|
builder.setCanceledOnTouchOutside(true)
|
||||||
|
builder.show()
|
||||||
|
builder
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
observe(viewModel.selectedSeason) { text ->
|
observeNullable(viewModel.selectedSeason) { text ->
|
||||||
result_season_button.setText(text)
|
result_season_button.setText(text)
|
||||||
|
|
||||||
selectSeason =
|
selectSeason =
|
||||||
(if (text is Some.Success) text.value else null)?.asStringNull(result_season_button?.context)
|
text?.asStringNull(result_season_button?.context)
|
||||||
// If the season button is visible the result season button will be next focus down
|
// If the season button is visible the result season button will be next focus down
|
||||||
if (result_season_button?.isVisible == true)
|
if (result_season_button?.isVisible == true)
|
||||||
if (result_resume_parent?.isVisible == true)
|
if (result_resume_parent?.isVisible == true)
|
||||||
|
@ -346,7 +340,7 @@ class ResultFragmentPhone : ResultFragment() {
|
||||||
// setFocusUpAndDown(result_bookmark_button, result_season_button)
|
// setFocusUpAndDown(result_bookmark_button, result_season_button)
|
||||||
}
|
}
|
||||||
|
|
||||||
observe(viewModel.selectedDubStatus) { status ->
|
observeNullable(viewModel.selectedDubStatus) { status ->
|
||||||
result_dub_select?.setText(status)
|
result_dub_select?.setText(status)
|
||||||
|
|
||||||
if (result_dub_select?.isVisible == true)
|
if (result_dub_select?.isVisible == true)
|
||||||
|
@ -357,7 +351,7 @@ class ResultFragmentPhone : ResultFragment() {
|
||||||
// setFocusUpAndDown(result_bookmark_button, result_dub_select)
|
// setFocusUpAndDown(result_bookmark_button, result_dub_select)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
observe(viewModel.selectedRange) { range ->
|
observeNullable(viewModel.selectedRange) { range ->
|
||||||
result_episode_select.setText(range)
|
result_episode_select.setText(range)
|
||||||
|
|
||||||
// If Season button is invisible then the bookmark button next focus is episode select
|
// If Season button is invisible then the bookmark button next focus is episode select
|
||||||
|
|
|
@ -12,9 +12,9 @@ import com.lagradost.cloudstream3.DubStatus
|
||||||
import com.lagradost.cloudstream3.LoadResponse
|
import com.lagradost.cloudstream3.LoadResponse
|
||||||
import com.lagradost.cloudstream3.R
|
import com.lagradost.cloudstream3.R
|
||||||
import com.lagradost.cloudstream3.SearchResponse
|
import com.lagradost.cloudstream3.SearchResponse
|
||||||
import com.lagradost.cloudstream3.mvvm.ResourceSome
|
import com.lagradost.cloudstream3.mvvm.Resource
|
||||||
import com.lagradost.cloudstream3.mvvm.Some
|
|
||||||
import com.lagradost.cloudstream3.mvvm.observe
|
import com.lagradost.cloudstream3.mvvm.observe
|
||||||
|
import com.lagradost.cloudstream3.mvvm.observeNullable
|
||||||
import com.lagradost.cloudstream3.ui.player.ExtractorLinkGenerator
|
import com.lagradost.cloudstream3.ui.player.ExtractorLinkGenerator
|
||||||
import com.lagradost.cloudstream3.ui.player.GeneratorPlayer
|
import com.lagradost.cloudstream3.ui.player.GeneratorPlayer
|
||||||
import com.lagradost.cloudstream3.ui.search.SearchAdapter
|
import com.lagradost.cloudstream3.ui.search.SearchAdapter
|
||||||
|
@ -69,16 +69,16 @@ class ResultFragmentTv : ResultFragment() {
|
||||||
return focus == this.result_root
|
return focus == this.result_root
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun updateEpisodes(episodes: ResourceSome<List<ResultEpisode>>) {
|
override fun updateEpisodes(episodes: Resource<List<ResultEpisode>>?) {
|
||||||
super.updateEpisodes(episodes)
|
super.updateEpisodes(episodes)
|
||||||
if (episodes is ResourceSome.Success && hasNoFocus()) {
|
if (episodes is Resource.Success && hasNoFocus()) {
|
||||||
result_episodes?.requestFocus()
|
result_episodes?.requestFocus()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun updateMovie(data: ResourceSome<Pair<UiText, ResultEpisode>>) {
|
override fun updateMovie(data: Resource<Pair<UiText, ResultEpisode>>?) {
|
||||||
super.updateMovie(data)
|
super.updateMovie(data)
|
||||||
if (data is ResourceSome.Success && hasNoFocus()) {
|
if (data is Resource.Success && hasNoFocus()) {
|
||||||
result_play_movie?.requestFocus()
|
result_play_movie?.requestFocus()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -130,9 +130,9 @@ class ResultFragmentTv : ResultFragment() {
|
||||||
LinearListLayout(result_episodes?.context).apply {
|
LinearListLayout(result_episodes?.context).apply {
|
||||||
setHorizontal()
|
setHorizontal()
|
||||||
}
|
}
|
||||||
(result_episodes?.adapter as EpisodeAdapter?)?.apply {
|
// (result_episodes?.adapter as EpisodeAdapter?)?.apply {
|
||||||
layout = R.layout.result_episode_both_tv
|
// layout = R.layout.result_episode_both_tv
|
||||||
}
|
// }
|
||||||
//result_episodes?.setMaxViewPoolSize(0, Int.MAX_VALUE)
|
//result_episodes?.setMaxViewPoolSize(0, Int.MAX_VALUE)
|
||||||
|
|
||||||
result_season_selection.setAdapter()
|
result_season_selection.setAdapter()
|
||||||
|
@ -140,37 +140,37 @@ class ResultFragmentTv : ResultFragment() {
|
||||||
result_dub_selection.setAdapter()
|
result_dub_selection.setAdapter()
|
||||||
result_recommendations_filter_selection.setAdapter()
|
result_recommendations_filter_selection.setAdapter()
|
||||||
|
|
||||||
observe(viewModel.selectPopup) { popup ->
|
observeNullable(viewModel.selectPopup) { popup ->
|
||||||
when (popup) {
|
if(popup == null) {
|
||||||
is Some.Success -> {
|
popupDialog?.dismissSafe(activity)
|
||||||
popupDialog?.dismissSafe(activity)
|
popupDialog = null
|
||||||
|
return@observeNullable
|
||||||
|
}
|
||||||
|
|
||||||
popupDialog = activity?.let { act ->
|
popupDialog?.dismissSafe(activity)
|
||||||
val pop = popup.value
|
|
||||||
val options = pop.getOptions(act)
|
|
||||||
val title = pop.getTitle(act)
|
|
||||||
|
|
||||||
act.showBottomDialogInstant(
|
popupDialog = activity?.let { act ->
|
||||||
options, title, {
|
val options = popup.getOptions(act)
|
||||||
popupDialog = null
|
val title = popup.getTitle(act)
|
||||||
pop.callback(null)
|
|
||||||
}, {
|
act.showBottomDialogInstant(
|
||||||
popupDialog = null
|
options, title, {
|
||||||
pop.callback(it)
|
popupDialog = null
|
||||||
}
|
popup.callback(null)
|
||||||
)
|
}, {
|
||||||
|
popupDialog = null
|
||||||
|
popup.callback(it)
|
||||||
}
|
}
|
||||||
}
|
)
|
||||||
is Some.None -> {
|
|
||||||
popupDialog?.dismissSafe(activity)
|
|
||||||
popupDialog = null
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
observe(viewModel.loadedLinks) { load ->
|
observeNullable(viewModel.loadedLinks) { load ->
|
||||||
when (load) {
|
if(load == null) {
|
||||||
is Some.Success -> {
|
loadingDialog?.dismissSafe(activity)
|
||||||
|
loadingDialog = null
|
||||||
|
return@observeNullable
|
||||||
|
}
|
||||||
if (loadingDialog?.isShowing != true) {
|
if (loadingDialog?.isShowing != true) {
|
||||||
loadingDialog?.dismissSafe(activity)
|
loadingDialog?.dismissSafe(activity)
|
||||||
loadingDialog = null
|
loadingDialog = null
|
||||||
|
@ -189,16 +189,11 @@ class ResultFragmentTv : ResultFragment() {
|
||||||
builder.show()
|
builder.show()
|
||||||
builder
|
builder
|
||||||
}
|
}
|
||||||
}
|
|
||||||
is Some.None -> {
|
|
||||||
loadingDialog?.dismissSafe(activity)
|
|
||||||
loadingDialog = null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
observe(viewModel.episodesCountText) { count ->
|
observeNullable(viewModel.episodesCountText) { count ->
|
||||||
result_episodes_text.setText(count)
|
result_episodes_text.setText(count)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -145,15 +145,18 @@ fun LoadResponse.toResultData(repo: APIRepository): ResultData {
|
||||||
minute
|
minute
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
hours > 0 -> txt(
|
hours > 0 -> txt(
|
||||||
R.string.next_episode_time_hour_format,
|
R.string.next_episode_time_hour_format,
|
||||||
hours,
|
hours,
|
||||||
minute
|
minute
|
||||||
)
|
)
|
||||||
|
|
||||||
minute > 0 -> txt(
|
minute > 0 -> txt(
|
||||||
R.string.next_episode_time_min_format,
|
R.string.next_episode_time_min_format,
|
||||||
minute
|
minute
|
||||||
)
|
)
|
||||||
|
|
||||||
else -> null
|
else -> null
|
||||||
}?.also {
|
}?.also {
|
||||||
nextAiringEpisode = txt(R.string.next_episode_format, airing.episode)
|
nextAiringEpisode = txt(R.string.next_episode_format, airing.episode)
|
||||||
|
@ -305,6 +308,7 @@ fun SelectPopup.getOptions(context: Context): List<String> {
|
||||||
is SelectPopup.SelectArray -> {
|
is SelectPopup.SelectArray -> {
|
||||||
this.options.map { it.first.asString(context) }
|
this.options.map { it.first.asString(context) }
|
||||||
}
|
}
|
||||||
|
|
||||||
is SelectPopup.SelectText -> options.map { it.asString(context) }
|
is SelectPopup.SelectText -> options.map { it.asString(context) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -352,17 +356,17 @@ class ResultViewModel2 : ViewModel() {
|
||||||
MutableLiveData(null)
|
MutableLiveData(null)
|
||||||
val page: LiveData<Resource<ResultData>?> = _page
|
val page: LiveData<Resource<ResultData>?> = _page
|
||||||
|
|
||||||
private val _episodes: MutableLiveData<ResourceSome<List<ResultEpisode>>> =
|
private val _episodes: MutableLiveData<Resource<List<ResultEpisode>>?> =
|
||||||
MutableLiveData(ResourceSome.Loading())
|
MutableLiveData(Resource.Loading())
|
||||||
val episodes: LiveData<ResourceSome<List<ResultEpisode>>> = _episodes
|
val episodes: LiveData<Resource<List<ResultEpisode>>?> = _episodes
|
||||||
|
|
||||||
private val _movie: MutableLiveData<ResourceSome<Pair<UiText, ResultEpisode>>> =
|
private val _movie: MutableLiveData<Resource<Pair<UiText, ResultEpisode>>?> =
|
||||||
MutableLiveData(ResourceSome.None)
|
MutableLiveData(null)
|
||||||
val movie: LiveData<ResourceSome<Pair<UiText, ResultEpisode>>> = _movie
|
val movie: LiveData<Resource<Pair<UiText, ResultEpisode>>?> = _movie
|
||||||
|
|
||||||
private val _episodesCountText: MutableLiveData<Some<UiText>> =
|
private val _episodesCountText: MutableLiveData<UiText?> =
|
||||||
MutableLiveData(Some.None)
|
MutableLiveData(null)
|
||||||
val episodesCountText: LiveData<Some<UiText>> = _episodesCountText
|
val episodesCountText: LiveData<UiText?> = _episodesCountText
|
||||||
|
|
||||||
private val _trailers: MutableLiveData<List<ExtractedTrailerData>> =
|
private val _trailers: MutableLiveData<List<ExtractedTrailerData>> =
|
||||||
MutableLiveData(mutableListOf())
|
MutableLiveData(mutableListOf())
|
||||||
|
@ -384,16 +388,16 @@ class ResultViewModel2 : ViewModel() {
|
||||||
MutableLiveData(emptyList())
|
MutableLiveData(emptyList())
|
||||||
val recommendations: LiveData<List<SearchResponse>> = _recommendations
|
val recommendations: LiveData<List<SearchResponse>> = _recommendations
|
||||||
|
|
||||||
private val _selectedRange: MutableLiveData<Some<UiText>> =
|
private val _selectedRange: MutableLiveData<UiText?> =
|
||||||
MutableLiveData(Some.None)
|
MutableLiveData(null)
|
||||||
val selectedRange: LiveData<Some<UiText>> = _selectedRange
|
val selectedRange: LiveData<UiText?> = _selectedRange
|
||||||
|
|
||||||
private val _selectedSeason: MutableLiveData<Some<UiText>> =
|
private val _selectedSeason: MutableLiveData<UiText?> =
|
||||||
MutableLiveData(Some.None)
|
MutableLiveData(null)
|
||||||
val selectedSeason: LiveData<Some<UiText>> = _selectedSeason
|
val selectedSeason: LiveData<UiText?> = _selectedSeason
|
||||||
|
|
||||||
private val _selectedDubStatus: MutableLiveData<Some<UiText>> = MutableLiveData(Some.None)
|
private val _selectedDubStatus: MutableLiveData<UiText?> = MutableLiveData(null)
|
||||||
val selectedDubStatus: LiveData<Some<UiText>> = _selectedDubStatus
|
val selectedDubStatus: LiveData<UiText?> = _selectedDubStatus
|
||||||
|
|
||||||
private val _selectedRangeIndex: MutableLiveData<Int> =
|
private val _selectedRangeIndex: MutableLiveData<Int> =
|
||||||
MutableLiveData(-1)
|
MutableLiveData(-1)
|
||||||
|
@ -406,12 +410,12 @@ class ResultViewModel2 : ViewModel() {
|
||||||
private val _selectedDubStatusIndex: MutableLiveData<Int> = MutableLiveData(-1)
|
private val _selectedDubStatusIndex: MutableLiveData<Int> = MutableLiveData(-1)
|
||||||
val selectedDubStatusIndex: LiveData<Int> = _selectedDubStatusIndex
|
val selectedDubStatusIndex: LiveData<Int> = _selectedDubStatusIndex
|
||||||
|
|
||||||
private val _loadedLinks: MutableLiveData<Some<LinkProgress>> = MutableLiveData(Some.None)
|
private val _loadedLinks: MutableLiveData<LinkProgress?> = MutableLiveData(null)
|
||||||
val loadedLinks: LiveData<Some<LinkProgress>> = _loadedLinks
|
val loadedLinks: LiveData<LinkProgress?> = _loadedLinks
|
||||||
|
|
||||||
private val _resumeWatching: MutableLiveData<Some<ResumeWatchingStatus>> =
|
private val _resumeWatching: MutableLiveData<ResumeWatchingStatus?> =
|
||||||
MutableLiveData(Some.None)
|
MutableLiveData(null)
|
||||||
val resumeWatching: LiveData<Some<ResumeWatchingStatus>> = _resumeWatching
|
val resumeWatching: LiveData<ResumeWatchingStatus?> = _resumeWatching
|
||||||
|
|
||||||
private val _episodeSynopsis: MutableLiveData<String?> = MutableLiveData(null)
|
private val _episodeSynopsis: MutableLiveData<String?> = MutableLiveData(null)
|
||||||
val episodeSynopsis: LiveData<String?> = _episodeSynopsis
|
val episodeSynopsis: LiveData<String?> = _episodeSynopsis
|
||||||
|
@ -800,8 +804,8 @@ class ResultViewModel2 : ViewModel() {
|
||||||
private val _watchStatus: MutableLiveData<WatchType> = MutableLiveData(WatchType.NONE)
|
private val _watchStatus: MutableLiveData<WatchType> = MutableLiveData(WatchType.NONE)
|
||||||
val watchStatus: LiveData<WatchType> get() = _watchStatus
|
val watchStatus: LiveData<WatchType> get() = _watchStatus
|
||||||
|
|
||||||
private val _selectPopup: MutableLiveData<Some<SelectPopup>> = MutableLiveData(Some.None)
|
private val _selectPopup: MutableLiveData<SelectPopup?> = MutableLiveData(null)
|
||||||
val selectPopup: LiveData<Some<SelectPopup>> get() = _selectPopup
|
val selectPopup: LiveData<SelectPopup?> = _selectPopup
|
||||||
|
|
||||||
|
|
||||||
fun updateWatchStatus(status: WatchType) {
|
fun updateWatchStatus(status: WatchType) {
|
||||||
|
@ -885,23 +889,22 @@ class ResultViewModel2 : ViewModel() {
|
||||||
}
|
}
|
||||||
|
|
||||||
fun cancelLinks() {
|
fun cancelLinks() {
|
||||||
println("called::cancelLinks")
|
|
||||||
currentLoadLinkJob?.cancel()
|
currentLoadLinkJob?.cancel()
|
||||||
currentLoadLinkJob = null
|
currentLoadLinkJob = null
|
||||||
_loadedLinks.postValue(Some.None)
|
_loadedLinks.postValue(null)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun postPopup(text: UiText, options: List<UiText>, callback: suspend (Int?) -> Unit) {
|
private fun postPopup(text: UiText, options: List<UiText>, callback: suspend (Int?) -> Unit) {
|
||||||
_selectPopup.postValue(
|
_selectPopup.postValue(
|
||||||
some(SelectPopup.SelectText(
|
SelectPopup.SelectText(
|
||||||
text,
|
text,
|
||||||
options
|
options
|
||||||
) { value ->
|
) { value ->
|
||||||
viewModelScope.launchSafe {
|
viewModelScope.launchSafe {
|
||||||
_selectPopup.postValue(Some.None)
|
_selectPopup.postValue(null)
|
||||||
callback.invoke(value)
|
callback.invoke(value)
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -912,15 +915,15 @@ class ResultViewModel2 : ViewModel() {
|
||||||
callback: suspend (Int?) -> Unit
|
callback: suspend (Int?) -> Unit
|
||||||
) {
|
) {
|
||||||
_selectPopup.postValue(
|
_selectPopup.postValue(
|
||||||
some(SelectPopup.SelectArray(
|
SelectPopup.SelectArray(
|
||||||
text,
|
text,
|
||||||
options,
|
options,
|
||||||
) { value ->
|
) { value ->
|
||||||
viewModelScope.launchSafe {
|
viewModelScope.launchSafe {
|
||||||
_selectPopup.value = Some.None
|
_selectPopup.postValue(null)
|
||||||
callback.invoke(value)
|
callback.invoke(value)
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -988,7 +991,7 @@ class ResultViewModel2 : ViewModel() {
|
||||||
val subs: MutableSet<SubtitleData> = mutableSetOf()
|
val subs: MutableSet<SubtitleData> = mutableSetOf()
|
||||||
fun updatePage() {
|
fun updatePage() {
|
||||||
if (isVisible && isActive) {
|
if (isVisible && isActive) {
|
||||||
_loadedLinks.postValue(some(LinkProgress(links.size, subs.size)))
|
_loadedLinks.postValue(LinkProgress(links.size, subs.size))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
|
@ -1005,7 +1008,7 @@ class ResultViewModel2 : ViewModel() {
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
logError(e)
|
logError(e)
|
||||||
} finally {
|
} finally {
|
||||||
_loadedLinks.postValue(Some.None)
|
_loadedLinks.postValue(null)
|
||||||
}
|
}
|
||||||
|
|
||||||
return LinkLoadingResult(sortUrls(links), sortSubs(subs))
|
return LinkLoadingResult(sortUrls(links), sortSubs(subs))
|
||||||
|
@ -1233,6 +1236,7 @@ class ResultViewModel2 : ViewModel() {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ACTION_CLICK_DEFAULT -> {
|
ACTION_CLICK_DEFAULT -> {
|
||||||
activity?.let { ctx ->
|
activity?.let { ctx ->
|
||||||
if (ctx.isConnectedToChromecast()) {
|
if (ctx.isConnectedToChromecast()) {
|
||||||
|
@ -1249,6 +1253,7 @@ class ResultViewModel2 : ViewModel() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ACTION_SHOW_DESCRIPTION -> {
|
ACTION_SHOW_DESCRIPTION -> {
|
||||||
_episodeSynopsis.postValue(click.data.description)
|
_episodeSynopsis.postValue(click.data.description)
|
||||||
}
|
}
|
||||||
|
@ -1286,9 +1291,11 @@ class ResultViewModel2 : ViewModel() {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ACTION_SHOW_TOAST -> {
|
ACTION_SHOW_TOAST -> {
|
||||||
showToast(activity, R.string.play_episode_toast, Toast.LENGTH_SHORT)
|
showToast(activity, R.string.play_episode_toast, Toast.LENGTH_SHORT)
|
||||||
}
|
}
|
||||||
|
|
||||||
ACTION_DOWNLOAD_EPISODE -> {
|
ACTION_DOWNLOAD_EPISODE -> {
|
||||||
val response = currentResponse ?: return
|
val response = currentResponse ?: return
|
||||||
downloadEpisode(
|
downloadEpisode(
|
||||||
|
@ -1303,6 +1310,7 @@ class ResultViewModel2 : ViewModel() {
|
||||||
response.url
|
response.url
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
ACTION_DOWNLOAD_MIRROR -> {
|
ACTION_DOWNLOAD_MIRROR -> {
|
||||||
val response = currentResponse ?: return
|
val response = currentResponse ?: return
|
||||||
acquireSingleLink(
|
acquireSingleLink(
|
||||||
|
@ -1332,6 +1340,7 @@ class ResultViewModel2 : ViewModel() {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ACTION_RELOAD_EPISODE -> {
|
ACTION_RELOAD_EPISODE -> {
|
||||||
ioSafe {
|
ioSafe {
|
||||||
loadLinks(
|
loadLinks(
|
||||||
|
@ -1342,6 +1351,7 @@ class ResultViewModel2 : ViewModel() {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ACTION_CHROME_CAST_MIRROR -> {
|
ACTION_CHROME_CAST_MIRROR -> {
|
||||||
acquireSingleLink(
|
acquireSingleLink(
|
||||||
click.data,
|
click.data,
|
||||||
|
@ -1351,6 +1361,7 @@ class ResultViewModel2 : ViewModel() {
|
||||||
startChromecast(activity, click.data, result.links, result.subs, index)
|
startChromecast(activity, click.data, result.links, result.subs, index)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ACTION_PLAY_EPISODE_IN_BROWSER -> acquireSingleLink(
|
ACTION_PLAY_EPISODE_IN_BROWSER -> acquireSingleLink(
|
||||||
click.data,
|
click.data,
|
||||||
isCasting = true,
|
isCasting = true,
|
||||||
|
@ -1364,6 +1375,7 @@ class ResultViewModel2 : ViewModel() {
|
||||||
logError(e)
|
logError(e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ACTION_COPY_LINK -> {
|
ACTION_COPY_LINK -> {
|
||||||
acquireSingleLink(
|
acquireSingleLink(
|
||||||
click.data,
|
click.data,
|
||||||
|
@ -1380,9 +1392,11 @@ class ResultViewModel2 : ViewModel() {
|
||||||
showToast(act, R.string.copy_link_toast, Toast.LENGTH_SHORT)
|
showToast(act, R.string.copy_link_toast, Toast.LENGTH_SHORT)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ACTION_CHROME_CAST_EPISODE -> {
|
ACTION_CHROME_CAST_EPISODE -> {
|
||||||
startChromecast(activity, click.data)
|
startChromecast(activity, click.data)
|
||||||
}
|
}
|
||||||
|
|
||||||
ACTION_PLAY_EPISODE_IN_VLC_PLAYER -> {
|
ACTION_PLAY_EPISODE_IN_VLC_PLAYER -> {
|
||||||
loadLinks(click.data, isVisible = true, isCasting = true) { links ->
|
loadLinks(click.data, isVisible = true, isCasting = true) { links ->
|
||||||
if (links.links.isEmpty()) {
|
if (links.links.isEmpty()) {
|
||||||
|
@ -1397,6 +1411,7 @@ class ResultViewModel2 : ViewModel() {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ACTION_PLAY_EPISODE_IN_WEB_VIDEO -> acquireSingleLink(
|
ACTION_PLAY_EPISODE_IN_WEB_VIDEO -> acquireSingleLink(
|
||||||
click.data,
|
click.data,
|
||||||
isCasting = true,
|
isCasting = true,
|
||||||
|
@ -1413,6 +1428,7 @@ class ResultViewModel2 : ViewModel() {
|
||||||
result.subs
|
result.subs
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
ACTION_PLAY_EPISODE_IN_MPV -> acquireSingleLink(
|
ACTION_PLAY_EPISODE_IN_MPV -> acquireSingleLink(
|
||||||
click.data,
|
click.data,
|
||||||
isCasting = true,
|
isCasting = true,
|
||||||
|
@ -1428,6 +1444,7 @@ class ResultViewModel2 : ViewModel() {
|
||||||
result.subs
|
result.subs
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
ACTION_PLAY_EPISODE_IN_PLAYER -> {
|
ACTION_PLAY_EPISODE_IN_PLAYER -> {
|
||||||
val data = currentResponse?.syncData?.toList() ?: emptyList()
|
val data = currentResponse?.syncData?.toList() ?: emptyList()
|
||||||
val list =
|
val list =
|
||||||
|
@ -1448,6 +1465,7 @@ class ResultViewModel2 : ViewModel() {
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
ACTION_MARK_AS_WATCHED -> {
|
ACTION_MARK_AS_WATCHED -> {
|
||||||
val isWatched =
|
val isWatched =
|
||||||
DataStoreHelper.getVideoWatchState(click.data.id) == VideoWatchState.Watched
|
DataStoreHelper.getVideoWatchState(click.data.id) == VideoWatchState.Watched
|
||||||
|
@ -1672,10 +1690,10 @@ class ResultViewModel2 : ViewModel() {
|
||||||
|
|
||||||
private fun postMovie() {
|
private fun postMovie() {
|
||||||
val response = currentResponse
|
val response = currentResponse
|
||||||
_episodes.postValue(ResourceSome.None)
|
_episodes.postValue(null)
|
||||||
|
|
||||||
if (response == null) {
|
if (response == null) {
|
||||||
_movie.postValue(ResourceSome.None)
|
_movie.postValue(null)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1692,11 +1710,11 @@ class ResultViewModel2 : ViewModel() {
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
val data = getMovie()
|
val data = getMovie()
|
||||||
_episodes.postValue(ResourceSome.None)
|
_episodes.postValue(null)
|
||||||
if (text == null || data == null) {
|
if (text == null || data == null) {
|
||||||
_movie.postValue(ResourceSome.None)
|
_movie.postValue(null)
|
||||||
} else {
|
} else {
|
||||||
_movie.postValue(ResourceSome.Success(text to data))
|
_movie.postValue(Resource.Success(text to data))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1705,14 +1723,14 @@ class ResultViewModel2 : ViewModel() {
|
||||||
postMovie()
|
postMovie()
|
||||||
} else {
|
} else {
|
||||||
_episodes.postValue(
|
_episodes.postValue(
|
||||||
ResourceSome.Success(
|
Resource.Success(
|
||||||
getEpisodes(
|
getEpisodes(
|
||||||
currentIndex ?: return,
|
currentIndex ?: return,
|
||||||
currentRange ?: return
|
currentRange ?: return
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
_movie.postValue(ResourceSome.None)
|
_movie.postValue(null)
|
||||||
}
|
}
|
||||||
postResume()
|
postResume()
|
||||||
}
|
}
|
||||||
|
@ -1755,14 +1773,14 @@ class ResultViewModel2 : ViewModel() {
|
||||||
|
|
||||||
val size = currentEpisodes[indexer]?.size
|
val size = currentEpisodes[indexer]?.size
|
||||||
_episodesCountText.postValue(
|
_episodesCountText.postValue(
|
||||||
some(
|
|
||||||
if (isMovie) null else
|
if (isMovie) null else
|
||||||
txt(
|
txt(
|
||||||
R.string.episode_format,
|
R.string.episode_format,
|
||||||
size,
|
size,
|
||||||
txt(if (size == 1) R.string.episode else R.string.episodes),
|
txt(if (size == 1) R.string.episode else R.string.episodes),
|
||||||
)
|
)
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
_selectedSeasonIndex.postValue(
|
_selectedSeasonIndex.postValue(
|
||||||
|
@ -1770,29 +1788,29 @@ class ResultViewModel2 : ViewModel() {
|
||||||
)
|
)
|
||||||
|
|
||||||
_selectedSeason.postValue(
|
_selectedSeason.postValue(
|
||||||
some(
|
|
||||||
if (isMovie || currentSeasons.size <= 1) null else
|
|
||||||
when (indexer.season) {
|
|
||||||
0 -> txt(R.string.no_season)
|
|
||||||
else -> {
|
|
||||||
val seasonNames = (currentResponse as? EpisodeResponse)?.seasonNames
|
|
||||||
val seasonData = seasonNames.getSeason(indexer.season)
|
|
||||||
|
|
||||||
// If displaySeason is null then only show the name!
|
if (isMovie || currentSeasons.size <= 1) null else
|
||||||
if (seasonData?.name != null && seasonData.displaySeason == null) {
|
when (indexer.season) {
|
||||||
txt(seasonData.name)
|
0 -> txt(R.string.no_season)
|
||||||
} else {
|
else -> {
|
||||||
val suffix = seasonData?.name?.let { " $it" } ?: ""
|
val seasonNames = (currentResponse as? EpisodeResponse)?.seasonNames
|
||||||
txt(
|
val seasonData = seasonNames.getSeason(indexer.season)
|
||||||
R.string.season_format,
|
|
||||||
txt(R.string.season),
|
// If displaySeason is null then only show the name!
|
||||||
seasonData?.displaySeason ?: indexer.season,
|
if (seasonData?.name != null && seasonData.displaySeason == null) {
|
||||||
suffix
|
txt(seasonData.name)
|
||||||
)
|
} else {
|
||||||
}
|
val suffix = seasonData?.name?.let { " $it" } ?: ""
|
||||||
|
txt(
|
||||||
|
R.string.season_format,
|
||||||
|
txt(R.string.season),
|
||||||
|
seasonData?.displaySeason ?: indexer.season,
|
||||||
|
suffix
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
}
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|
||||||
_selectedRangeIndex.postValue(
|
_selectedRangeIndex.postValue(
|
||||||
|
@ -1800,13 +1818,13 @@ class ResultViewModel2 : ViewModel() {
|
||||||
)
|
)
|
||||||
|
|
||||||
_selectedRange.postValue(
|
_selectedRange.postValue(
|
||||||
some(
|
|
||||||
if (isMovie) null else if ((currentRanges[indexer]?.size ?: 0) > 1) {
|
if (isMovie) null else if ((currentRanges[indexer]?.size ?: 0) > 1) {
|
||||||
txt(R.string.episodes_range, range.startEpisode, range.endEpisode)
|
txt(R.string.episodes_range, range.startEpisode, range.endEpisode)
|
||||||
} else {
|
} else {
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
_selectedDubStatusIndex.postValue(
|
_selectedDubStatusIndex.postValue(
|
||||||
|
@ -1814,10 +1832,10 @@ class ResultViewModel2 : ViewModel() {
|
||||||
)
|
)
|
||||||
|
|
||||||
_selectedDubStatus.postValue(
|
_selectedDubStatus.postValue(
|
||||||
some(
|
|
||||||
if (isMovie || currentDubStatus.size <= 1) null else
|
if (isMovie || currentDubStatus.size <= 1) null else
|
||||||
txt(indexer.dubStatus)
|
txt(indexer.dubStatus)
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
currentId?.let { id ->
|
currentId?.let { id ->
|
||||||
|
@ -1851,7 +1869,7 @@ class ResultViewModel2 : ViewModel() {
|
||||||
|
|
||||||
}
|
}
|
||||||
}*/
|
}*/
|
||||||
_episodes.postValue(ResourceSome.Success(ret))
|
_episodes.postValue(Resource.Success(ret))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1869,7 +1887,7 @@ class ResultViewModel2 : ViewModel() {
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun postEpisodes(loadResponse: LoadResponse, updateFillers: Boolean) {
|
private suspend fun postEpisodes(loadResponse: LoadResponse, updateFillers: Boolean) {
|
||||||
_episodes.postValue(ResourceSome.Loading())
|
_episodes.postValue(Resource.Loading())
|
||||||
|
|
||||||
val mainId = loadResponse.getId()
|
val mainId = loadResponse.getId()
|
||||||
currentId = mainId
|
currentId = mainId
|
||||||
|
@ -1924,6 +1942,7 @@ class ResultViewModel2 : ViewModel() {
|
||||||
}
|
}
|
||||||
episodes
|
episodes
|
||||||
}
|
}
|
||||||
|
|
||||||
is TvSeriesLoadResponse -> {
|
is TvSeriesLoadResponse -> {
|
||||||
val episodes: MutableMap<EpisodeIndexer, MutableList<ResultEpisode>> =
|
val episodes: MutableMap<EpisodeIndexer, MutableList<ResultEpisode>> =
|
||||||
mutableMapOf()
|
mutableMapOf()
|
||||||
|
@ -1968,6 +1987,7 @@ class ResultViewModel2 : ViewModel() {
|
||||||
}
|
}
|
||||||
episodes
|
episodes
|
||||||
}
|
}
|
||||||
|
|
||||||
is MovieLoadResponse -> {
|
is MovieLoadResponse -> {
|
||||||
singleMap(
|
singleMap(
|
||||||
buildResultEpisode(
|
buildResultEpisode(
|
||||||
|
@ -1989,6 +2009,7 @@ class ResultViewModel2 : ViewModel() {
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
is LiveStreamLoadResponse -> {
|
is LiveStreamLoadResponse -> {
|
||||||
singleMap(
|
singleMap(
|
||||||
buildResultEpisode(
|
buildResultEpisode(
|
||||||
|
@ -2010,6 +2031,7 @@ class ResultViewModel2 : ViewModel() {
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
is TorrentLoadResponse -> {
|
is TorrentLoadResponse -> {
|
||||||
singleMap(
|
singleMap(
|
||||||
buildResultEpisode(
|
buildResultEpisode(
|
||||||
|
@ -2031,6 +2053,7 @@ class ResultViewModel2 : ViewModel() {
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> {
|
else -> {
|
||||||
mapOf()
|
mapOf()
|
||||||
}
|
}
|
||||||
|
@ -2088,7 +2111,7 @@ class ResultViewModel2 : ViewModel() {
|
||||||
}
|
}
|
||||||
|
|
||||||
fun postResume() {
|
fun postResume() {
|
||||||
_resumeWatching.postValue(some(resume()))
|
_resumeWatching.postValue(resume())
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun resume(): ResumeWatchingStatus? {
|
private fun resume(): ResumeWatchingStatus? {
|
||||||
|
@ -2196,6 +2219,7 @@ class ResultViewModel2 : ViewModel() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
START_ACTION_LOAD_EP -> {
|
START_ACTION_LOAD_EP -> {
|
||||||
val all = currentEpisodes.values.flatten()
|
val all = currentEpisodes.values.flatten()
|
||||||
val episode =
|
val episode =
|
||||||
|
@ -2227,7 +2251,7 @@ class ResultViewModel2 : ViewModel() {
|
||||||
) =
|
) =
|
||||||
ioSafe {
|
ioSafe {
|
||||||
_page.postValue(Resource.Loading(url))
|
_page.postValue(Resource.Loading(url))
|
||||||
_episodes.postValue(ResourceSome.Loading())
|
_episodes.postValue(Resource.Loading())
|
||||||
|
|
||||||
preferDubStatus = dubStatus
|
preferDubStatus = dubStatus
|
||||||
currentShowFillers = showFillers
|
currentShowFillers = showFillers
|
||||||
|
@ -2271,6 +2295,7 @@ class ResultViewModel2 : ViewModel() {
|
||||||
is Resource.Failure -> {
|
is Resource.Failure -> {
|
||||||
_page.postValue(data)
|
_page.postValue(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
is Resource.Success -> {
|
is Resource.Success -> {
|
||||||
if (!isActive) return@ioSafe
|
if (!isActive) return@ioSafe
|
||||||
val loadResponse = ioWork {
|
val loadResponse = ioWork {
|
||||||
|
@ -2307,6 +2332,7 @@ class ResultViewModel2 : ViewModel() {
|
||||||
if (!isActive) return@ioSafe
|
if (!isActive) return@ioSafe
|
||||||
handleAutoStart(activity, autostart)
|
handleAutoStart(activity, autostart)
|
||||||
}
|
}
|
||||||
|
|
||||||
is Resource.Loading -> {
|
is Resource.Loading -> {
|
||||||
debugException { "Invalid load result" }
|
debugException { "Invalid load result" }
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,11 @@
|
||||||
package com.lagradost.cloudstream3.ui.result
|
package com.lagradost.cloudstream3.ui.result
|
||||||
|
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.recyclerview.widget.DiffUtil
|
import androidx.recyclerview.widget.DiffUtil
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import com.google.android.material.button.MaterialButton
|
import com.google.android.material.button.MaterialButton
|
||||||
import com.lagradost.cloudstream3.R
|
import com.lagradost.cloudstream3.databinding.ResultSelectionBinding
|
||||||
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTrueTvSettings
|
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTrueTvSettings
|
||||||
|
|
||||||
typealias SelectData = Pair<UiText?, Any>
|
typealias SelectData = Pair<UiText?, Any>
|
||||||
|
@ -17,7 +16,9 @@ class SelectAdaptor(val callback: (Any) -> Unit) : RecyclerView.Adapter<Recycler
|
||||||
|
|
||||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
||||||
return SelectViewHolder(
|
return SelectViewHolder(
|
||||||
LayoutInflater.from(parent.context).inflate(R.layout.result_selection, parent, false),
|
ResultSelectionBinding.inflate(LayoutInflater.from(parent.context), parent, false),
|
||||||
|
|
||||||
|
//LayoutInflater.from(parent.context).inflate(R.layout.result_selection, parent, false),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,10 +74,10 @@ class SelectAdaptor(val callback: (Any) -> Unit) : RecyclerView.Adapter<Recycler
|
||||||
|
|
||||||
private class SelectViewHolder
|
private class SelectViewHolder
|
||||||
constructor(
|
constructor(
|
||||||
itemView: View,
|
binding: ResultSelectionBinding,
|
||||||
) :
|
) :
|
||||||
RecyclerView.ViewHolder(itemView) {
|
RecyclerView.ViewHolder(binding.root) {
|
||||||
private val item: MaterialButton = itemView as MaterialButton
|
private val item: MaterialButton = binding.root
|
||||||
|
|
||||||
fun update(isSelected: Boolean) {
|
fun update(isSelected: Boolean) {
|
||||||
item.isSelected = isSelected
|
item.isSelected = isSelected
|
||||||
|
|
|
@ -8,7 +8,6 @@ import androidx.annotation.DrawableRes
|
||||||
import androidx.annotation.StringRes
|
import androidx.annotation.StringRes
|
||||||
import androidx.core.view.isGone
|
import androidx.core.view.isGone
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import com.lagradost.cloudstream3.mvvm.Some
|
|
||||||
import com.lagradost.cloudstream3.mvvm.logError
|
import com.lagradost.cloudstream3.mvvm.logError
|
||||||
import com.lagradost.cloudstream3.utils.AppUtils.html
|
import com.lagradost.cloudstream3.utils.AppUtils.html
|
||||||
import com.lagradost.cloudstream3.utils.UIHelper.setImage
|
import com.lagradost.cloudstream3.utils.UIHelper.setImage
|
||||||
|
@ -162,11 +161,3 @@ fun TextView?.setTextHtml(text: UiText?) {
|
||||||
this.text = str.html()
|
this.text = str.html()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun TextView?.setTextHtml(text: Some<UiText>?) {
|
|
||||||
setTextHtml(if (text is Some.Success) text.value else null)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun TextView?.setText(text: Some<UiText>?) {
|
|
||||||
setText(if (text is Some.Success) text.value else null)
|
|
||||||
}
|
|
|
@ -78,7 +78,7 @@ class SearchAdapter(
|
||||||
resView: AutofitRecyclerView
|
resView: AutofitRecyclerView
|
||||||
) :
|
) :
|
||||||
RecyclerView.ViewHolder(itemView) {
|
RecyclerView.ViewHolder(itemView) {
|
||||||
val cardView: ImageView = itemView.imageView
|
private val cardView: ImageView = itemView.imageView
|
||||||
|
|
||||||
private val compactView = false//itemView.context.getGridIsCompact()
|
private val compactView = false//itemView.context.getGridIsCompact()
|
||||||
private val coverHeight: Int =
|
private val coverHeight: Int =
|
||||||
|
|
|
@ -33,6 +33,8 @@ import com.lagradost.cloudstream3.AcraApplication.Companion.removeKey
|
||||||
import com.lagradost.cloudstream3.AcraApplication.Companion.removeKeys
|
import com.lagradost.cloudstream3.AcraApplication.Companion.removeKeys
|
||||||
import com.lagradost.cloudstream3.AcraApplication.Companion.setKey
|
import com.lagradost.cloudstream3.AcraApplication.Companion.setKey
|
||||||
import com.lagradost.cloudstream3.MainActivity.Companion.afterPluginsLoadedEvent
|
import com.lagradost.cloudstream3.MainActivity.Companion.afterPluginsLoadedEvent
|
||||||
|
import com.lagradost.cloudstream3.databinding.FragmentSearchBinding
|
||||||
|
import com.lagradost.cloudstream3.databinding.HomeSelectMainpageBinding
|
||||||
import com.lagradost.cloudstream3.mvvm.Resource
|
import com.lagradost.cloudstream3.mvvm.Resource
|
||||||
import com.lagradost.cloudstream3.mvvm.logError
|
import com.lagradost.cloudstream3.mvvm.logError
|
||||||
import com.lagradost.cloudstream3.mvvm.observe
|
import com.lagradost.cloudstream3.mvvm.observe
|
||||||
|
@ -56,8 +58,6 @@ import com.lagradost.cloudstream3.utils.UIHelper.dismissSafe
|
||||||
import com.lagradost.cloudstream3.utils.UIHelper.fixPaddingStatusbar
|
import com.lagradost.cloudstream3.utils.UIHelper.fixPaddingStatusbar
|
||||||
import com.lagradost.cloudstream3.utils.UIHelper.getSpanCount
|
import com.lagradost.cloudstream3.utils.UIHelper.getSpanCount
|
||||||
import com.lagradost.cloudstream3.utils.UIHelper.hideKeyboard
|
import com.lagradost.cloudstream3.utils.UIHelper.hideKeyboard
|
||||||
import kotlinx.android.synthetic.main.fragment_search.*
|
|
||||||
import kotlinx.android.synthetic.main.tvtypes_chips.*
|
|
||||||
import java.util.concurrent.locks.ReentrantLock
|
import java.util.concurrent.locks.ReentrantLock
|
||||||
|
|
||||||
const val SEARCH_PREF_TAGS = "search_pref_tags"
|
const val SEARCH_PREF_TAGS = "search_pref_tags"
|
||||||
|
@ -89,6 +89,7 @@ class SearchFragment : Fragment() {
|
||||||
|
|
||||||
private val searchViewModel: SearchViewModel by activityViewModels()
|
private val searchViewModel: SearchViewModel by activityViewModels()
|
||||||
private var bottomSheetDialog: BottomSheetDialog? = null
|
private var bottomSheetDialog: BottomSheetDialog? = null
|
||||||
|
var binding: FragmentSearchBinding? = null
|
||||||
|
|
||||||
override fun onCreateView(
|
override fun onCreateView(
|
||||||
inflater: LayoutInflater,
|
inflater: LayoutInflater,
|
||||||
|
@ -99,18 +100,20 @@ class SearchFragment : Fragment() {
|
||||||
WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE
|
WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE
|
||||||
)
|
)
|
||||||
bottomSheetDialog?.ownShow()
|
bottomSheetDialog?.ownShow()
|
||||||
return inflater.inflate(
|
|
||||||
if (isTvSettings()) R.layout.fragment_search_tv else R.layout.fragment_search,
|
val layout = if (isTvSettings()) R.layout.fragment_search_tv else R.layout.fragment_search
|
||||||
container,
|
|
||||||
false
|
val root = inflater.inflate(layout, container, false)
|
||||||
)
|
binding = FragmentSearchBinding.bind(root)
|
||||||
|
|
||||||
|
return root
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun fixGrid() {
|
private fun fixGrid() {
|
||||||
activity?.getSpanCount()?.let {
|
activity?.getSpanCount()?.let {
|
||||||
currentSpan = it
|
currentSpan = it
|
||||||
}
|
}
|
||||||
search_autofit_results.spanCount = currentSpan
|
binding?.searchAutofitResults?.spanCount = currentSpan
|
||||||
currentSpan = currentSpan
|
currentSpan = currentSpan
|
||||||
HomeFragment.configEvent.invoke(currentSpan)
|
HomeFragment.configEvent.invoke(currentSpan)
|
||||||
}
|
}
|
||||||
|
@ -123,6 +126,7 @@ class SearchFragment : Fragment() {
|
||||||
override fun onDestroyView() {
|
override fun onDestroyView() {
|
||||||
hideKeyboard()
|
hideKeyboard()
|
||||||
bottomSheetDialog?.ownHide()
|
bottomSheetDialog?.ownHide()
|
||||||
|
binding = null
|
||||||
super.onDestroyView()
|
super.onDestroyView()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -181,7 +185,7 @@ class SearchFragment : Fragment() {
|
||||||
searchViewModel.reloadRepos()
|
searchViewModel.reloadRepos()
|
||||||
context?.filterProviderByPreferredMedia()?.let { validAPIs ->
|
context?.filterProviderByPreferredMedia()?.let { validAPIs ->
|
||||||
bindChips(
|
bindChips(
|
||||||
home_select_group,
|
binding?.tvtypesChipsScroll?.tvtypesChips,
|
||||||
selectedSearchTypes,
|
selectedSearchTypes,
|
||||||
validAPIs.flatMap { api -> api.supportedTypes }.distinct()
|
validAPIs.flatMap { api -> api.supportedTypes }.distinct()
|
||||||
) { list ->
|
) { list ->
|
||||||
|
@ -189,7 +193,7 @@ class SearchFragment : Fragment() {
|
||||||
setKey(SEARCH_PREF_TAGS, selectedSearchTypes)
|
setKey(SEARCH_PREF_TAGS, selectedSearchTypes)
|
||||||
selectedSearchTypes.clear()
|
selectedSearchTypes.clear()
|
||||||
selectedSearchTypes.addAll(list)
|
selectedSearchTypes.addAll(list)
|
||||||
search(main_search?.query?.toString())
|
search(binding?.mainSearch?.query?.toString())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -199,24 +203,27 @@ class SearchFragment : Fragment() {
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
|
||||||
context?.fixPaddingStatusbar(searchRoot)
|
fixPaddingStatusbar(binding?.searchRoot)
|
||||||
fixGrid()
|
fixGrid()
|
||||||
reloadRepos()
|
reloadRepos()
|
||||||
|
|
||||||
val adapter: RecyclerView.Adapter<RecyclerView.ViewHolder>? = activity?.let {
|
binding?.apply {
|
||||||
SearchAdapter(
|
val adapter: RecyclerView.Adapter<RecyclerView.ViewHolder>? =
|
||||||
ArrayList(),
|
SearchAdapter(
|
||||||
search_autofit_results,
|
ArrayList(),
|
||||||
) { callback ->
|
searchAutofitResults,
|
||||||
SearchHelper.handleSearchClickCallback(activity, callback)
|
) { callback ->
|
||||||
}
|
SearchHelper.handleSearchClickCallback(activity, callback)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
searchAutofitResults.adapter = adapter
|
||||||
|
searchLoadingBar.alpha = 0f
|
||||||
}
|
}
|
||||||
|
|
||||||
search_autofit_results.adapter = adapter
|
|
||||||
search_loading_bar.alpha = 0f
|
|
||||||
|
|
||||||
val searchExitIcon =
|
val searchExitIcon =
|
||||||
main_search.findViewById<ImageView>(androidx.appcompat.R.id.search_close_btn)
|
binding?.mainSearch?.findViewById<ImageView>(androidx.appcompat.R.id.search_close_btn)
|
||||||
// val searchMagIcon =
|
// val searchMagIcon =
|
||||||
// main_search.findViewById<ImageView>(androidx.appcompat.R.id.search_mag_icon)
|
// main_search.findViewById<ImageView>(androidx.appcompat.R.id.search_mag_icon)
|
||||||
//searchMagIcon.scaleX = 0.65f
|
//searchMagIcon.scaleX = 0.65f
|
||||||
|
@ -230,7 +237,7 @@ class SearchFragment : Fragment() {
|
||||||
)!!.toMutableSet()
|
)!!.toMutableSet()
|
||||||
}
|
}
|
||||||
|
|
||||||
search_filter.setOnClickListener { searchView ->
|
binding?.searchFilter?.setOnClickListener { searchView ->
|
||||||
searchView?.context?.let { ctx ->
|
searchView?.context?.let { ctx ->
|
||||||
val validAPIs = ctx.filterProviderByPreferredMedia(hasHomePageIsRequired = false)
|
val validAPIs = ctx.filterProviderByPreferredMedia(hasHomePageIsRequired = false)
|
||||||
var currentValidApis = listOf<MainAPI>()
|
var currentValidApis = listOf<MainAPI>()
|
||||||
|
@ -241,7 +248,13 @@ class SearchFragment : Fragment() {
|
||||||
BottomSheetDialog(ctx)
|
BottomSheetDialog(ctx)
|
||||||
|
|
||||||
builder.behavior.state = BottomSheetBehavior.STATE_EXPANDED
|
builder.behavior.state = BottomSheetBehavior.STATE_EXPANDED
|
||||||
builder.setContentView(R.layout.home_select_mainpage)
|
|
||||||
|
val binding: HomeSelectMainpageBinding = HomeSelectMainpageBinding.inflate(
|
||||||
|
builder.layoutInflater,
|
||||||
|
null,
|
||||||
|
false
|
||||||
|
)
|
||||||
|
builder.setContentView(binding.root)
|
||||||
builder.show()
|
builder.show()
|
||||||
builder.let { dialog ->
|
builder.let { dialog ->
|
||||||
val isMultiLang = ctx.getApiProviderLangSettings().let { set ->
|
val isMultiLang = ctx.getApiProviderLangSettings().let { set ->
|
||||||
|
@ -303,7 +316,7 @@ class SearchFragment : Fragment() {
|
||||||
?: mutableListOf(TvType.Movie, TvType.TvSeries)
|
?: mutableListOf(TvType.Movie, TvType.TvSeries)
|
||||||
|
|
||||||
bindChips(
|
bindChips(
|
||||||
dialog.home_select_group,
|
binding.tvtypesChipsScroll.tvtypesChips,
|
||||||
selectedSearchTypes,
|
selectedSearchTypes,
|
||||||
TvType.values().toList()
|
TvType.values().toList()
|
||||||
) { list ->
|
) { list ->
|
||||||
|
@ -343,15 +356,15 @@ class SearchFragment : Fragment() {
|
||||||
?: mutableListOf(TvType.Movie, TvType.TvSeries)
|
?: mutableListOf(TvType.Movie, TvType.TvSeries)
|
||||||
|
|
||||||
if (isTrueTvSettings()) {
|
if (isTrueTvSettings()) {
|
||||||
search_filter.isFocusable = true
|
binding?.searchFilter?.isFocusable = true
|
||||||
search_filter.isFocusableInTouchMode = true
|
binding?.searchFilter?.isFocusableInTouchMode = true
|
||||||
}
|
}
|
||||||
|
|
||||||
main_search.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
|
binding?.mainSearch?.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
|
||||||
override fun onQueryTextSubmit(query: String): Boolean {
|
override fun onQueryTextSubmit(query: String): Boolean {
|
||||||
search(query)
|
search(query)
|
||||||
|
|
||||||
main_search?.let {
|
binding?.mainSearch?.let {
|
||||||
hideKeyboard(it)
|
hideKeyboard(it)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -365,17 +378,17 @@ class SearchFragment : Fragment() {
|
||||||
searchViewModel.clearSearch()
|
searchViewModel.clearSearch()
|
||||||
searchViewModel.updateHistory()
|
searchViewModel.updateHistory()
|
||||||
}
|
}
|
||||||
|
binding?.apply {
|
||||||
search_history_holder?.isVisible = showHistory
|
searchHistoryHolder.isVisible = showHistory
|
||||||
|
searchMasterRecycler.isVisible = !showHistory && isAdvancedSearch
|
||||||
search_master_recycler?.isVisible = !showHistory && isAdvancedSearch
|
searchAutofitResults.isVisible = !showHistory && !isAdvancedSearch
|
||||||
search_autofit_results?.isVisible = !showHistory && !isAdvancedSearch
|
}
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
search_clear_call_history?.setOnClickListener {
|
binding?.searchClearCallHistory?.setOnClickListener {
|
||||||
activity?.let { ctx ->
|
activity?.let { ctx ->
|
||||||
val builder: AlertDialog.Builder = AlertDialog.Builder(ctx)
|
val builder: AlertDialog.Builder = AlertDialog.Builder(ctx)
|
||||||
val dialogClickListener =
|
val dialogClickListener =
|
||||||
|
@ -409,8 +422,8 @@ class SearchFragment : Fragment() {
|
||||||
}
|
}
|
||||||
|
|
||||||
observe(searchViewModel.currentHistory) { list ->
|
observe(searchViewModel.currentHistory) { list ->
|
||||||
search_clear_call_history?.isVisible = list.isNotEmpty()
|
binding?.searchClearCallHistory?.isVisible = list.isNotEmpty()
|
||||||
(search_history_recycler.adapter as? SearchHistoryAdaptor?)?.updateList(list)
|
(binding?.searchHistoryRecycler?.adapter as? SearchHistoryAdaptor?)?.updateList(list)
|
||||||
}
|
}
|
||||||
|
|
||||||
searchViewModel.updateHistory()
|
searchViewModel.updateHistory()
|
||||||
|
@ -420,20 +433,20 @@ class SearchFragment : Fragment() {
|
||||||
is Resource.Success -> {
|
is Resource.Success -> {
|
||||||
it.value.let { data ->
|
it.value.let { data ->
|
||||||
if (data.isNotEmpty()) {
|
if (data.isNotEmpty()) {
|
||||||
(search_autofit_results?.adapter as? SearchAdapter)?.updateList(data)
|
(binding?.searchAutofitResults?.adapter as? SearchAdapter)?.updateList(data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
searchExitIcon.alpha = 1f
|
searchExitIcon?.alpha = 1f
|
||||||
search_loading_bar.alpha = 0f
|
binding?.searchLoadingBar?.alpha = 0f
|
||||||
}
|
}
|
||||||
is Resource.Failure -> {
|
is Resource.Failure -> {
|
||||||
// Toast.makeText(activity, "Server error", Toast.LENGTH_LONG).show()
|
// Toast.makeText(activity, "Server error", Toast.LENGTH_LONG).show()
|
||||||
searchExitIcon.alpha = 1f
|
searchExitIcon?.alpha = 1f
|
||||||
search_loading_bar.alpha = 0f
|
binding?.searchLoadingBar?.alpha = 0f
|
||||||
}
|
}
|
||||||
is Resource.Loading -> {
|
is Resource.Loading -> {
|
||||||
searchExitIcon.alpha = 0f
|
searchExitIcon?.alpha = 0f
|
||||||
search_loading_bar.alpha = 1f
|
binding?.searchLoadingBar?.alpha = 1f
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -443,7 +456,7 @@ class SearchFragment : Fragment() {
|
||||||
try {
|
try {
|
||||||
// https://stackoverflow.com/questions/6866238/concurrent-modification-exception-adding-to-an-arraylist
|
// https://stackoverflow.com/questions/6866238/concurrent-modification-exception-adding-to-an-arraylist
|
||||||
listLock.lock()
|
listLock.lock()
|
||||||
(search_master_recycler?.adapter as ParentItemAdapter?)?.apply {
|
(binding?.searchMasterRecycler?.adapter as ParentItemAdapter?)?.apply {
|
||||||
val newItems = list.map { ongoing ->
|
val newItems = list.map { ongoing ->
|
||||||
val dataList =
|
val dataList =
|
||||||
if (ongoing.data is Resource.Success) ongoing.data.value else ArrayList()
|
if (ongoing.data is Resource.Success) ongoing.data.value else ArrayList()
|
||||||
|
@ -490,8 +503,8 @@ class SearchFragment : Fragment() {
|
||||||
SEARCH_HISTORY_OPEN -> {
|
SEARCH_HISTORY_OPEN -> {
|
||||||
searchViewModel.clearSearch()
|
searchViewModel.clearSearch()
|
||||||
if (searchItem.type.isNotEmpty())
|
if (searchItem.type.isNotEmpty())
|
||||||
updateChips(home_select_group, searchItem.type.toMutableList())
|
updateChips(binding?.tvtypesChipsScroll?.tvtypesChips, searchItem.type.toMutableList())
|
||||||
main_search?.setQuery(searchItem.searchText, true)
|
binding?.mainSearch?.setQuery(searchItem.searchText, true)
|
||||||
}
|
}
|
||||||
SEARCH_HISTORY_REMOVE -> {
|
SEARCH_HISTORY_REMOVE -> {
|
||||||
removeKey(SEARCH_HISTORY_KEY, searchItem.key)
|
removeKey(SEARCH_HISTORY_KEY, searchItem.key)
|
||||||
|
@ -503,20 +516,23 @@ class SearchFragment : Fragment() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
search_history_recycler?.adapter = historyAdapter
|
binding?.apply {
|
||||||
search_history_recycler?.layoutManager = GridLayoutManager(context, 1)
|
searchHistoryRecycler.adapter = historyAdapter
|
||||||
|
searchHistoryRecycler.layoutManager = GridLayoutManager(context, 1)
|
||||||
|
|
||||||
search_master_recycler?.adapter = masterAdapter
|
searchMasterRecycler.adapter = masterAdapter
|
||||||
search_master_recycler?.layoutManager = GridLayoutManager(context, 1)
|
searchMasterRecycler.layoutManager = GridLayoutManager(context, 1)
|
||||||
|
|
||||||
// Automatically search the specified query, this allows the app search to launch from intent
|
// Automatically search the specified query, this allows the app search to launch from intent
|
||||||
arguments?.getString(SEARCH_QUERY)?.let { query ->
|
arguments?.getString(SEARCH_QUERY)?.let { query ->
|
||||||
if (query.isBlank()) return@let
|
if (query.isBlank()) return@let
|
||||||
main_search?.setQuery(query, true)
|
mainSearch.setQuery(query, true)
|
||||||
// Clear the query as to not make it request the same query every time the page is opened
|
// Clear the query as to not make it request the same query every time the page is opened
|
||||||
arguments?.putString(SEARCH_QUERY, null)
|
arguments?.putString(SEARCH_QUERY, null)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// SubtitlesFragment.push(activity)
|
// SubtitlesFragment.push(activity)
|
||||||
//searchViewModel.search("iron man")
|
//searchViewModel.search("iron man")
|
||||||
//(activity as AppCompatActivity).loadResult("https://shiro.is/overlord-dubbed", "overlord-dubbed", "Shiro")
|
//(activity as AppCompatActivity).loadResult("https://shiro.is/overlord-dubbed", "overlord-dubbed", "Shiro")
|
||||||
|
|
|
@ -10,7 +10,8 @@ import androidx.recyclerview.widget.RecyclerView
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty
|
import com.fasterxml.jackson.annotation.JsonProperty
|
||||||
import com.lagradost.cloudstream3.R
|
import com.lagradost.cloudstream3.R
|
||||||
import com.lagradost.cloudstream3.TvType
|
import com.lagradost.cloudstream3.TvType
|
||||||
import kotlinx.android.synthetic.main.search_history_item.view.*
|
import com.lagradost.cloudstream3.databinding.AccountSingleBinding
|
||||||
|
import com.lagradost.cloudstream3.databinding.SearchHistoryItemBinding
|
||||||
|
|
||||||
data class SearchHistoryItem(
|
data class SearchHistoryItem(
|
||||||
@JsonProperty("searchedAt") val searchedAt: Long,
|
@JsonProperty("searchedAt") val searchedAt: Long,
|
||||||
|
@ -34,8 +35,7 @@ class SearchHistoryAdaptor(
|
||||||
|
|
||||||
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)
|
SearchHistoryItemBinding.inflate(LayoutInflater.from(parent.context), parent, false),
|
||||||
.inflate(R.layout.search_history_item, parent, false),
|
|
||||||
clickCallback,
|
clickCallback,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -65,22 +65,24 @@ class SearchHistoryAdaptor(
|
||||||
|
|
||||||
class CardViewHolder
|
class CardViewHolder
|
||||||
constructor(
|
constructor(
|
||||||
itemView: View,
|
val binding: SearchHistoryItemBinding,
|
||||||
private val clickCallback: (SearchHistoryCallback) -> Unit,
|
private val clickCallback: (SearchHistoryCallback) -> Unit,
|
||||||
) :
|
) :
|
||||||
RecyclerView.ViewHolder(itemView) {
|
RecyclerView.ViewHolder(binding.root) {
|
||||||
private val removeButton: ImageView = itemView.home_history_remove
|
// private val removeButton: ImageView = itemView.home_history_remove
|
||||||
private val openButton: View = itemView.home_history_tab
|
// private val openButton: View = itemView.home_history_tab
|
||||||
private val title: TextView = itemView.home_history_title
|
// private val title: TextView = itemView.home_history_title
|
||||||
|
|
||||||
fun bind(card: SearchHistoryItem) {
|
fun bind(card: SearchHistoryItem) {
|
||||||
title.text = card.searchText
|
binding.apply {
|
||||||
|
homeHistoryTitle.text = card.searchText
|
||||||
|
|
||||||
removeButton.setOnClickListener {
|
homeHistoryRemove.setOnClickListener {
|
||||||
clickCallback.invoke(SearchHistoryCallback(card, SEARCH_HISTORY_REMOVE))
|
clickCallback.invoke(SearchHistoryCallback(card, SEARCH_HISTORY_REMOVE))
|
||||||
}
|
}
|
||||||
openButton.setOnClickListener {
|
homeHistoryTab.setOnClickListener {
|
||||||
clickCallback.invoke(SearchHistoryCallback(card, SEARCH_HISTORY_OPEN))
|
clickCallback.invoke(SearchHistoryCallback(card, SEARCH_HISTORY_OPEN))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package com.lagradost.cloudstream3.ui.search
|
package com.lagradost.cloudstream3.ui.search
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.graphics.drawable.Drawable
|
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.widget.ImageView
|
import android.widget.ImageView
|
||||||
import android.widget.ProgressBar
|
import android.widget.ProgressBar
|
||||||
|
@ -10,14 +9,29 @@ import androidx.cardview.widget.CardView
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import androidx.palette.graphics.Palette
|
import androidx.palette.graphics.Palette
|
||||||
import androidx.preference.PreferenceManager
|
import androidx.preference.PreferenceManager
|
||||||
import com.lagradost.cloudstream3.*
|
import com.lagradost.cloudstream3.AnimeSearchResponse
|
||||||
|
import com.lagradost.cloudstream3.DubStatus
|
||||||
|
import com.lagradost.cloudstream3.LiveSearchResponse
|
||||||
|
import com.lagradost.cloudstream3.R
|
||||||
|
import com.lagradost.cloudstream3.SearchQuality
|
||||||
|
import com.lagradost.cloudstream3.SearchResponse
|
||||||
|
import com.lagradost.cloudstream3.isMovieType
|
||||||
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTrueTvSettings
|
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTrueTvSettings
|
||||||
import com.lagradost.cloudstream3.utils.AppUtils.getNameFull
|
import com.lagradost.cloudstream3.utils.AppUtils.getNameFull
|
||||||
import com.lagradost.cloudstream3.utils.DataStoreHelper
|
import com.lagradost.cloudstream3.utils.DataStoreHelper
|
||||||
import com.lagradost.cloudstream3.utils.DataStoreHelper.fixVisual
|
import com.lagradost.cloudstream3.utils.DataStoreHelper.fixVisual
|
||||||
import com.lagradost.cloudstream3.utils.SubtitleHelper
|
import com.lagradost.cloudstream3.utils.SubtitleHelper
|
||||||
import com.lagradost.cloudstream3.utils.UIHelper.setImage
|
import com.lagradost.cloudstream3.utils.UIHelper.setImage
|
||||||
import kotlinx.android.synthetic.main.home_result_grid.view.*
|
import kotlinx.android.synthetic.main.home_result_grid.view.background_card
|
||||||
|
import kotlinx.android.synthetic.main.home_result_grid.view.imageText
|
||||||
|
import kotlinx.android.synthetic.main.home_result_grid.view.imageView
|
||||||
|
import kotlinx.android.synthetic.main.home_result_grid.view.search_item_download_play
|
||||||
|
import kotlinx.android.synthetic.main.home_result_grid.view.text_flag
|
||||||
|
import kotlinx.android.synthetic.main.home_result_grid.view.text_is_dub
|
||||||
|
import kotlinx.android.synthetic.main.home_result_grid.view.text_is_sub
|
||||||
|
import kotlinx.android.synthetic.main.home_result_grid.view.text_quality
|
||||||
|
import kotlinx.android.synthetic.main.home_result_grid.view.title_shadow
|
||||||
|
import kotlinx.android.synthetic.main.home_result_grid.view.watchProgress
|
||||||
|
|
||||||
object SearchResultBuilder {
|
object SearchResultBuilder {
|
||||||
private val showCache: MutableMap<String, Boolean> = mutableMapOf()
|
private val showCache: MutableMap<String, Boolean> = mutableMapOf()
|
||||||
|
|
|
@ -3,11 +3,10 @@ package com.lagradost.cloudstream3.ui.settings
|
||||||
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 android.widget.ImageView
|
|
||||||
import android.widget.TextView
|
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import com.lagradost.cloudstream3.R
|
import com.lagradost.cloudstream3.R
|
||||||
|
import com.lagradost.cloudstream3.databinding.AccountSingleBinding
|
||||||
import com.lagradost.cloudstream3.syncproviders.AuthAPI
|
import com.lagradost.cloudstream3.syncproviders.AuthAPI
|
||||||
import com.lagradost.cloudstream3.utils.UIHelper.setImage
|
import com.lagradost.cloudstream3.utils.UIHelper.setImage
|
||||||
|
|
||||||
|
@ -15,14 +14,15 @@ class AccountClickCallback(val action: Int, val view: View, val card: AuthAPI.Lo
|
||||||
|
|
||||||
class AccountAdapter(
|
class AccountAdapter(
|
||||||
val cardList: List<AuthAPI.LoginInfo>,
|
val cardList: List<AuthAPI.LoginInfo>,
|
||||||
val layout: Int = R.layout.account_single,
|
|
||||||
private val clickCallback: (AccountClickCallback) -> Unit
|
private val clickCallback: (AccountClickCallback) -> Unit
|
||||||
) :
|
) :
|
||||||
RecyclerView.Adapter<RecyclerView.ViewHolder>() {
|
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(layout, parent, false), clickCallback
|
AccountSingleBinding.inflate(LayoutInflater.from(parent.context), parent, false), //LayoutInflater.from(parent.context).inflate(layout, parent, false),
|
||||||
|
|
||||||
|
clickCallback
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,18 +43,18 @@ class AccountAdapter(
|
||||||
}
|
}
|
||||||
|
|
||||||
class CardViewHolder
|
class CardViewHolder
|
||||||
constructor(itemView: View, private val clickCallback: (AccountClickCallback) -> Unit) :
|
constructor(val binding: AccountSingleBinding, private val clickCallback: (AccountClickCallback) -> Unit) :
|
||||||
RecyclerView.ViewHolder(itemView) {
|
RecyclerView.ViewHolder(binding.root) {
|
||||||
private val pfp: ImageView = itemView.findViewById(R.id.account_profile_picture)!!
|
// private val pfp: ImageView = itemView.findViewById(R.id.account_profile_picture)!!
|
||||||
private val accountName: TextView = itemView.findViewById(R.id.account_name)!!
|
// private val accountName: TextView = itemView.findViewById(R.id.account_name)!!
|
||||||
|
|
||||||
fun bind(card: AuthAPI.LoginInfo) {
|
fun bind(card: AuthAPI.LoginInfo) {
|
||||||
// just in case name is null account index will show, should never happened
|
// just in case name is null account index will show, should never happened
|
||||||
accountName.text = card.name ?: "%s %d".format(
|
binding.accountName.text = card.name ?: "%s %d".format(
|
||||||
accountName.context.getString(R.string.account),
|
binding.accountName.context.getString(R.string.account),
|
||||||
card.accountIndex
|
card.accountIndex
|
||||||
)
|
)
|
||||||
pfp.isVisible = pfp.setImage(card.profilePicture)
|
binding.accountProfilePicture.isVisible = binding.accountProfilePicture.setImage(card.profilePicture)
|
||||||
|
|
||||||
itemView.setOnClickListener {
|
itemView.setOnClickListener {
|
||||||
clickCallback.invoke(AccountClickCallback(0, itemView, card))
|
clickCallback.invoke(AccountClickCallback(0, itemView, card))
|
||||||
|
|
|
@ -96,7 +96,7 @@ class SettingsAccount : PreferenceFragmentCompat() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
api.accountIndex = ogIndex
|
api.accountIndex = ogIndex
|
||||||
val adapter = AccountAdapter(items, R.layout.account_single) {
|
val adapter = AccountAdapter(items) {
|
||||||
dialog?.dismissSafe(activity)
|
dialog?.dismissSafe(activity)
|
||||||
api.changeAccount(it.card.accountIndex)
|
api.changeAccount(it.card.accountIndex)
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,7 +62,7 @@ class SettingsFragment : Fragment() {
|
||||||
activity?.onBackPressed()
|
activity?.onBackPressed()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
context.fixPaddingStatusbar(settings_toolbar)
|
fixPaddingStatusbar(settings_toolbar)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Fragment?.setUpToolbar(@StringRes title: Int) {
|
fun Fragment?.setUpToolbar(@StringRes title: Int) {
|
||||||
|
@ -74,7 +74,7 @@ class SettingsFragment : Fragment() {
|
||||||
activity?.onBackPressed()
|
activity?.onBackPressed()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
context.fixPaddingStatusbar(settings_toolbar)
|
fixPaddingStatusbar(settings_toolbar)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getFolderSize(dir: File): Long {
|
fun getFolderSize(dir: File): Long {
|
||||||
|
|
|
@ -18,8 +18,8 @@ import androidx.navigation.fragment.findNavController
|
||||||
import com.lagradost.cloudstream3.CommonActivity.showToast
|
import com.lagradost.cloudstream3.CommonActivity.showToast
|
||||||
import com.lagradost.cloudstream3.MainActivity.Companion.afterRepositoryLoadedEvent
|
import com.lagradost.cloudstream3.MainActivity.Companion.afterRepositoryLoadedEvent
|
||||||
import com.lagradost.cloudstream3.R
|
import com.lagradost.cloudstream3.R
|
||||||
import com.lagradost.cloudstream3.mvvm.Some
|
|
||||||
import com.lagradost.cloudstream3.mvvm.observe
|
import com.lagradost.cloudstream3.mvvm.observe
|
||||||
|
import com.lagradost.cloudstream3.mvvm.observeNullable
|
||||||
import com.lagradost.cloudstream3.plugins.RepositoryManager
|
import com.lagradost.cloudstream3.plugins.RepositoryManager
|
||||||
import com.lagradost.cloudstream3.ui.result.setText
|
import com.lagradost.cloudstream3.ui.result.setText
|
||||||
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTrueTvSettings
|
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTrueTvSettings
|
||||||
|
@ -97,6 +97,7 @@ class ExtensionsFragment : Fragment() {
|
||||||
extensionViewModel.loadRepositories()
|
extensionViewModel.loadRepositories()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DialogInterface.BUTTON_NEGATIVE -> {}
|
DialogInterface.BUTTON_NEGATIVE -> {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -138,29 +139,26 @@ class ExtensionsFragment : Fragment() {
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
observe(extensionViewModel.pluginStats) {
|
observeNullable(extensionViewModel.pluginStats) { value ->
|
||||||
when (it) {
|
if (value == null) {
|
||||||
is Some.Success -> {
|
plugin_storage_appbar?.isVisible = false
|
||||||
val value = it.value
|
|
||||||
|
|
||||||
plugin_storage_appbar?.isVisible = true
|
return@observeNullable
|
||||||
if (value.total == 0) {
|
|
||||||
plugin_download?.setLayoutWidth(1)
|
|
||||||
plugin_disabled?.setLayoutWidth(0)
|
|
||||||
plugin_not_downloaded?.setLayoutWidth(0)
|
|
||||||
} else {
|
|
||||||
plugin_download?.setLayoutWidth(value.downloaded)
|
|
||||||
plugin_disabled?.setLayoutWidth(value.disabled)
|
|
||||||
plugin_not_downloaded?.setLayoutWidth(value.notDownloaded)
|
|
||||||
}
|
|
||||||
plugin_not_downloaded_txt.setText(value.notDownloadedText)
|
|
||||||
plugin_disabled_txt.setText(value.disabledText)
|
|
||||||
plugin_download_txt.setText(value.downloadedText)
|
|
||||||
}
|
|
||||||
is Some.None -> {
|
|
||||||
plugin_storage_appbar?.isVisible = false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
plugin_storage_appbar?.isVisible = true
|
||||||
|
if (value.total == 0) {
|
||||||
|
plugin_download?.setLayoutWidth(1)
|
||||||
|
plugin_disabled?.setLayoutWidth(0)
|
||||||
|
plugin_not_downloaded?.setLayoutWidth(0)
|
||||||
|
} else {
|
||||||
|
plugin_download?.setLayoutWidth(value.downloaded)
|
||||||
|
plugin_disabled?.setLayoutWidth(value.disabled)
|
||||||
|
plugin_not_downloaded?.setLayoutWidth(value.notDownloaded)
|
||||||
|
}
|
||||||
|
plugin_not_downloaded_txt.setText(value.notDownloadedText)
|
||||||
|
plugin_disabled_txt.setText(value.disabledText)
|
||||||
|
plugin_download_txt.setText(value.downloadedText)
|
||||||
}
|
}
|
||||||
|
|
||||||
plugin_storage_appbar?.setOnClickListener {
|
plugin_storage_appbar?.setOnClickListener {
|
||||||
|
|
|
@ -7,7 +7,6 @@ import com.fasterxml.jackson.annotation.JsonProperty
|
||||||
import com.lagradost.cloudstream3.AcraApplication.Companion.getKey
|
import com.lagradost.cloudstream3.AcraApplication.Companion.getKey
|
||||||
import com.lagradost.cloudstream3.R
|
import com.lagradost.cloudstream3.R
|
||||||
import com.lagradost.cloudstream3.amap
|
import com.lagradost.cloudstream3.amap
|
||||||
import com.lagradost.cloudstream3.mvvm.Some
|
|
||||||
import com.lagradost.cloudstream3.mvvm.debugAssert
|
import com.lagradost.cloudstream3.mvvm.debugAssert
|
||||||
import com.lagradost.cloudstream3.plugins.PluginManager
|
import com.lagradost.cloudstream3.plugins.PluginManager
|
||||||
import com.lagradost.cloudstream3.plugins.PluginManager.getPluginsOnline
|
import com.lagradost.cloudstream3.plugins.PluginManager.getPluginsOnline
|
||||||
|
@ -40,8 +39,8 @@ class ExtensionsViewModel : ViewModel() {
|
||||||
private val _repositories = MutableLiveData<Array<RepositoryData>>()
|
private val _repositories = MutableLiveData<Array<RepositoryData>>()
|
||||||
val repositories: LiveData<Array<RepositoryData>> = _repositories
|
val repositories: LiveData<Array<RepositoryData>> = _repositories
|
||||||
|
|
||||||
private val _pluginStats: MutableLiveData<Some<PluginStats>> = MutableLiveData(Some.None)
|
private val _pluginStats: MutableLiveData<PluginStats?> = MutableLiveData(null)
|
||||||
val pluginStats: LiveData<Some<PluginStats>> = _pluginStats
|
val pluginStats: LiveData<PluginStats?> = _pluginStats
|
||||||
|
|
||||||
//TODO CACHE GET REQUESTS
|
//TODO CACHE GET REQUESTS
|
||||||
// DO not use viewModelScope.launchSafe, it will ANR on slow internet
|
// DO not use viewModelScope.launchSafe, it will ANR on slow internet
|
||||||
|
@ -78,7 +77,7 @@ class ExtensionsViewModel : ViewModel() {
|
||||||
debugAssert({ stats.downloaded + stats.notDownloaded + stats.disabled != stats.total }) {
|
debugAssert({ stats.downloaded + stats.notDownloaded + stats.disabled != stats.total }) {
|
||||||
"downloaded(${stats.downloaded}) + notDownloaded(${stats.notDownloaded}) + disabled(${stats.disabled}) != total(${stats.total})"
|
"downloaded(${stats.downloaded}) + notDownloaded(${stats.notDownloaded}) + disabled(${stats.disabled}) != total(${stats.total})"
|
||||||
}
|
}
|
||||||
_pluginStats.postValue(Some.Success(stats))
|
_pluginStats.postValue(stats)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun repos() = (getKey<Array<RepositoryData>>(REPOSITORIES_KEY)
|
private fun repos() = (getKey<Array<RepositoryData>>(REPOSITORIES_KEY)
|
||||||
|
|
|
@ -12,6 +12,7 @@ import com.lagradost.cloudstream3.APIHolder.getApiProviderLangSettings
|
||||||
import com.lagradost.cloudstream3.AllLanguagesName
|
import com.lagradost.cloudstream3.AllLanguagesName
|
||||||
import com.lagradost.cloudstream3.R
|
import com.lagradost.cloudstream3.R
|
||||||
import com.lagradost.cloudstream3.TvType
|
import com.lagradost.cloudstream3.TvType
|
||||||
|
import com.lagradost.cloudstream3.databinding.FragmentPluginsBinding
|
||||||
import com.lagradost.cloudstream3.mvvm.observe
|
import com.lagradost.cloudstream3.mvvm.observe
|
||||||
import com.lagradost.cloudstream3.ui.home.HomeFragment.Companion.bindChips
|
import com.lagradost.cloudstream3.ui.home.HomeFragment.Companion.bindChips
|
||||||
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTvSettings
|
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTvSettings
|
||||||
|
@ -20,9 +21,6 @@ import com.lagradost.cloudstream3.ui.settings.appLanguages
|
||||||
import com.lagradost.cloudstream3.utils.SingleSelectionHelper.showMultiDialog
|
import com.lagradost.cloudstream3.utils.SingleSelectionHelper.showMultiDialog
|
||||||
import com.lagradost.cloudstream3.utils.SubtitleHelper
|
import com.lagradost.cloudstream3.utils.SubtitleHelper
|
||||||
import com.lagradost.cloudstream3.utils.UIHelper.toPx
|
import com.lagradost.cloudstream3.utils.UIHelper.toPx
|
||||||
import kotlinx.android.synthetic.main.fragment_plugins.*
|
|
||||||
import kotlinx.android.synthetic.main.tvtypes_chips.*
|
|
||||||
import kotlinx.android.synthetic.main.tvtypes_chips_scroll.*
|
|
||||||
|
|
||||||
const val PLUGINS_BUNDLE_NAME = "name"
|
const val PLUGINS_BUNDLE_NAME = "name"
|
||||||
const val PLUGINS_BUNDLE_URL = "url"
|
const val PLUGINS_BUNDLE_URL = "url"
|
||||||
|
@ -33,11 +31,19 @@ class PluginsFragment : Fragment() {
|
||||||
inflater: LayoutInflater,
|
inflater: LayoutInflater,
|
||||||
container: ViewGroup?,
|
container: ViewGroup?,
|
||||||
savedInstanceState: Bundle?,
|
savedInstanceState: Bundle?,
|
||||||
): View? {
|
): View {
|
||||||
return inflater.inflate(R.layout.fragment_plugins, container, false)
|
val localBinding = FragmentPluginsBinding.inflate(inflater,container,false)
|
||||||
|
binding = localBinding
|
||||||
|
return localBinding.root//inflater.inflate(R.layout.fragment_plugins, container, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDestroyView() {
|
||||||
|
binding = null
|
||||||
|
super.onDestroyView()
|
||||||
}
|
}
|
||||||
|
|
||||||
private val pluginViewModel: PluginsViewModel by activityViewModels()
|
private val pluginViewModel: PluginsViewModel by activityViewModels()
|
||||||
|
var binding: FragmentPluginsBinding? = null
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
@ -66,8 +72,8 @@ class PluginsFragment : Fragment() {
|
||||||
}
|
}
|
||||||
|
|
||||||
setUpToolbar(name)
|
setUpToolbar(name)
|
||||||
|
binding?.settingsToolbar?.apply {
|
||||||
settings_toolbar?.setOnMenuItemClickListener { menuItem ->
|
setOnMenuItemClickListener { menuItem ->
|
||||||
when (menuItem?.itemId) {
|
when (menuItem?.itemId) {
|
||||||
R.id.download_all -> {
|
R.id.download_all -> {
|
||||||
PluginsViewModel.downloadAll(activity, url, pluginViewModel)
|
PluginsViewModel.downloadAll(activity, url, pluginViewModel)
|
||||||
|
@ -99,67 +105,69 @@ class PluginsFragment : Fragment() {
|
||||||
}
|
}
|
||||||
|
|
||||||
val searchView =
|
val searchView =
|
||||||
settings_toolbar?.menu?.findItem(R.id.search_button)?.actionView as? SearchView
|
menu?.findItem(R.id.search_button)?.actionView as? SearchView
|
||||||
|
|
||||||
// Don't go back if active query
|
// Don't go back if active query
|
||||||
settings_toolbar?.setNavigationOnClickListener {
|
setNavigationOnClickListener {
|
||||||
if (searchView?.isIconified == false) {
|
if (searchView?.isIconified == false) {
|
||||||
searchView.isIconified = true
|
searchView.isIconified = true
|
||||||
} else {
|
} else {
|
||||||
activity?.onBackPressed()
|
activity?.onBackPressed()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
searchView?.setOnQueryTextFocusChangeListener { _, hasFocus ->
|
||||||
|
if (!hasFocus) pluginViewModel.search(null)
|
||||||
|
}
|
||||||
|
|
||||||
|
searchView?.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
|
||||||
|
override fun onQueryTextSubmit(query: String?): Boolean {
|
||||||
|
pluginViewModel.search(query)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onQueryTextChange(newText: String?): Boolean {
|
||||||
|
pluginViewModel.search(newText)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
// searchView?.onActionViewCollapsed = {
|
// searchView?.onActionViewCollapsed = {
|
||||||
// pluginViewModel.search(null)
|
// pluginViewModel.search(null)
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// Because onActionViewCollapsed doesn't wanna work we need this workaround :(
|
// Because onActionViewCollapsed doesn't wanna work we need this workaround :(
|
||||||
searchView?.setOnQueryTextFocusChangeListener { _, hasFocus ->
|
|
||||||
if (!hasFocus) pluginViewModel.search(null)
|
|
||||||
}
|
|
||||||
|
|
||||||
searchView?.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
|
|
||||||
override fun onQueryTextSubmit(query: String?): Boolean {
|
|
||||||
pluginViewModel.search(query)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onQueryTextChange(newText: String?): Boolean {
|
|
||||||
pluginViewModel.search(newText)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
plugin_recycler_view?.adapter =
|
|
||||||
|
binding?.pluginRecyclerView?.adapter =
|
||||||
PluginAdapter {
|
PluginAdapter {
|
||||||
pluginViewModel.handlePluginAction(activity, url, it, isLocal)
|
pluginViewModel.handlePluginAction(activity, url, it, isLocal)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isTvSettings()) {
|
if (isTvSettings()) {
|
||||||
// Scrolling down does not reveal the whole RecyclerView on TV, add to bypass that.
|
// Scrolling down does not reveal the whole RecyclerView on TV, add to bypass that.
|
||||||
plugin_recycler_view?.setPadding(0, 0, 0, 200.toPx)
|
binding?.pluginRecyclerView?.setPadding(0, 0, 0, 200.toPx)
|
||||||
}
|
}
|
||||||
|
|
||||||
observe(pluginViewModel.filteredPlugins) { (scrollToTop, list) ->
|
observe(pluginViewModel.filteredPlugins) { (scrollToTop, list) ->
|
||||||
(plugin_recycler_view?.adapter as? PluginAdapter)?.updateList(list)
|
(binding?.pluginRecyclerView?.adapter as? PluginAdapter)?.updateList(list)
|
||||||
|
|
||||||
if (scrollToTop)
|
if (scrollToTop)
|
||||||
plugin_recycler_view?.scrollToPosition(0)
|
binding?.pluginRecyclerView?.scrollToPosition(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isLocal) {
|
if (isLocal) {
|
||||||
// No download button and no categories on local
|
// No download button and no categories on local
|
||||||
settings_toolbar?.menu?.findItem(R.id.download_all)?.isVisible = false
|
binding?.settingsToolbar?.menu?.findItem(R.id.download_all)?.isVisible = false
|
||||||
settings_toolbar?.menu?.findItem(R.id.lang_filter)?.isVisible = false
|
binding?.settingsToolbar?.menu?.findItem(R.id.lang_filter)?.isVisible = false
|
||||||
pluginViewModel.updatePluginListLocal()
|
pluginViewModel.updatePluginListLocal()
|
||||||
tv_types_scroll_view?.isVisible = false
|
|
||||||
|
binding?.tvtypesChipsScroll?.root?.isVisible = false
|
||||||
} else {
|
} else {
|
||||||
pluginViewModel.updatePluginList(context, url)
|
pluginViewModel.updatePluginList(context, url)
|
||||||
tv_types_scroll_view?.isVisible = true
|
binding?.tvtypesChipsScroll?.root?.isVisible = true
|
||||||
|
|
||||||
bindChips(home_select_group, emptyList(), TvType.values().toList()) { list ->
|
bindChips(binding?.tvtypesChipsScroll?.tvtypesChips, emptyList(), TvType.values().toList()) { list ->
|
||||||
pluginViewModel.tvTypes.clear()
|
pluginViewModel.tvTypes.clear()
|
||||||
pluginViewModel.tvTypes.addAll(list.map { it.name })
|
pluginViewModel.tvTypes.addAll(list.map { it.name })
|
||||||
pluginViewModel.updateFilteredPlugins()
|
pluginViewModel.updateFilteredPlugins()
|
||||||
|
|
|
@ -8,21 +8,16 @@ import androidx.core.view.isVisible
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.navigation.fragment.findNavController
|
import androidx.navigation.fragment.findNavController
|
||||||
import com.lagradost.cloudstream3.APIHolder.apis
|
import com.lagradost.cloudstream3.APIHolder.apis
|
||||||
import com.lagradost.cloudstream3.APIHolder.getApiProviderLangSettings
|
|
||||||
import com.lagradost.cloudstream3.AllLanguagesName
|
|
||||||
import com.lagradost.cloudstream3.MainActivity.Companion.afterRepositoryLoadedEvent
|
import com.lagradost.cloudstream3.MainActivity.Companion.afterRepositoryLoadedEvent
|
||||||
import com.lagradost.cloudstream3.R
|
import com.lagradost.cloudstream3.R
|
||||||
|
import com.lagradost.cloudstream3.databinding.FragmentSetupExtensionsBinding
|
||||||
|
import com.lagradost.cloudstream3.mvvm.normalSafeApiCall
|
||||||
import com.lagradost.cloudstream3.plugins.RepositoryManager
|
import com.lagradost.cloudstream3.plugins.RepositoryManager
|
||||||
import com.lagradost.cloudstream3.plugins.RepositoryManager.PREBUILT_REPOSITORIES
|
import com.lagradost.cloudstream3.plugins.RepositoryManager.PREBUILT_REPOSITORIES
|
||||||
import com.lagradost.cloudstream3.ui.settings.extensions.PluginsViewModel
|
import com.lagradost.cloudstream3.ui.settings.extensions.PluginsViewModel
|
||||||
import com.lagradost.cloudstream3.ui.settings.extensions.RepoAdapter
|
import com.lagradost.cloudstream3.ui.settings.extensions.RepoAdapter
|
||||||
import com.lagradost.cloudstream3.utils.Coroutines.main
|
import com.lagradost.cloudstream3.utils.Coroutines.main
|
||||||
import com.lagradost.cloudstream3.utils.UIHelper.fixPaddingStatusbar
|
import com.lagradost.cloudstream3.utils.UIHelper.fixPaddingStatusbar
|
||||||
import kotlinx.android.synthetic.main.fragment_extensions.blank_repo_screen
|
|
||||||
import kotlinx.android.synthetic.main.fragment_extensions.repo_recycler_view
|
|
||||||
import kotlinx.android.synthetic.main.fragment_setup_media.next_btt
|
|
||||||
import kotlinx.android.synthetic.main.fragment_setup_media.prev_btt
|
|
||||||
import kotlinx.android.synthetic.main.fragment_setup_media.setup_root
|
|
||||||
|
|
||||||
|
|
||||||
class SetupFragmentExtensions : Fragment() {
|
class SetupFragmentExtensions : Fragment() {
|
||||||
|
@ -39,13 +34,24 @@ class SetupFragmentExtensions : Fragment() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var binding: FragmentSetupExtensionsBinding? = null
|
||||||
|
|
||||||
|
override fun onDestroyView() {
|
||||||
|
binding = null
|
||||||
|
super.onDestroyView()
|
||||||
|
}
|
||||||
|
|
||||||
override fun onCreateView(
|
override fun onCreateView(
|
||||||
inflater: LayoutInflater, container: ViewGroup?,
|
inflater: LayoutInflater, container: ViewGroup?,
|
||||||
savedInstanceState: Bundle?
|
savedInstanceState: Bundle?
|
||||||
): View? {
|
): View {
|
||||||
return inflater.inflate(R.layout.fragment_setup_extensions, container, false)
|
val localBinding = FragmentSetupExtensionsBinding.inflate(inflater, container, false)
|
||||||
|
binding = localBinding
|
||||||
|
return localBinding.root
|
||||||
|
//return inflater.inflate(R.layout.fragment_setup_extensions, container, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
super.onResume()
|
super.onResume()
|
||||||
afterRepositoryLoadedEvent += ::setRepositories
|
afterRepositoryLoadedEvent += ::setRepositories
|
||||||
|
@ -60,12 +66,12 @@ class SetupFragmentExtensions : Fragment() {
|
||||||
main {
|
main {
|
||||||
val repositories = RepositoryManager.getRepositories() + PREBUILT_REPOSITORIES
|
val repositories = RepositoryManager.getRepositories() + PREBUILT_REPOSITORIES
|
||||||
val hasRepos = repositories.isNotEmpty()
|
val hasRepos = repositories.isNotEmpty()
|
||||||
repo_recycler_view?.isVisible = hasRepos
|
binding?.repoRecyclerView?.isVisible = hasRepos
|
||||||
blank_repo_screen?.isVisible = !hasRepos
|
binding?.blankRepoScreen?.isVisible = !hasRepos
|
||||||
// view_public_repositories_button?.isVisible = hasRepos
|
// view_public_repositories_button?.isVisible = hasRepos
|
||||||
|
|
||||||
if (hasRepos) {
|
if (hasRepos) {
|
||||||
repo_recycler_view?.adapter = RepoAdapter(true, {}, {
|
binding?.repoRecyclerView?.adapter = RepoAdapter(true, {}, {
|
||||||
PluginsViewModel.downloadAll(activity, it.url, null)
|
PluginsViewModel.downloadAll(activity, it.url, null)
|
||||||
}).apply { updateList(repositories) }
|
}).apply { updateList(repositories) }
|
||||||
}
|
}
|
||||||
|
@ -80,39 +86,40 @@ class SetupFragmentExtensions : Fragment() {
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
context?.fixPaddingStatusbar(setup_root)
|
fixPaddingStatusbar(binding?.setupRoot)
|
||||||
val isSetup = arguments?.getBoolean(SETUP_EXTENSION_BUNDLE_IS_SETUP) ?: false
|
val isSetup = arguments?.getBoolean(SETUP_EXTENSION_BUNDLE_IS_SETUP) ?: false
|
||||||
|
|
||||||
// view_public_repositories_button?.setOnClickListener {
|
// view_public_repositories_button?.setOnClickListener {
|
||||||
// openBrowser(PUBLIC_REPOSITORIES_LIST, isTvSettings(), this)
|
// openBrowser(PUBLIC_REPOSITORIES_LIST, isTvSettings(), this)
|
||||||
// }
|
// }
|
||||||
|
|
||||||
with(context) {
|
normalSafeApiCall {
|
||||||
if (this == null) return
|
// val ctx = context ?: return@normalSafeApiCall
|
||||||
setRepositories()
|
setRepositories()
|
||||||
|
binding?.apply {
|
||||||
|
if (!isSetup) {
|
||||||
|
nextBtt.setText(R.string.setup_done)
|
||||||
|
}
|
||||||
|
prevBtt.isVisible = isSetup
|
||||||
|
|
||||||
if (!isSetup) {
|
nextBtt.setOnClickListener {
|
||||||
next_btt.setText(R.string.setup_done)
|
// Continue setup
|
||||||
}
|
if (isSetup)
|
||||||
prev_btt?.isVisible = isSetup
|
if (
|
||||||
|
// If any available languages
|
||||||
|
apis.distinctBy { it.lang }.size > 1
|
||||||
|
) {
|
||||||
|
findNavController().navigate(R.id.action_navigation_setup_extensions_to_navigation_setup_provider_languages)
|
||||||
|
} else {
|
||||||
|
findNavController().navigate(R.id.action_navigation_setup_extensions_to_navigation_setup_media)
|
||||||
|
}
|
||||||
|
else
|
||||||
|
findNavController().navigate(R.id.navigation_home)
|
||||||
|
}
|
||||||
|
|
||||||
next_btt?.setOnClickListener {
|
prevBtt.setOnClickListener {
|
||||||
// Continue setup
|
findNavController().navigate(R.id.navigation_setup_language)
|
||||||
if (isSetup)
|
}
|
||||||
if (
|
|
||||||
// If any available languages
|
|
||||||
apis.distinctBy { it.lang }.size > 1
|
|
||||||
) {
|
|
||||||
findNavController().navigate(R.id.action_navigation_setup_extensions_to_navigation_setup_provider_languages)
|
|
||||||
} else {
|
|
||||||
findNavController().navigate(R.id.action_navigation_setup_extensions_to_navigation_setup_media)
|
|
||||||
}
|
|
||||||
else
|
|
||||||
findNavController().navigate(R.id.navigation_home)
|
|
||||||
}
|
|
||||||
|
|
||||||
prev_btt?.setOnClickListener {
|
|
||||||
findNavController().navigate(R.id.navigation_setup_language)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,40 +13,49 @@ import androidx.preference.PreferenceManager
|
||||||
import com.lagradost.cloudstream3.BuildConfig
|
import com.lagradost.cloudstream3.BuildConfig
|
||||||
import com.lagradost.cloudstream3.CommonActivity
|
import com.lagradost.cloudstream3.CommonActivity
|
||||||
import com.lagradost.cloudstream3.R
|
import com.lagradost.cloudstream3.R
|
||||||
|
import com.lagradost.cloudstream3.databinding.FragmentSetupLanguageBinding
|
||||||
import com.lagradost.cloudstream3.mvvm.normalSafeApiCall
|
import com.lagradost.cloudstream3.mvvm.normalSafeApiCall
|
||||||
import com.lagradost.cloudstream3.plugins.PluginManager
|
import com.lagradost.cloudstream3.plugins.PluginManager
|
||||||
import com.lagradost.cloudstream3.ui.settings.appLanguages
|
import com.lagradost.cloudstream3.ui.settings.appLanguages
|
||||||
import com.lagradost.cloudstream3.ui.settings.getCurrentLocale
|
import com.lagradost.cloudstream3.ui.settings.getCurrentLocale
|
||||||
import com.lagradost.cloudstream3.utils.SubtitleHelper
|
import com.lagradost.cloudstream3.utils.SubtitleHelper
|
||||||
import com.lagradost.cloudstream3.utils.UIHelper.fixPaddingStatusbar
|
import com.lagradost.cloudstream3.utils.UIHelper.fixPaddingStatusbar
|
||||||
import kotlinx.android.synthetic.main.fragment_setup_language.*
|
|
||||||
import kotlinx.android.synthetic.main.fragment_setup_media.listview1
|
|
||||||
import kotlinx.android.synthetic.main.fragment_setup_media.next_btt
|
|
||||||
|
|
||||||
const val HAS_DONE_SETUP_KEY = "HAS_DONE_SETUP"
|
const val HAS_DONE_SETUP_KEY = "HAS_DONE_SETUP"
|
||||||
|
|
||||||
class SetupFragmentLanguage : Fragment() {
|
class SetupFragmentLanguage : Fragment() {
|
||||||
|
var binding: FragmentSetupLanguageBinding? = null
|
||||||
|
|
||||||
|
override fun onDestroyView() {
|
||||||
|
binding = null
|
||||||
|
super.onDestroyView()
|
||||||
|
}
|
||||||
|
|
||||||
override fun onCreateView(
|
override fun onCreateView(
|
||||||
inflater: LayoutInflater, container: ViewGroup?,
|
inflater: LayoutInflater, container: ViewGroup?,
|
||||||
savedInstanceState: Bundle?
|
savedInstanceState: Bundle?
|
||||||
): View? {
|
): View {
|
||||||
// Inflate the layout for this fragment
|
val localBinding = FragmentSetupLanguageBinding.inflate(inflater, container, false)
|
||||||
return inflater.inflate(R.layout.fragment_setup_language, container, false)
|
binding = localBinding
|
||||||
|
return localBinding.root
|
||||||
|
//return inflater.inflate(R.layout.fragment_setup_language, container, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
context?.fixPaddingStatusbar(setup_root)
|
|
||||||
|
|
||||||
// We don't want a crash for all users
|
// We don't want a crash for all users
|
||||||
normalSafeApiCall {
|
normalSafeApiCall {
|
||||||
with(context) {
|
fixPaddingStatusbar(binding?.setupRoot)
|
||||||
if (this == null) return@normalSafeApiCall
|
|
||||||
val settingsManager = PreferenceManager.getDefaultSharedPreferences(this)
|
|
||||||
|
|
||||||
val arrayAdapter =
|
val ctx = context ?: return@normalSafeApiCall
|
||||||
ArrayAdapter<String>(this, R.layout.sort_bottom_single_choice)
|
val settingsManager = PreferenceManager.getDefaultSharedPreferences(ctx)
|
||||||
|
|
||||||
|
val arrayAdapter =
|
||||||
|
ArrayAdapter<String>(ctx, R.layout.sort_bottom_single_choice)
|
||||||
|
|
||||||
|
binding?.apply {
|
||||||
// Icons may crash on some weird android versions?
|
// Icons may crash on some weird android versions?
|
||||||
normalSafeApiCall {
|
normalSafeApiCall {
|
||||||
val drawable = when {
|
val drawable = when {
|
||||||
|
@ -54,10 +63,10 @@ class SetupFragmentLanguage : Fragment() {
|
||||||
BuildConfig.BUILD_TYPE == "prerelease" -> R.drawable.cloud_2_gradient_beta
|
BuildConfig.BUILD_TYPE == "prerelease" -> R.drawable.cloud_2_gradient_beta
|
||||||
else -> R.drawable.cloud_2_gradient
|
else -> R.drawable.cloud_2_gradient
|
||||||
}
|
}
|
||||||
app_icon_image?.setImageDrawable(ContextCompat.getDrawable(this, drawable))
|
appIconImage.setImageDrawable(ContextCompat.getDrawable(ctx, drawable))
|
||||||
}
|
}
|
||||||
|
|
||||||
val current = getCurrentLocale(this)
|
val current = getCurrentLocale(ctx)
|
||||||
val languageCodes = appLanguages.map { it.third }
|
val languageCodes = appLanguages.map { it.third }
|
||||||
val languageNames = appLanguages.map { (emoji, name, iso) ->
|
val languageNames = appLanguages.map { (emoji, name, iso) ->
|
||||||
val flag = emoji.ifBlank { SubtitleHelper.getFlagFromIso(iso) ?: "ERROR" }
|
val flag = emoji.ifBlank { SubtitleHelper.getFlagFromIso(iso) ?: "ERROR" }
|
||||||
|
@ -66,18 +75,19 @@ class SetupFragmentLanguage : Fragment() {
|
||||||
val index = languageCodes.indexOf(current)
|
val index = languageCodes.indexOf(current)
|
||||||
|
|
||||||
arrayAdapter.addAll(languageNames)
|
arrayAdapter.addAll(languageNames)
|
||||||
listview1?.adapter = arrayAdapter
|
listview1.adapter = arrayAdapter
|
||||||
listview1?.choiceMode = AbsListView.CHOICE_MODE_SINGLE
|
listview1.choiceMode = AbsListView.CHOICE_MODE_SINGLE
|
||||||
listview1?.setItemChecked(index, true)
|
listview1.setItemChecked(index, true)
|
||||||
|
|
||||||
listview1?.setOnItemClickListener { _, _, position, _ ->
|
listview1.setOnItemClickListener { _, _, position, _ ->
|
||||||
val code = languageCodes[position]
|
val code = languageCodes[position]
|
||||||
CommonActivity.setLocale(activity, code)
|
CommonActivity.setLocale(activity, code)
|
||||||
settingsManager.edit().putString(getString(R.string.locale_key), code).apply()
|
settingsManager.edit().putString(getString(R.string.locale_key), code)
|
||||||
|
.apply()
|
||||||
activity?.recreate()
|
activity?.recreate()
|
||||||
}
|
}
|
||||||
|
|
||||||
next_btt?.setOnClickListener {
|
nextBtt.setOnClickListener {
|
||||||
// If no plugins go to plugins page
|
// If no plugins go to plugins page
|
||||||
val nextDestination = if (
|
val nextDestination = if (
|
||||||
PluginManager.getPluginsOnline().isEmpty()
|
PluginManager.getPluginsOnline().isEmpty()
|
||||||
|
@ -92,10 +102,11 @@ class SetupFragmentLanguage : Fragment() {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
skip_btt?.setOnClickListener {
|
skipBtt.setOnClickListener {
|
||||||
findNavController().navigate(R.id.navigation_home)
|
findNavController().navigate(R.id.navigation_home)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,30 +10,39 @@ import androidx.fragment.app.Fragment
|
||||||
import androidx.navigation.fragment.findNavController
|
import androidx.navigation.fragment.findNavController
|
||||||
import androidx.preference.PreferenceManager
|
import androidx.preference.PreferenceManager
|
||||||
import com.lagradost.cloudstream3.R
|
import com.lagradost.cloudstream3.R
|
||||||
|
import com.lagradost.cloudstream3.databinding.FragmentSetupLayoutBinding
|
||||||
|
import com.lagradost.cloudstream3.mvvm.normalSafeApiCall
|
||||||
import com.lagradost.cloudstream3.utils.UIHelper.fixPaddingStatusbar
|
import com.lagradost.cloudstream3.utils.UIHelper.fixPaddingStatusbar
|
||||||
import kotlinx.android.synthetic.main.fragment_setup_layout.*
|
|
||||||
import kotlinx.android.synthetic.main.fragment_setup_media.listview1
|
|
||||||
import kotlinx.android.synthetic.main.fragment_setup_media.next_btt
|
|
||||||
import kotlinx.android.synthetic.main.fragment_setup_media.prev_btt
|
|
||||||
import kotlinx.android.synthetic.main.fragment_setup_media.setup_root
|
|
||||||
import org.acra.ACRA
|
import org.acra.ACRA
|
||||||
|
|
||||||
|
|
||||||
class SetupFragmentLayout : Fragment() {
|
class SetupFragmentLayout : Fragment() {
|
||||||
|
|
||||||
|
var binding: FragmentSetupLayoutBinding? = null
|
||||||
|
|
||||||
|
override fun onDestroyView() {
|
||||||
|
binding = null
|
||||||
|
super.onDestroyView()
|
||||||
|
}
|
||||||
|
|
||||||
override fun onCreateView(
|
override fun onCreateView(
|
||||||
inflater: LayoutInflater, container: ViewGroup?,
|
inflater: LayoutInflater, container: ViewGroup?,
|
||||||
savedInstanceState: Bundle?
|
savedInstanceState: Bundle?
|
||||||
): View? {
|
): View {
|
||||||
return inflater.inflate(R.layout.fragment_setup_layout, container, false)
|
val localBinding = FragmentSetupLayoutBinding.inflate(inflater, container, false)
|
||||||
|
binding = localBinding
|
||||||
|
return localBinding.root
|
||||||
|
//return inflater.inflate(R.layout.fragment_setup_layout, container, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
context?.fixPaddingStatusbar(setup_root)
|
fixPaddingStatusbar(binding?.setupRoot)
|
||||||
|
|
||||||
with(context) {
|
normalSafeApiCall {
|
||||||
if (this == null) return
|
val ctx = context ?: return@normalSafeApiCall
|
||||||
val settingsManager = PreferenceManager.getDefaultSharedPreferences(this)
|
|
||||||
|
val settingsManager = PreferenceManager.getDefaultSharedPreferences(ctx)
|
||||||
|
|
||||||
val prefNames = resources.getStringArray(R.array.app_layout)
|
val prefNames = resources.getStringArray(R.array.app_layout)
|
||||||
val prefValues = resources.getIntArray(R.array.app_layout_values)
|
val prefValues = resources.getIntArray(R.array.app_layout_values)
|
||||||
|
@ -42,48 +51,48 @@ class SetupFragmentLayout : Fragment() {
|
||||||
settingsManager.getInt(getString(R.string.app_layout_key), -1)
|
settingsManager.getInt(getString(R.string.app_layout_key), -1)
|
||||||
|
|
||||||
val arrayAdapter =
|
val arrayAdapter =
|
||||||
ArrayAdapter<String>(this, R.layout.sort_bottom_single_choice)
|
ArrayAdapter<String>(ctx, R.layout.sort_bottom_single_choice)
|
||||||
|
|
||||||
arrayAdapter.addAll(prefNames.toList())
|
arrayAdapter.addAll(prefNames.toList())
|
||||||
listview1?.adapter = arrayAdapter
|
binding?.apply {
|
||||||
listview1?.choiceMode = AbsListView.CHOICE_MODE_SINGLE
|
listview1.adapter = arrayAdapter
|
||||||
listview1?.setItemChecked(
|
listview1.choiceMode = AbsListView.CHOICE_MODE_SINGLE
|
||||||
prefValues.indexOf(currentLayout), true
|
listview1.setItemChecked(
|
||||||
)
|
prefValues.indexOf(currentLayout), true
|
||||||
|
|
||||||
listview1?.setOnItemClickListener { _, _, position, _ ->
|
|
||||||
settingsManager.edit()
|
|
||||||
.putInt(getString(R.string.app_layout_key), prefValues[position])
|
|
||||||
.apply()
|
|
||||||
activity?.recreate()
|
|
||||||
}
|
|
||||||
|
|
||||||
acra_switch?.setOnCheckedChangeListener { _, enableCrashReporting ->
|
|
||||||
// Use same pref as in settings
|
|
||||||
settingsManager.edit().putBoolean(ACRA.PREF_DISABLE_ACRA, !enableCrashReporting)
|
|
||||||
.apply()
|
|
||||||
val text =
|
|
||||||
if (enableCrashReporting) R.string.bug_report_settings_off else R.string.bug_report_settings_on
|
|
||||||
crash_reporting_text?.text = getText(text)
|
|
||||||
}
|
|
||||||
|
|
||||||
val enableCrashReporting = !settingsManager.getBoolean(ACRA.PREF_DISABLE_ACRA, true)
|
|
||||||
acra_switch.isChecked = enableCrashReporting
|
|
||||||
crash_reporting_text.text =
|
|
||||||
getText(
|
|
||||||
if (enableCrashReporting) R.string.bug_report_settings_off else R.string.bug_report_settings_on
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
listview1.setOnItemClickListener { _, _, position, _ ->
|
||||||
|
settingsManager.edit()
|
||||||
|
.putInt(getString(R.string.app_layout_key), prefValues[position])
|
||||||
|
.apply()
|
||||||
|
activity?.recreate()
|
||||||
|
}
|
||||||
|
acraSwitch.setOnCheckedChangeListener { _, enableCrashReporting ->
|
||||||
|
// Use same pref as in settings
|
||||||
|
settingsManager.edit().putBoolean(ACRA.PREF_DISABLE_ACRA, !enableCrashReporting)
|
||||||
|
.apply()
|
||||||
|
val text =
|
||||||
|
if (enableCrashReporting) R.string.bug_report_settings_off else R.string.bug_report_settings_on
|
||||||
|
crashReportingText.text = getText(text)
|
||||||
|
}
|
||||||
|
|
||||||
next_btt?.setOnClickListener {
|
val enableCrashReporting = !settingsManager.getBoolean(ACRA.PREF_DISABLE_ACRA, true)
|
||||||
findNavController().navigate(R.id.navigation_home)
|
|
||||||
}
|
|
||||||
|
|
||||||
prev_btt?.setOnClickListener {
|
acraSwitch.isChecked = enableCrashReporting
|
||||||
findNavController().popBackStack()
|
crashReportingText.text =
|
||||||
|
getText(
|
||||||
|
if (enableCrashReporting) R.string.bug_report_settings_off else R.string.bug_report_settings_on
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
nextBtt.setOnClickListener {
|
||||||
|
findNavController().navigate(R.id.navigation_home)
|
||||||
|
}
|
||||||
|
|
||||||
|
prevBtt.setOnClickListener {
|
||||||
|
findNavController().popBackStack()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -10,72 +10,85 @@ import androidx.core.util.forEach
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.navigation.fragment.findNavController
|
import androidx.navigation.fragment.findNavController
|
||||||
import androidx.preference.PreferenceManager
|
import androidx.preference.PreferenceManager
|
||||||
|
import com.lagradost.cloudstream3.AcraApplication.Companion.removeKey
|
||||||
import com.lagradost.cloudstream3.R
|
import com.lagradost.cloudstream3.R
|
||||||
import com.lagradost.cloudstream3.TvType
|
import com.lagradost.cloudstream3.TvType
|
||||||
import com.lagradost.cloudstream3.utils.DataStore.removeKey
|
import com.lagradost.cloudstream3.databinding.FragmentSetupMediaBinding
|
||||||
import com.lagradost.cloudstream3.utils.USER_SELECTED_HOMEPAGE_API
|
import com.lagradost.cloudstream3.mvvm.normalSafeApiCall
|
||||||
import com.lagradost.cloudstream3.utils.UIHelper.fixPaddingStatusbar
|
import com.lagradost.cloudstream3.utils.UIHelper.fixPaddingStatusbar
|
||||||
import kotlinx.android.synthetic.main.fragment_setup_media.*
|
import com.lagradost.cloudstream3.utils.USER_SELECTED_HOMEPAGE_API
|
||||||
|
|
||||||
|
|
||||||
class SetupFragmentMedia : Fragment() {
|
class SetupFragmentMedia : Fragment() {
|
||||||
|
var binding: FragmentSetupMediaBinding? = null
|
||||||
|
|
||||||
|
override fun onDestroyView() {
|
||||||
|
binding = null
|
||||||
|
super.onDestroyView()
|
||||||
|
}
|
||||||
|
|
||||||
override fun onCreateView(
|
override fun onCreateView(
|
||||||
inflater: LayoutInflater, container: ViewGroup?,
|
inflater: LayoutInflater, container: ViewGroup?,
|
||||||
savedInstanceState: Bundle?
|
savedInstanceState: Bundle?
|
||||||
): View? {
|
): View {
|
||||||
return inflater.inflate(R.layout.fragment_setup_media, container, false)
|
val localBinding = FragmentSetupMediaBinding.inflate(inflater, container, false)
|
||||||
|
binding = localBinding
|
||||||
|
return localBinding.root
|
||||||
|
//return inflater.inflate(R.layout.fragment_setup_media, container, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
context?.fixPaddingStatusbar(setup_root)
|
normalSafeApiCall {
|
||||||
|
fixPaddingStatusbar(binding?.setupRoot)
|
||||||
|
|
||||||
with(context) {
|
val ctx = context ?: return@normalSafeApiCall
|
||||||
if (this == null) return
|
val settingsManager = PreferenceManager.getDefaultSharedPreferences(ctx)
|
||||||
val settingsManager = PreferenceManager.getDefaultSharedPreferences(this)
|
|
||||||
|
|
||||||
val arrayAdapter =
|
val arrayAdapter =
|
||||||
ArrayAdapter<String>(this, R.layout.sort_bottom_single_choice)
|
ArrayAdapter<String>(ctx, R.layout.sort_bottom_single_choice)
|
||||||
|
|
||||||
val names = enumValues<TvType>().sorted().map { it.name }
|
val names = enumValues<TvType>().sorted().map { it.name }
|
||||||
val selected = mutableListOf<Int>()
|
val selected = mutableListOf<Int>()
|
||||||
|
|
||||||
arrayAdapter.addAll(names)
|
arrayAdapter.addAll(names)
|
||||||
listview1?.let {
|
binding?.apply {
|
||||||
it.adapter = arrayAdapter
|
listview1.let {
|
||||||
it.choiceMode = AbsListView.CHOICE_MODE_MULTIPLE
|
it.adapter = arrayAdapter
|
||||||
|
it.choiceMode = AbsListView.CHOICE_MODE_MULTIPLE
|
||||||
|
|
||||||
it.setOnItemClickListener { _, _, _, _ ->
|
it.setOnItemClickListener { _, _, _, _ ->
|
||||||
it.checkedItemPositions?.forEach { key, value ->
|
it.checkedItemPositions?.forEach { key, value ->
|
||||||
if (value) {
|
if (value) {
|
||||||
selected.add(key)
|
selected.add(key)
|
||||||
} else {
|
} else {
|
||||||
selected.remove(key)
|
selected.remove(key)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
val prefValues = selected.mapNotNull { pos ->
|
||||||
|
val item =
|
||||||
|
it.getItemAtPosition(pos)?.toString() ?: return@mapNotNull null
|
||||||
|
val itemVal = TvType.valueOf(item)
|
||||||
|
itemVal.ordinal.toString()
|
||||||
|
}.toSet()
|
||||||
|
settingsManager.edit()
|
||||||
|
.putStringSet(getString(R.string.prefer_media_type_key), prefValues)
|
||||||
|
.apply()
|
||||||
|
|
||||||
|
// Regenerate set homepage
|
||||||
|
removeKey(USER_SELECTED_HOMEPAGE_API)
|
||||||
}
|
}
|
||||||
val prefValues = selected.mapNotNull { pos ->
|
|
||||||
val item = it.getItemAtPosition(pos)?.toString() ?: return@mapNotNull null
|
|
||||||
val itemVal = TvType.valueOf(item)
|
|
||||||
itemVal.ordinal.toString()
|
|
||||||
}.toSet()
|
|
||||||
settingsManager.edit()
|
|
||||||
.putStringSet(getString(R.string.prefer_media_type_key), prefValues)
|
|
||||||
.apply()
|
|
||||||
|
|
||||||
// Regenerate set homepage
|
|
||||||
removeKey(USER_SELECTED_HOMEPAGE_API)
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
next_btt?.setOnClickListener {
|
nextBtt.setOnClickListener {
|
||||||
findNavController().navigate(R.id.navigation_setup_media_to_navigation_setup_layout)
|
findNavController().navigate(R.id.navigation_setup_media_to_navigation_setup_layout)
|
||||||
}
|
}
|
||||||
|
|
||||||
prev_btt?.setOnClickListener {
|
prevBtt.setOnClickListener {
|
||||||
findNavController().popBackStack()
|
findNavController().popBackStack()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -14,31 +14,43 @@ import com.lagradost.cloudstream3.APIHolder
|
||||||
import com.lagradost.cloudstream3.APIHolder.getApiProviderLangSettings
|
import com.lagradost.cloudstream3.APIHolder.getApiProviderLangSettings
|
||||||
import com.lagradost.cloudstream3.AllLanguagesName
|
import com.lagradost.cloudstream3.AllLanguagesName
|
||||||
import com.lagradost.cloudstream3.R
|
import com.lagradost.cloudstream3.R
|
||||||
|
import com.lagradost.cloudstream3.databinding.FragmentSetupProviderLanguagesBinding
|
||||||
|
import com.lagradost.cloudstream3.mvvm.normalSafeApiCall
|
||||||
import com.lagradost.cloudstream3.utils.SubtitleHelper
|
import com.lagradost.cloudstream3.utils.SubtitleHelper
|
||||||
import com.lagradost.cloudstream3.utils.UIHelper.fixPaddingStatusbar
|
import com.lagradost.cloudstream3.utils.UIHelper.fixPaddingStatusbar
|
||||||
import kotlinx.android.synthetic.main.fragment_setup_media.*
|
|
||||||
|
|
||||||
class SetupFragmentProviderLanguage : Fragment() {
|
class SetupFragmentProviderLanguage : Fragment() {
|
||||||
|
var binding: FragmentSetupProviderLanguagesBinding? = null
|
||||||
|
|
||||||
|
override fun onDestroyView() {
|
||||||
|
binding = null
|
||||||
|
super.onDestroyView()
|
||||||
|
}
|
||||||
|
|
||||||
override fun onCreateView(
|
override fun onCreateView(
|
||||||
inflater: LayoutInflater, container: ViewGroup?,
|
inflater: LayoutInflater, container: ViewGroup?,
|
||||||
savedInstanceState: Bundle?
|
savedInstanceState: Bundle?
|
||||||
): View? {
|
): View {
|
||||||
// Inflate the layout for this fragment
|
val localBinding = FragmentSetupProviderLanguagesBinding.inflate(inflater, container, false)
|
||||||
return inflater.inflate(R.layout.fragment_setup_provider_languages, container, false)
|
binding = localBinding
|
||||||
|
return localBinding.root
|
||||||
|
//return inflater.inflate(R.layout.fragment_setup_provider_languages, container, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
context?.fixPaddingStatusbar(setup_root)
|
fixPaddingStatusbar(binding?.setupRoot)
|
||||||
|
|
||||||
with(context) {
|
normalSafeApiCall {
|
||||||
if (this == null) return
|
val ctx = context ?: return@normalSafeApiCall
|
||||||
val settingsManager = PreferenceManager.getDefaultSharedPreferences(this)
|
|
||||||
|
val settingsManager = PreferenceManager.getDefaultSharedPreferences(ctx)
|
||||||
|
|
||||||
val arrayAdapter =
|
val arrayAdapter =
|
||||||
ArrayAdapter<String>(this, R.layout.sort_bottom_single_choice)
|
ArrayAdapter<String>(ctx, R.layout.sort_bottom_single_choice)
|
||||||
|
|
||||||
val current = this.getApiProviderLangSettings()
|
val current = ctx.getApiProviderLangSettings()
|
||||||
val langs = APIHolder.apis.map { it.lang }.toSet()
|
val langs = APIHolder.apis.map { it.lang }.toSet()
|
||||||
.sortedBy { SubtitleHelper.fromTwoLettersToLanguage(it) } + AllLanguagesName
|
.sortedBy { SubtitleHelper.fromTwoLettersToLanguage(it) } + AllLanguagesName
|
||||||
|
|
||||||
|
@ -56,31 +68,31 @@ class SetupFragmentProviderLanguage : Fragment() {
|
||||||
}
|
}
|
||||||
|
|
||||||
arrayAdapter.addAll(languageNames)
|
arrayAdapter.addAll(languageNames)
|
||||||
|
binding?.apply {
|
||||||
listview1?.adapter = arrayAdapter
|
listview1.adapter = arrayAdapter
|
||||||
listview1?.choiceMode = AbsListView.CHOICE_MODE_MULTIPLE
|
listview1.choiceMode = AbsListView.CHOICE_MODE_MULTIPLE
|
||||||
currentList.forEach {
|
currentList.forEach {
|
||||||
listview1.setItemChecked(it, true)
|
listview1.setItemChecked(it, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
listview1?.setOnItemClickListener { _, _, _, _ ->
|
listview1.setOnItemClickListener { _, _, _, _ ->
|
||||||
val currentLanguages = mutableListOf<String>()
|
val currentLanguages = mutableListOf<String>()
|
||||||
listview1?.checkedItemPositions?.forEach { key, value ->
|
listview1.checkedItemPositions?.forEach { key, value ->
|
||||||
if (value) currentLanguages.add(langs[key])
|
if (value) currentLanguages.add(langs[key])
|
||||||
}
|
}
|
||||||
settingsManager.edit().putStringSet(
|
settingsManager.edit().putStringSet(
|
||||||
this.getString(R.string.provider_lang_key),
|
ctx.getString(R.string.provider_lang_key),
|
||||||
currentLanguages.toSet()
|
currentLanguages.toSet()
|
||||||
).apply()
|
).apply()
|
||||||
}
|
}
|
||||||
|
|
||||||
next_btt?.setOnClickListener {
|
nextBtt.setOnClickListener {
|
||||||
findNavController().navigate(R.id.navigation_setup_provider_languages_to_navigation_setup_media)
|
findNavController().navigate(R.id.navigation_setup_provider_languages_to_navigation_setup_media)
|
||||||
}
|
}
|
||||||
|
|
||||||
prev_btt?.setOnClickListener {
|
prevBtt.setOnClickListener {
|
||||||
findNavController().popBackStack()
|
findNavController().popBackStack()
|
||||||
}
|
} }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,7 @@ import com.lagradost.cloudstream3.CommonActivity.onColorSelectedEvent
|
||||||
import com.lagradost.cloudstream3.CommonActivity.onDialogDismissedEvent
|
import com.lagradost.cloudstream3.CommonActivity.onDialogDismissedEvent
|
||||||
import com.lagradost.cloudstream3.CommonActivity.showToast
|
import com.lagradost.cloudstream3.CommonActivity.showToast
|
||||||
import com.lagradost.cloudstream3.R
|
import com.lagradost.cloudstream3.R
|
||||||
|
import com.lagradost.cloudstream3.databinding.ChromecastSubtitleSettingsBinding
|
||||||
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTvSettings
|
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTvSettings
|
||||||
import com.lagradost.cloudstream3.utils.DataStore.setKey
|
import com.lagradost.cloudstream3.utils.DataStore.setKey
|
||||||
import com.lagradost.cloudstream3.utils.Event
|
import com.lagradost.cloudstream3.utils.Event
|
||||||
|
@ -31,7 +32,6 @@ import com.lagradost.cloudstream3.utils.UIHelper.fixPaddingStatusbar
|
||||||
import com.lagradost.cloudstream3.utils.UIHelper.hideSystemUI
|
import com.lagradost.cloudstream3.utils.UIHelper.hideSystemUI
|
||||||
import com.lagradost.cloudstream3.utils.UIHelper.navigate
|
import com.lagradost.cloudstream3.utils.UIHelper.navigate
|
||||||
import com.lagradost.cloudstream3.utils.UIHelper.popCurrentPage
|
import com.lagradost.cloudstream3.utils.UIHelper.popCurrentPage
|
||||||
import kotlinx.android.synthetic.main.subtitle_settings.*
|
|
||||||
|
|
||||||
const val CHROME_SUBTITLE_KEY = "chome_subtitle_settings"
|
const val CHROME_SUBTITLE_KEY = "chome_subtitle_settings"
|
||||||
|
|
||||||
|
@ -137,12 +137,21 @@ class ChromecastSubtitlesFragment : Fragment() {
|
||||||
//subtitle_text?.setStyle(fromSaveToStyle(state))
|
//subtitle_text?.setStyle(fromSaveToStyle(state))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var binding : ChromecastSubtitleSettingsBinding? = null
|
||||||
|
|
||||||
override fun onCreateView(
|
override fun onCreateView(
|
||||||
inflater: LayoutInflater,
|
inflater: LayoutInflater,
|
||||||
container: ViewGroup?,
|
container: ViewGroup?,
|
||||||
savedInstanceState: Bundle?,
|
savedInstanceState: Bundle?,
|
||||||
): View? {
|
): View {
|
||||||
return inflater.inflate(R.layout.chromecast_subtitle_settings, container, false)
|
val localBinding = ChromecastSubtitleSettingsBinding.inflate(inflater, container, false)
|
||||||
|
binding = localBinding
|
||||||
|
return localBinding.root//inflater.inflate(R.layout.chromecast_subtitle_settings, container, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDestroyView() {
|
||||||
|
binding = null
|
||||||
|
super.onDestroyView()
|
||||||
}
|
}
|
||||||
|
|
||||||
private lateinit var state: SaveChromeCaptionStyle
|
private lateinit var state: SaveChromeCaptionStyle
|
||||||
|
@ -159,7 +168,7 @@ class ChromecastSubtitlesFragment : Fragment() {
|
||||||
onColorSelectedEvent += ::onColorSelected
|
onColorSelectedEvent += ::onColorSelected
|
||||||
onDialogDismissedEvent += ::onDialogDismissed
|
onDialogDismissedEvent += ::onDialogDismissed
|
||||||
|
|
||||||
context?.fixPaddingStatusbar(subs_root)
|
fixPaddingStatusbar(binding?.subsRoot)
|
||||||
|
|
||||||
state = getCurrentSavedStyle()
|
state = getCurrentSavedStyle()
|
||||||
context?.updateState()
|
context?.updateState()
|
||||||
|
@ -190,17 +199,20 @@ class ChromecastSubtitlesFragment : Fragment() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
subs_text_color.setup(0)
|
binding?.apply {
|
||||||
subs_outline_color.setup(1)
|
subsTextColor.setup(0)
|
||||||
subs_background_color.setup(2)
|
subsOutlineColor.setup(1)
|
||||||
|
subsBackgroundColor.setup(2)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
val dismissCallback = {
|
val dismissCallback = {
|
||||||
if (hide)
|
if (hide)
|
||||||
activity?.hideSystemUI()
|
activity?.hideSystemUI()
|
||||||
}
|
}
|
||||||
|
|
||||||
subs_edge_type.setFocusableInTv()
|
binding?.subsEdgeType?.setFocusableInTv()
|
||||||
subs_edge_type.setOnClickListener { textView ->
|
binding?.subsEdgeType?.setOnClickListener { textView ->
|
||||||
val edgeTypes = listOf(
|
val edgeTypes = listOf(
|
||||||
Pair(
|
Pair(
|
||||||
EDGE_TYPE_NONE,
|
EDGE_TYPE_NONE,
|
||||||
|
@ -237,15 +249,15 @@ class ChromecastSubtitlesFragment : Fragment() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
subs_edge_type.setOnLongClickListener {
|
binding?.subsEdgeType?.setOnLongClickListener {
|
||||||
state.edgeType = defaultState.edgeType
|
state.edgeType = defaultState.edgeType
|
||||||
it.context.updateState()
|
it.context.updateState()
|
||||||
showToast(activity, R.string.subs_default_reset_toast, Toast.LENGTH_SHORT)
|
showToast(activity, R.string.subs_default_reset_toast, Toast.LENGTH_SHORT)
|
||||||
return@setOnLongClickListener true
|
return@setOnLongClickListener true
|
||||||
}
|
}
|
||||||
|
|
||||||
subs_font_size.setFocusableInTv()
|
binding?.subsFontSize?.setFocusableInTv()
|
||||||
subs_font_size.setOnClickListener { textView ->
|
binding?.subsFontSize?.setOnClickListener { textView ->
|
||||||
val fontSizes = listOf(
|
val fontSizes = listOf(
|
||||||
Pair(0.75f, "75%"),
|
Pair(0.75f, "75%"),
|
||||||
Pair(0.80f, "80%"),
|
Pair(0.80f, "80%"),
|
||||||
|
@ -278,24 +290,26 @@ class ChromecastSubtitlesFragment : Fragment() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
subs_font_size.setOnLongClickListener { _ ->
|
binding?.subsFontSize?.setOnLongClickListener { _ ->
|
||||||
state.fontScale = defaultState.fontScale
|
state.fontScale = defaultState.fontScale
|
||||||
//textView.context.updateState() // font size not changed
|
//textView.context.updateState() // font size not changed
|
||||||
showToast(activity, R.string.subs_default_reset_toast, Toast.LENGTH_SHORT)
|
showToast(activity, R.string.subs_default_reset_toast, Toast.LENGTH_SHORT)
|
||||||
return@setOnLongClickListener true
|
return@setOnLongClickListener true
|
||||||
}
|
}
|
||||||
|
|
||||||
subs_font.setFocusableInTv()
|
|
||||||
subs_font.setOnClickListener { textView ->
|
|
||||||
|
binding?.subsFont?.setFocusableInTv()
|
||||||
|
binding?.subsFont?.setOnClickListener { textView ->
|
||||||
val fontTypes = listOf(
|
val fontTypes = listOf(
|
||||||
Pair(null, textView.context.getString(R.string.normal)),
|
null to textView.context.getString(R.string.normal),
|
||||||
Pair("Droid Sans", "Droid Sans"),
|
"Droid Sans" to "Droid Sans",
|
||||||
Pair("Droid Sans Mono", "Droid Sans Mono"),
|
"Droid Sans Mono" to "Droid Sans Mono",
|
||||||
Pair("Droid Serif Regular", "Droid Serif Regular"),
|
"Droid Serif Regular" to "Droid Serif Regular",
|
||||||
Pair("Cutive Mono", "Cutive Mono"),
|
"Cutive Mono" to "Cutive Mono",
|
||||||
Pair("Short Stack", "Short Stack"),
|
"Short Stack" to "Short Stack",
|
||||||
Pair("Quintessential", "Quintessential"),
|
"Quintessential" to "Quintessential",
|
||||||
Pair("Alegreya Sans SC", "Alegreya Sans SC"),
|
"Alegreya Sans SC" to "Alegreya Sans SC",
|
||||||
)
|
)
|
||||||
|
|
||||||
//showBottomDialog
|
//showBottomDialog
|
||||||
|
@ -310,35 +324,35 @@ class ChromecastSubtitlesFragment : Fragment() {
|
||||||
textView.context.updateState()
|
textView.context.updateState()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
binding?.subsFont?.setOnLongClickListener { textView ->
|
||||||
subs_font.setOnLongClickListener { textView ->
|
|
||||||
state.fontFamily = defaultState.fontFamily
|
state.fontFamily = defaultState.fontFamily
|
||||||
textView.context.updateState()
|
textView.context.updateState()
|
||||||
showToast(activity, R.string.subs_default_reset_toast, Toast.LENGTH_SHORT)
|
showToast(activity, R.string.subs_default_reset_toast, Toast.LENGTH_SHORT)
|
||||||
return@setOnLongClickListener true
|
return@setOnLongClickListener true
|
||||||
}
|
}
|
||||||
|
|
||||||
cancel_btt.setOnClickListener {
|
binding?.cancelBtt?.setOnClickListener {
|
||||||
activity?.popCurrentPage()
|
activity?.popCurrentPage()
|
||||||
}
|
}
|
||||||
|
|
||||||
apply_btt.setOnClickListener {
|
binding?.applyBtt?.setOnClickListener {
|
||||||
it.context.saveStyle(state)
|
it.context.saveStyle(state)
|
||||||
applyStyleEvent.invoke(state)
|
applyStyleEvent.invoke(state)
|
||||||
//it.context.fromSaveToStyle(state)
|
//it.context.fromSaveToStyle(state)
|
||||||
activity?.popCurrentPage()
|
activity?.popCurrentPage()
|
||||||
}
|
}
|
||||||
|
binding?.subtitleText?.apply {
|
||||||
subtitle_text.setCues(
|
setCues(
|
||||||
listOf(
|
listOf(
|
||||||
Cue.Builder()
|
Cue.Builder()
|
||||||
.setTextSize(
|
.setTextSize(
|
||||||
getPixels(TypedValue.COMPLEX_UNIT_SP, 25.0f).toFloat(),
|
getPixels(TypedValue.COMPLEX_UNIT_SP, 25.0f).toFloat(),
|
||||||
Cue.TEXT_SIZE_TYPE_ABSOLUTE
|
Cue.TEXT_SIZE_TYPE_ABSOLUTE
|
||||||
)
|
)
|
||||||
.setText(subtitle_text.context.getString(R.string.subtitles_example_text))
|
.setText(context.getString(R.string.subtitles_example_text))
|
||||||
.build()
|
.build()
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -238,7 +238,7 @@ class SubtitlesFragment : Fragment() {
|
||||||
context?.getExternalFilesDir(null)?.absolutePath.toString() + "/Fonts"
|
context?.getExternalFilesDir(null)?.absolutePath.toString() + "/Fonts"
|
||||||
)
|
)
|
||||||
|
|
||||||
context?.fixPaddingStatusbar(subs_root)
|
fixPaddingStatusbar(subs_root)
|
||||||
|
|
||||||
state = getCurrentSavedStyle()
|
state = getCurrentSavedStyle()
|
||||||
context?.updateState()
|
context?.updateState()
|
||||||
|
|
|
@ -397,21 +397,22 @@ object UIHelper {
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Context?.fixPaddingStatusbar(v: View?) {
|
fun fixPaddingStatusbar(v: View?) {
|
||||||
if (v == null || this == null) return
|
if (v == null) return
|
||||||
|
val ctx = v.context ?: return
|
||||||
v.setPadding(
|
v.setPadding(
|
||||||
v.paddingLeft,
|
v.paddingLeft,
|
||||||
v.paddingTop + getStatusBarHeight(),
|
v.paddingTop + ctx.getStatusBarHeight(),
|
||||||
v.paddingRight,
|
v.paddingRight,
|
||||||
v.paddingBottom
|
v.paddingBottom
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Context.fixPaddingStatusbarView(v: View?) {
|
fun fixPaddingStatusbarView(v: View?) {
|
||||||
if (v == null) return
|
if (v == null) return
|
||||||
|
val ctx = v.context ?: return
|
||||||
val params = v.layoutParams
|
val params = v.layoutParams
|
||||||
params.height = getStatusBarHeight()
|
params.height = ctx.getStatusBarHeight()
|
||||||
v.layoutParams = params
|
v.layoutParams = params
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -172,4 +172,15 @@
|
||||||
app:icon="@drawable/ic_baseline_filter_list_24"
|
app:icon="@drawable/ic_baseline_filter_list_24"
|
||||||
tools:ignore="ContentDescription"
|
tools:ignore="ContentDescription"
|
||||||
tools:visibility="visible" />
|
tools:visibility="visible" />
|
||||||
|
|
||||||
|
<com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
|
||||||
|
android:id="@+id/home_random"
|
||||||
|
style="@style/ExtendedFloatingActionButton"
|
||||||
|
android:layout_gravity="bottom|start"
|
||||||
|
android:text="@string/home_random"
|
||||||
|
android:textColor="?attr/textColor"
|
||||||
|
android:visibility="gone"
|
||||||
|
app:icon="@drawable/ic_baseline_play_arrow_24"
|
||||||
|
tools:ignore="ContentDescription"
|
||||||
|
tools:visibility="visible" />
|
||||||
</FrameLayout>
|
</FrameLayout>
|
|
@ -25,7 +25,7 @@
|
||||||
app:titleTextColor="?attr/textColor"
|
app:titleTextColor="?attr/textColor"
|
||||||
tools:title="Overlord" />
|
tools:title="Overlord" />
|
||||||
|
|
||||||
<include layout="@layout/tvtypes_chips_scroll" />
|
<include layout="@layout/tvtypes_chips_scroll" android:id="@+id/tvtypes_chips_scroll" />
|
||||||
</com.google.android.material.appbar.AppBarLayout>
|
</com.google.android.material.appbar.AppBarLayout>
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
|
|
@ -88,7 +88,7 @@
|
||||||
app:tint="?attr/textColor" />
|
app:tint="?attr/textColor" />
|
||||||
</FrameLayout>
|
</FrameLayout>
|
||||||
|
|
||||||
<include layout="@layout/tvtypes_chips_scroll" />
|
<include layout="@layout/tvtypes_chips_scroll" android:id="@+id/tvtypes_chips_scroll" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -89,7 +89,7 @@
|
||||||
app:tint="?attr/textColor" />
|
app:tint="?attr/textColor" />
|
||||||
</FrameLayout>
|
</FrameLayout>
|
||||||
|
|
||||||
<include layout="@layout/tvtypes_chips_scroll" />
|
<include layout="@layout/tvtypes_chips_scroll" android:id="@+id/tvtypes_chips_scroll" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
android:layout_gravity="bottom"
|
android:layout_gravity="bottom"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="60dp">
|
android:layout_height="60dp">
|
||||||
<include layout="@layout/tvtypes_chips_scroll" />
|
<include layout="@layout/tvtypes_chips_scroll" android:id="@+id/tvtypes_chips_scroll" />
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:id="@+id/apply_btt_holder"
|
android:id="@+id/apply_btt_holder"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|
|
@ -1,6 +1,4 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
|
|
||||||
<com.lagradost.cloudstream3.ui.AutofitRecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
|
<com.lagradost.cloudstream3.ui.AutofitRecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:id="@+id/page_recyclerview"
|
android:id="@+id/page_recyclerview"
|
||||||
|
|
|
@ -1,151 +1,152 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
|
<androidx.cardview.widget.CardView 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:nextFocusRight="@id/result_episode_download"
|
android:id="@+id/episode_holder_large"
|
||||||
android:id="@+id/episode_holder_large"
|
android:layout_width="wrap_content"
|
||||||
|
|
||||||
android:layout_width="match_parent"
|
android:layout_height="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_marginBottom="10dp"
|
||||||
app:cardCornerRadius="@dimen/rounded_image_radius"
|
android:nextFocusRight="@id/result_episode_download"
|
||||||
app:cardBackgroundColor="?attr/boxItemBackground"
|
app:cardBackgroundColor="?attr/boxItemBackground"
|
||||||
|
|
||||||
android:layout_marginBottom="10dp">
|
app:cardCornerRadius="@dimen/rounded_image_radius">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:foreground="?android:attr/selectableItemBackgroundBorderless"
|
android:layout_width="wrap_content"
|
||||||
android:padding="10dp"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="vertical"
|
android:foreground="?android:attr/selectableItemBackgroundBorderless"
|
||||||
android:layout_width="match_parent"
|
android:orientation="vertical"
|
||||||
android:layout_height="wrap_content">
|
android:padding="10dp">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:id="@+id/episode_lin_holder"
|
||||||
android:orientation="horizontal"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content">
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal">
|
||||||
<!--app:cardCornerRadius="@dimen/roundedImageRadius"-->
|
<!--app:cardCornerRadius="@dimen/roundedImageRadius"-->
|
||||||
<androidx.cardview.widget.CardView
|
<androidx.cardview.widget.CardView
|
||||||
android:layout_width="126dp"
|
android:layout_width="126dp"
|
||||||
android:layout_height="72dp"
|
android:layout_height="72dp"
|
||||||
android:foreground="@drawable/outline_drawable">
|
android:foreground="@drawable/outline_drawable">
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:nextFocusRight="@id/result_episode_download"
|
android:id="@+id/episode_poster"
|
||||||
|
|
||||||
android:id="@+id/episode_poster"
|
android:layout_width="match_parent"
|
||||||
tools:src="@drawable/example_poster"
|
android:layout_height="match_parent"
|
||||||
android:foreground="?android:attr/selectableItemBackgroundBorderless"
|
android:contentDescription="@string/episode_poster_img_des"
|
||||||
|
|
||||||
android:scaleType="centerCrop"
|
android:foreground="?android:attr/selectableItemBackgroundBorderless"
|
||||||
android:layout_width="match_parent"
|
android:nextFocusRight="@id/result_episode_download"
|
||||||
android:layout_height="match_parent"
|
android:scaleType="centerCrop"
|
||||||
android:contentDescription="@string/episode_poster_img_des" />
|
tools:src="@drawable/example_poster" />
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:src="@drawable/play_button"
|
android:layout_width="36dp"
|
||||||
android:layout_gravity="center"
|
android:layout_height="36dp"
|
||||||
android:layout_width="36dp"
|
android:layout_gravity="center"
|
||||||
android:layout_height="36dp"
|
android:contentDescription="@string/play_episode"
|
||||||
android:contentDescription="@string/play_episode" />
|
android:src="@drawable/play_button" />
|
||||||
|
|
||||||
<androidx.core.widget.ContentLoadingProgressBar
|
<androidx.core.widget.ContentLoadingProgressBar
|
||||||
android:layout_marginBottom="-1.5dp"
|
android:id="@+id/episode_progress"
|
||||||
android:id="@+id/episode_progress"
|
style="@android:style/Widget.Material.ProgressBar.Horizontal"
|
||||||
android:progressTint="?attr/colorPrimary"
|
android:layout_width="match_parent"
|
||||||
android:progressBackgroundTint="?attr/colorPrimary"
|
android:layout_height="5dp"
|
||||||
style="@android:style/Widget.Material.ProgressBar.Horizontal"
|
android:layout_gravity="bottom"
|
||||||
android:layout_width="match_parent"
|
android:layout_marginBottom="-1.5dp"
|
||||||
tools:progress="50"
|
android:progressBackgroundTint="?attr/colorPrimary"
|
||||||
android:layout_gravity="bottom"
|
android:progressTint="?attr/colorPrimary"
|
||||||
android:layout_height="5dp" />
|
tools:progress="50" />
|
||||||
</androidx.cardview.widget.CardView>
|
</androidx.cardview.widget.CardView>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_marginStart="15dp"
|
android:layout_width="match_parent"
|
||||||
android:orientation="vertical"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="center"
|
android:layout_gravity="center"
|
||||||
android:layout_width="match_parent"
|
android:layout_marginStart="15dp"
|
||||||
android:layout_marginEnd="50dp"
|
android:layout_marginEnd="50dp"
|
||||||
android:layout_height="wrap_content">
|
android:orientation="vertical">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:orientation="horizontal"
|
android:layout_width="wrap_content"
|
||||||
android:layout_width="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_height="wrap_content">
|
android:orientation="horizontal">
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
<com.google.android.material.button.MaterialButton
|
||||||
android:layout_gravity="start"
|
android:id="@+id/episode_filler"
|
||||||
style="@style/SmallBlackButton"
|
style="@style/SmallBlackButton"
|
||||||
android:layout_marginEnd="10dp"
|
android:layout_gravity="start"
|
||||||
android:text="@string/filler"
|
android:layout_marginEnd="10dp"
|
||||||
android:id="@+id/episode_filler" />
|
android:text="@string/filler" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_gravity="center_vertical"
|
android:id="@+id/episode_text"
|
||||||
android:id="@+id/episode_text"
|
android:layout_width="wrap_content"
|
||||||
tools:text="1. Jobless"
|
android:layout_height="wrap_content"
|
||||||
android:textStyle="bold"
|
android:layout_gravity="center_vertical"
|
||||||
android:textColor="?attr/textColor"
|
android:textColor="?attr/textColor"
|
||||||
android:layout_width="wrap_content"
|
android:textStyle="bold"
|
||||||
android:layout_height="wrap_content" />
|
tools:text="1. Jobless" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/episode_rating"
|
android:id="@+id/episode_rating"
|
||||||
tools:text="Rated: 8.8"
|
android:layout_width="wrap_content"
|
||||||
android:textColor="?attr/grayTextColor"
|
android:layout_height="wrap_content"
|
||||||
android:layout_width="wrap_content"
|
android:textColor="?attr/grayTextColor"
|
||||||
android:layout_height="wrap_content" />
|
tools:text="Rated: 8.8" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<FrameLayout
|
<FrameLayout
|
||||||
android:layout_marginStart="-50dp"
|
android:layout_width="wrap_content"
|
||||||
android:layout_gravity="end"
|
android:layout_height="match_parent"
|
||||||
android:layout_width="wrap_content"
|
android:layout_gravity="end"
|
||||||
android:layout_height="match_parent">
|
android:layout_marginStart="-50dp">
|
||||||
|
|
||||||
<androidx.core.widget.ContentLoadingProgressBar
|
<androidx.core.widget.ContentLoadingProgressBar
|
||||||
android:layout_marginEnd="10dp"
|
android:id="@+id/result_episode_progress_downloaded"
|
||||||
android:layout_marginStart="10dp"
|
style="?android:attr/progressBarStyleHorizontal"
|
||||||
android:layout_width="40dp"
|
android:layout_width="40dp"
|
||||||
android:layout_height="40dp"
|
android:layout_height="40dp"
|
||||||
android:id="@+id/result_episode_progress_downloaded"
|
android:layout_gravity="end|center_vertical"
|
||||||
android:indeterminate="false"
|
android:layout_margin="5dp"
|
||||||
android:progressDrawable="@drawable/circular_progress_bar"
|
android:layout_marginStart="10dp"
|
||||||
android:background="@drawable/circle_shape"
|
android:layout_marginEnd="10dp"
|
||||||
style="?android:attr/progressBarStyleHorizontal"
|
android:background="@drawable/circle_shape"
|
||||||
android:max="100"
|
android:indeterminate="false"
|
||||||
android:layout_margin="5dp"
|
android:max="100"
|
||||||
android:layout_gravity="end|center_vertical"
|
android:progress="0"
|
||||||
android:progress="0"
|
android:progressDrawable="@drawable/circular_progress_bar"
|
||||||
android:visibility="visible" />
|
android:visibility="visible" />
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:nextFocusLeft="@id/episode_poster"
|
android:id="@+id/result_episode_download"
|
||||||
android:id="@+id/result_episode_download"
|
android:layout_width="50dp"
|
||||||
|
|
||||||
android:visibility="visible"
|
android:layout_height="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_gravity="center_vertical"
|
||||||
android:layout_gravity="center_vertical"
|
android:background="?selectableItemBackgroundBorderless"
|
||||||
android:padding="10dp"
|
android:contentDescription="@string/download"
|
||||||
android:layout_width="50dp"
|
android:nextFocusLeft="@id/episode_poster"
|
||||||
android:background="?selectableItemBackgroundBorderless"
|
android:padding="10dp"
|
||||||
android:src="@drawable/ic_baseline_play_arrow_24"
|
android:src="@drawable/ic_baseline_play_arrow_24"
|
||||||
android:contentDescription="@string/download"
|
android:visibility="visible"
|
||||||
app:tint="?attr/white" />
|
app:tint="?attr/white" />
|
||||||
</FrameLayout>
|
</FrameLayout>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:maxLines="4"
|
android:id="@+id/episode_descript"
|
||||||
android:ellipsize="end"
|
android:layout_width="match_parent"
|
||||||
android:paddingTop="10dp"
|
android:layout_height="wrap_content"
|
||||||
android:paddingBottom="10dp"
|
android:ellipsize="end"
|
||||||
android:id="@+id/episode_descript"
|
android:maxLines="4"
|
||||||
android:textColor="?attr/grayTextColor"
|
android:paddingTop="10dp"
|
||||||
tools:text="Jon and Daenerys arrive in Winterfell and are met with skepticism. Sam learns about the fate of his family. Cersei gives Euron the reward he aims for. Theon follows his heart. Jon and Daenerys arrive in Winterfell and are met with skepticism. Sam learns about the fate of his family. Cersei gives Euron the reward he aims for. Theon follows his heart."
|
android:paddingBottom="10dp"
|
||||||
android:layout_width="match_parent"
|
android:textColor="?attr/grayTextColor"
|
||||||
android:layout_height="wrap_content" />
|
tools:text="Jon and Daenerys arrive in Winterfell and are met with skepticism. Sam learns about the fate of his family. Cersei gives Euron the reward he aims for. Theon follows his heart. Jon and Daenerys arrive in Winterfell and are met with skepticism. Sam learns about the fate of his family. Cersei gives Euron the reward he aims for. Theon follows his heart." />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</androidx.cardview.widget.CardView>
|
</androidx.cardview.widget.CardView>
|
|
@ -6,5 +6,5 @@
|
||||||
android:requiresFadingEdge="horizontal"
|
android:requiresFadingEdge="horizontal"
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
|
||||||
<include layout="@layout/tvtypes_chips" />
|
<include layout="@layout/tvtypes_chips" android:id="@+id/tvtypes_chips" />
|
||||||
</HorizontalScrollView>
|
</HorizontalScrollView>
|
Loading…
Reference in a new issue