more views -> viewbinding

This commit is contained in:
LagradOst 2023-07-14 02:28:49 +02:00
parent 05a0d3cd81
commit 166a21f74e
19 changed files with 412 additions and 502 deletions

View File

@ -743,6 +743,7 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener {
window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN) window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN)
updateTv() updateTv()
if (isTvSettings()) { if (isTvSettings()) {
setContentView(R.layout.activity_main_tv) setContentView(R.layout.activity_main_tv)
} else { } else {

View File

@ -16,14 +16,16 @@ import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.AppCompatImageView import androidx.appcompat.widget.AppCompatImageView
import androidx.core.view.isVisible import androidx.core.view.isVisible
import com.lagradost.cloudstream3.R import com.lagradost.cloudstream3.R
import kotlinx.android.synthetic.main.activity_easter_egg_monke.* import com.lagradost.cloudstream3.databinding.ActivityEasterEggMonkeBinding
import java.util.*
class EasterEggMonke : AppCompatActivity() { class EasterEggMonke : AppCompatActivity() {
lateinit var binding : ActivityEasterEggMonkeBinding
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContentView(R.layout.activity_easter_egg_monke)
binding = ActivityEasterEggMonkeBinding.inflate(layoutInflater)
setContentView(binding.root)
val handler = Handler(mainLooper) val handler = Handler(mainLooper)
lateinit var runnable: Runnable lateinit var runnable: Runnable
@ -32,15 +34,14 @@ class EasterEggMonke : AppCompatActivity() {
handler.postDelayed(runnable, 300) handler.postDelayed(runnable, 300)
} }
handler.postDelayed(runnable, 1000) handler.postDelayed(runnable, 1000)
} }
private fun shower() { private fun shower() {
val containerW = frame.width val containerW = binding.frame.width
val containerH = frame.height val containerH = binding.frame.height
var starW: Float = monke.width.toFloat() var starW: Float = binding.monke.width.toFloat()
var starH: Float = monke.height.toFloat() var starH: Float = binding.monke.height.toFloat()
val newStar = AppCompatImageView(this) val newStar = AppCompatImageView(this)
val idx = (monkeys.size * Math.random()).toInt() val idx = (monkeys.size * Math.random()).toInt()
@ -48,7 +49,7 @@ class EasterEggMonke : AppCompatActivity() {
newStar.isVisible = true newStar.isVisible = true
newStar.layoutParams = FrameLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT, newStar.layoutParams = FrameLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT,
FrameLayout.LayoutParams.WRAP_CONTENT) FrameLayout.LayoutParams.WRAP_CONTENT)
frame.addView(newStar) binding.frame.addView(newStar)
newStar.scaleX = Math.random().toFloat() * 1.5f + newStar.scaleX newStar.scaleX = Math.random().toFloat() * 1.5f + newStar.scaleX
newStar.scaleY = newStar.scaleX newStar.scaleY = newStar.scaleX
@ -70,7 +71,7 @@ class EasterEggMonke : AppCompatActivity() {
set.addListener(object : AnimatorListenerAdapter() { set.addListener(object : AnimatorListenerAdapter() {
override fun onAnimationEnd(animation: Animator) { override fun onAnimationEnd(animation: Animator) {
frame.removeView(newStar) binding.frame.removeView(newStar)
} }
}) })

View File

@ -12,20 +12,23 @@ import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity import androidx.fragment.app.FragmentActivity
import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.findNavController
import com.lagradost.cloudstream3.MainActivity import com.lagradost.cloudstream3.MainActivity
import com.lagradost.cloudstream3.R
import com.lagradost.cloudstream3.USER_AGENT import com.lagradost.cloudstream3.USER_AGENT
import com.lagradost.cloudstream3.databinding.FragmentWebviewBinding
import com.lagradost.cloudstream3.network.WebViewResolver import com.lagradost.cloudstream3.network.WebViewResolver
import com.lagradost.cloudstream3.utils.AppUtils.loadRepository import com.lagradost.cloudstream3.utils.AppUtils.loadRepository
import kotlinx.android.synthetic.main.fragment_webview.*
class WebviewFragment : Fragment() { class WebviewFragment : Fragment() {
var binding: FragmentWebviewBinding? = null
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
val url = arguments?.getString(WEBVIEW_URL) ?: "".also { val url = arguments?.getString(WEBVIEW_URL) ?: "".also {
findNavController().popBackStack() findNavController().popBackStack()
} }
web_view.webViewClient = object : WebViewClient() { binding?.webView?.webViewClient = object : WebViewClient() {
override fun shouldOverrideUrlLoading( override fun shouldOverrideUrlLoading(
view: WebView?, view: WebView?,
request: WebResourceRequest? request: WebResourceRequest?
@ -40,24 +43,28 @@ class WebviewFragment : Fragment() {
return super.shouldOverrideUrlLoading(view, request) return super.shouldOverrideUrlLoading(view, request)
} }
} }
binding?.webView?.apply {
WebViewResolver.webViewUserAgent = settings.userAgentString
WebViewResolver.webViewUserAgent = web_view.settings.userAgentString addJavascriptInterface(RepoApi(activity), "RepoApi")
settings.javaScriptEnabled = true
web_view.addJavascriptInterface(RepoApi(activity), "RepoApi") settings.userAgentString = USER_AGENT
web_view.settings.javaScriptEnabled = true settings.domStorageEnabled = true
web_view.settings.userAgentString = USER_AGENT
web_view.settings.domStorageEnabled = true
// WebView.setWebContentsDebuggingEnabled(true) // WebView.setWebContentsDebuggingEnabled(true)
web_view.loadUrl(url) loadUrl(url)
}
} }
override fun onCreateView( override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle? savedInstanceState: Bundle?
): View? { ): View {
val localBinding = FragmentWebviewBinding.inflate(inflater, container, false)
binding = localBinding
// Inflate the layout for this fragment // Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_webview, container, false) return localBinding.root//inflater.inflate(R.layout.fragment_webview, container, false)
} }
companion object { companion object {
@ -70,7 +77,7 @@ class WebviewFragment : Fragment() {
private class RepoApi(val activity: FragmentActivity?) { private class RepoApi(val activity: FragmentActivity?) {
@JavascriptInterface @JavascriptInterface
fun installRepo(repoUrl: String) { fun installRepo(repoUrl: String) {
activity?.loadRepository(repoUrl) activity?.loadRepository(repoUrl)
} }
} }

View File

@ -3,18 +3,13 @@ package com.lagradost.cloudstream3.ui.download
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.cardview.widget.CardView
import androidx.core.widget.ContentLoadingProgressBar
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.lagradost.cloudstream3.R import com.lagradost.cloudstream3.databinding.DownloadChildEpisodeBinding
import com.lagradost.cloudstream3.utils.AppUtils.getNameFull import com.lagradost.cloudstream3.utils.AppUtils.getNameFull
import com.lagradost.cloudstream3.utils.DataStoreHelper.fixVisual import com.lagradost.cloudstream3.utils.DataStoreHelper.fixVisual
import com.lagradost.cloudstream3.utils.DataStoreHelper.getViewPos import com.lagradost.cloudstream3.utils.DataStoreHelper.getViewPos
import com.lagradost.cloudstream3.utils.VideoDownloadHelper import com.lagradost.cloudstream3.utils.VideoDownloadHelper
import kotlinx.android.synthetic.main.download_child_episode.view.* import java.util.Collections
import java.util.*
const val DOWNLOAD_ACTION_PLAY_FILE = 0 const val DOWNLOAD_ACTION_PLAY_FILE = 0
const val DOWNLOAD_ACTION_DELETE_FILE = 1 const val DOWNLOAD_ACTION_DELETE_FILE = 1
@ -68,7 +63,7 @@ class DownloadChildAdapter(
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
return DownloadChildViewHolder( return DownloadChildViewHolder(
LayoutInflater.from(parent.context).inflate(R.layout.download_child_episode, parent, false), DownloadChildEpisodeBinding.inflate(LayoutInflater.from(parent.context), parent, false),
clickCallback clickCallback
) )
} }
@ -88,17 +83,17 @@ class DownloadChildAdapter(
class DownloadChildViewHolder class DownloadChildViewHolder
constructor( constructor(
itemView: View, val binding: DownloadChildEpisodeBinding,
private val clickCallback: (DownloadClickEvent) -> Unit, private val clickCallback: (DownloadClickEvent) -> Unit,
) : RecyclerView.ViewHolder(itemView), DownloadButtonViewHolder { ) : RecyclerView.ViewHolder(binding.root), DownloadButtonViewHolder {
override var downloadButton = EasyDownloadButton() override var downloadButton = EasyDownloadButton()
private val title: TextView = itemView.download_child_episode_text /*private val title: TextView = itemView.download_child_episode_text
private val extraInfo: TextView = itemView.download_child_episode_text_extra private val extraInfo: TextView = itemView.download_child_episode_text_extra
private val holder: CardView = itemView.download_child_episode_holder private val holder: CardView = itemView.download_child_episode_holder
private val progressBar: ContentLoadingProgressBar = itemView.download_child_episode_progress private val progressBar: ContentLoadingProgressBar = itemView.download_child_episode_progress
private val progressBarDownload: ContentLoadingProgressBar = itemView.download_child_episode_progress_downloaded private val progressBarDownload: ContentLoadingProgressBar = itemView.download_child_episode_progress_downloaded
private val downloadImage: ImageView = itemView.download_child_episode_download private val downloadImage: ImageView = itemView.download_child_episode_download*/
private var localCard: VisualDownloadChildCached? = null private var localCard: VisualDownloadChildCached? = null
@ -107,29 +102,35 @@ class DownloadChildAdapter(
val d = card.data val d = card.data
val posDur = getViewPos(d.id) val posDur = getViewPos(d.id)
if (posDur != null) { binding.downloadChildEpisodeProgress.apply {
val visualPos = posDur.fixVisual() if (posDur != null) {
progressBar.max = (visualPos.duration / 1000).toInt() val visualPos = posDur.fixVisual()
progressBar.progress = (visualPos.position / 1000).toInt() max = (visualPos.duration / 1000).toInt()
progressBar.visibility = View.VISIBLE progress = (visualPos.position / 1000).toInt()
} else { visibility = View.VISIBLE
progressBar.visibility = View.GONE } else {
visibility = View.GONE
}
}
binding.downloadChildEpisodeText.apply {
text = context.getNameFull(d.name, d.episode, d.season)
isSelected = true // is needed for text repeating
} }
title.text = title.context.getNameFull(d.name, d.episode, d.season)
title.isSelected = true // is needed for text repeating
downloadButton.setUpButton( downloadButton.setUpButton(
card.currentBytes, card.currentBytes,
card.totalBytes, card.totalBytes,
progressBarDownload, binding.downloadChildEpisodeProgressDownloaded,
downloadImage, binding.downloadChildEpisodeDownload,
extraInfo, binding.downloadChildEpisodeTextExtra,
card.data, card.data,
clickCallback clickCallback
) )
holder.setOnClickListener { binding.downloadChildEpisodeHolder.setOnClickListener {
clickCallback.invoke(DownloadClickEvent(DOWNLOAD_ACTION_PLAY_FILE, d)) clickCallback.invoke(DownloadClickEvent(DOWNLOAD_ACTION_PLAY_FILE, d))
} }
} }
@ -141,9 +142,9 @@ class DownloadChildAdapter(
downloadButton.setUpButton( downloadButton.setUpButton(
card.currentBytes, card.currentBytes,
card.totalBytes, card.totalBytes,
progressBarDownload, binding.downloadChildEpisodeProgressDownloaded,
downloadImage, binding.downloadChildEpisodeDownload,
extraInfo, binding.downloadChildEpisodeTextExtra,
card.data, card.data,
clickCallback clickCallback
) )

View File

@ -5,16 +5,12 @@ import android.text.format.Formatter.formatShortFileSize
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.cardview.widget.CardView
import androidx.core.widget.ContentLoadingProgressBar
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.DownloadHeaderEpisodeBinding
import com.lagradost.cloudstream3.mvvm.logError import com.lagradost.cloudstream3.mvvm.logError
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 kotlinx.android.synthetic.main.download_header_episode.view.*
import java.util.* import java.util.*
data class VisualDownloadHeaderCached( data class VisualDownloadHeaderCached(
@ -66,7 +62,7 @@ class DownloadHeaderAdapter(
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
return DownloadHeaderViewHolder( return DownloadHeaderViewHolder(
LayoutInflater.from(parent.context).inflate(R.layout.download_header_episode, parent, false), DownloadHeaderEpisodeBinding.inflate(LayoutInflater.from(parent.context),parent,false),
clickCallback, clickCallback,
movieClickCallback movieClickCallback
) )
@ -87,20 +83,20 @@ class DownloadHeaderAdapter(
class DownloadHeaderViewHolder class DownloadHeaderViewHolder
constructor( constructor(
itemView: View, val binding: DownloadHeaderEpisodeBinding,
private val clickCallback: (DownloadHeaderClickEvent) -> Unit, private val clickCallback: (DownloadHeaderClickEvent) -> Unit,
private val movieClickCallback: (DownloadClickEvent) -> Unit, private val movieClickCallback: (DownloadClickEvent) -> Unit,
) : RecyclerView.ViewHolder(itemView), DownloadButtonViewHolder { ) : RecyclerView.ViewHolder(binding.root), DownloadButtonViewHolder {
override var downloadButton = EasyDownloadButton() override var downloadButton = EasyDownloadButton()
private val poster: ImageView? = itemView.download_header_poster /*private val poster: ImageView? = itemView.download_header_poster
private val title: TextView = itemView.download_header_title private val title: TextView = itemView.download_header_title
private val extraInfo: TextView = itemView.download_header_info private val extraInfo: TextView = itemView.download_header_info
private val holder: CardView = itemView.episode_holder private val holder: CardView = itemView.episode_holder
private val downloadBar: ContentLoadingProgressBar = itemView.download_header_progress_downloaded private val downloadBar: ContentLoadingProgressBar = itemView.download_header_progress_downloaded
private val downloadImage: ImageView = itemView.download_header_episode_download private val downloadImage: ImageView = itemView.download_header_episode_download
private val normalImage: ImageView = itemView.download_header_goto_child private val normalImage: ImageView = itemView.download_header_goto_child*/
private var localCard: VisualDownloadHeaderCached? = null private var localCard: VisualDownloadHeaderCached? = null
@SuppressLint("SetTextI18n") @SuppressLint("SetTextI18n")
@ -108,19 +104,24 @@ class DownloadHeaderAdapter(
localCard = card localCard = card
val d = card.data val d = card.data
poster?.setImage(d.poster) binding.downloadHeaderPoster.apply {
poster?.setOnClickListener { setImage(d.poster)
clickCallback.invoke(DownloadHeaderClickEvent(1, d)) setOnClickListener {
clickCallback.invoke(DownloadHeaderClickEvent(1, d))
}
} }
title.text = d.name binding.apply {
binding.downloadHeaderTitle.text = d.name
val mbString = formatShortFileSize(itemView.context, card.totalBytes) val mbString = formatShortFileSize(itemView.context, card.totalBytes)
//val isMovie = d.type.isMovieType() //val isMovie = d.type.isMovieType()
if (card.child != null) { if (card.child != null) {
downloadBar.visibility = View.VISIBLE downloadHeaderProgressDownloaded.visibility = View.VISIBLE
downloadImage.visibility = View.VISIBLE
normalImage.visibility = View.GONE downloadHeaderEpisodeDownload.visibility = View.VISIBLE
binding.downloadHeaderGotoChild.visibility = View.GONE
/*setUpButton( /*setUpButton(
card.currentBytes, card.currentBytes,
card.totalBytes, card.totalBytes,
@ -131,34 +132,35 @@ class DownloadHeaderAdapter(
movieClickCallback movieClickCallback
)*/ )*/
holder.setOnClickListener { episodeHolder.setOnClickListener {
movieClickCallback.invoke(DownloadClickEvent(DOWNLOAD_ACTION_PLAY_FILE, card.child)) movieClickCallback.invoke(DownloadClickEvent(DOWNLOAD_ACTION_PLAY_FILE, card.child))
} }
} else { } else {
downloadBar.visibility = View.GONE downloadHeaderProgressDownloaded.visibility = View.GONE
downloadImage.visibility = View.GONE downloadHeaderEpisodeDownload.visibility = View.GONE
normalImage.visibility = View.VISIBLE binding.downloadHeaderGotoChild.visibility = View.VISIBLE
try { try {
extraInfo.text = downloadHeaderInfo.text =
extraInfo.context.getString(R.string.extra_info_format).format( downloadHeaderInfo.context.getString(R.string.extra_info_format).format(
card.totalDownloads, card.totalDownloads,
if (card.totalDownloads == 1) extraInfo.context.getString(R.string.episode) else extraInfo.context.getString( if (card.totalDownloads == 1) downloadHeaderInfo.context.getString(R.string.episode) else downloadHeaderInfo.context.getString(
R.string.episodes R.string.episodes
), ),
mbString mbString
) )
} catch (t : Throwable) { } catch (t : Throwable) {
// you probably formatted incorrectly // you probably formatted incorrectly
extraInfo.text = "Error" downloadHeaderInfo.text = "Error"
logError(t) logError(t)
} }
holder.setOnClickListener { episodeHolder.setOnClickListener {
clickCallback.invoke(DownloadHeaderClickEvent(0, d)) clickCallback.invoke(DownloadHeaderClickEvent(0, d))
} }
} }
}
} }
override fun reattachDownloadButton() { override fun reattachDownloadButton() {
@ -168,9 +170,9 @@ class DownloadHeaderAdapter(
downloadButton.setUpButton( downloadButton.setUpButton(
card.currentBytes, card.currentBytes,
card.totalBytes, card.totalBytes,
downloadBar, binding.downloadHeaderProgressDownloaded,
downloadImage, binding.downloadHeaderEpisodeDownload,
extraInfo, binding.downloadHeaderInfo,
card.child, card.child,
movieClickCallback movieClickCallback
) )

View File

@ -3,49 +3,24 @@ package com.lagradost.cloudstream3.ui.home
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.FrameLayout
import android.widget.LinearLayout
import android.widget.TextView import android.widget.TextView
import androidx.core.content.ContextCompat
import androidx.core.view.isGone
import androidx.core.view.isVisible
import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListUpdateCallback import androidx.recyclerview.widget.ListUpdateCallback
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import androidx.transition.ChangeBounds
import androidx.transition.TransitionManager
import androidx.viewpager2.widget.ViewPager2
import com.google.android.material.chip.Chip
import com.google.android.material.chip.ChipDrawable
import com.lagradost.cloudstream3.APIHolder.getId
import com.lagradost.cloudstream3.AcraApplication.Companion.getActivity
import com.lagradost.cloudstream3.HomePageList import com.lagradost.cloudstream3.HomePageList
import com.lagradost.cloudstream3.LoadResponse import com.lagradost.cloudstream3.LoadResponse
import com.lagradost.cloudstream3.R import com.lagradost.cloudstream3.R
import com.lagradost.cloudstream3.SearchResponse
import com.lagradost.cloudstream3.mvvm.Resource
import com.lagradost.cloudstream3.ui.WatchType
import com.lagradost.cloudstream3.ui.result.LinearListLayout
import com.lagradost.cloudstream3.ui.result.ResultViewModel2
import com.lagradost.cloudstream3.ui.result.START_ACTION_RESUME_LATEST
import com.lagradost.cloudstream3.ui.result.setLinearListLayout import com.lagradost.cloudstream3.ui.result.setLinearListLayout
import com.lagradost.cloudstream3.ui.search.SEARCH_ACTION_LOAD
import com.lagradost.cloudstream3.ui.search.SearchClickCallback import com.lagradost.cloudstream3.ui.search.SearchClickCallback
import com.lagradost.cloudstream3.ui.search.SearchFragment.Companion.filterSearchResponse import com.lagradost.cloudstream3.ui.search.SearchFragment.Companion.filterSearchResponse
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTvSettings import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTvSettings
import com.lagradost.cloudstream3.utils.AppUtils.isRecyclerScrollable import com.lagradost.cloudstream3.utils.AppUtils.isRecyclerScrollable
import com.lagradost.cloudstream3.utils.AppUtils.loadResult
import com.lagradost.cloudstream3.utils.DataStoreHelper
import com.lagradost.cloudstream3.utils.SingleSelectionHelper.showBottomDialog
import com.lagradost.cloudstream3.utils.UIHelper.fixPaddingStatusbarView
import kotlinx.android.synthetic.main.activity_main_tv.* import kotlinx.android.synthetic.main.activity_main_tv.*
import kotlinx.android.synthetic.main.activity_main_tv.view.* import kotlinx.android.synthetic.main.activity_main_tv.view.*
import kotlinx.android.synthetic.main.fragment_home.* import kotlinx.android.synthetic.main.fragment_home.*
import kotlinx.android.synthetic.main.fragment_home.view.* import kotlinx.android.synthetic.main.fragment_home.view.*
import kotlinx.android.synthetic.main.fragment_home_head_tv.* import kotlinx.android.synthetic.main.fragment_home_head_tv.*
import kotlinx.android.synthetic.main.fragment_home_head_tv.view.* import kotlinx.android.synthetic.main.fragment_home_head_tv.view.*
import kotlinx.android.synthetic.main.fragment_home_head_tv.view.home_preview
import kotlinx.android.synthetic.main.fragment_home_head_tv.view.home_preview_viewpager
import kotlinx.android.synthetic.main.homepage_parent.view.* import kotlinx.android.synthetic.main.homepage_parent.view.*
class LoadClickCallback( class LoadClickCallback(

View File

@ -5,15 +5,7 @@ import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.BaseAdapter import android.widget.BaseAdapter
import android.widget.FrameLayout
import android.widget.LinearLayout
import android.widget.ListPopupWindow.MATCH_PARENT
import android.widget.RelativeLayout
import com.lagradost.cloudstream3.R import com.lagradost.cloudstream3.R
import com.lagradost.cloudstream3.utils.UIHelper.toPx
import kotlinx.android.synthetic.main.loading_poster_dynamic.view.*
import kotlin.math.roundToInt
import kotlin.math.sqrt
class LoadingPosterAdapter(context: Context, private val itemCount: Int) : class LoadingPosterAdapter(context: Context, private val itemCount: Int) :
BaseAdapter() { BaseAdapter() {

View File

@ -97,12 +97,6 @@ open class FullScreenPlayer : AbstractPlayerFragment() {
protected var isShowing = false protected var isShowing = false
protected var isLocked = false protected var isLocked = false
//private var episodes: List<Any> = listOf()
protected fun setEpisodes(ep: List<Any>) {
//hasEpisodes = ep.size > 1 // if has 2 episodes or more because you dont want to switch to your current episode
//(player_episode_list?.adapter as? PlayerEpisodeAdapter?)?.updateList(ep)
}
protected var hasEpisodes = false protected var hasEpisodes = false
private set private set
//protected val hasEpisodes //protected val hasEpisodes

View File

@ -163,7 +163,7 @@ class GeneratorPlayer : FullScreenPlayer() {
currentSelectedLink = link currentSelectedLink = link
currentMeta = viewModel.getMeta() currentMeta = viewModel.getMeta()
nextMeta = viewModel.getNextMeta() nextMeta = viewModel.getNextMeta()
setEpisodes(viewModel.getAllMeta() ?: emptyList()) // setEpisodes(viewModel.getAllMeta() ?: emptyList())
isActive = true isActive = true
setPlayerDimen(null) setPlayerDimen(null)
setTitle() setTitle()

View File

@ -1,158 +0,0 @@
package com.lagradost.cloudstream3.ui.player
import android.annotation.SuppressLint
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import androidx.core.view.isGone
import androidx.core.view.isVisible
import androidx.core.widget.ContentLoadingProgressBar
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.button.MaterialButton
import com.lagradost.cloudstream3.R
import com.lagradost.cloudstream3.ui.result.ResultEpisode
import com.lagradost.cloudstream3.ui.result.getDisplayPosition
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTrueTvSettings
import com.lagradost.cloudstream3.utils.AppUtils.html
import com.lagradost.cloudstream3.utils.UIHelper.setImage
import kotlinx.android.synthetic.main.player_episodes_large.view.episode_holder_large
import kotlinx.android.synthetic.main.player_episodes_large.view.episode_progress
import kotlinx.android.synthetic.main.player_episodes_small.view.episode_holder
import kotlinx.android.synthetic.main.result_episode_large.view.*
data class PlayerEpisodeClickEvent(val action: Int, val data: Any)
class PlayerEpisodeAdapter(
private val items: MutableList<Any> = mutableListOf(),
private val clickCallback: (PlayerEpisodeClickEvent) -> Unit,
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
return PlayerEpisodeCardViewHolder(
LayoutInflater.from(parent.context)
.inflate(R.layout.player_episodes, parent, false),
clickCallback,
)
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
println("HOLDER $holder $position")
when (holder) {
is PlayerEpisodeCardViewHolder -> {
holder.bind(items[position])
}
}
}
override fun getItemCount(): Int {
return items.size
}
fun updateList(newList: List<Any>) {
println("Updated list $newList")
val diffResult = DiffUtil.calculateDiff(EpisodeDiffCallback(this.items, newList))
items.clear()
items.addAll(newList)
diffResult.dispatchUpdatesTo(this)
}
class PlayerEpisodeCardViewHolder
constructor(
itemView: View,
private val clickCallback: (PlayerEpisodeClickEvent) -> Unit,
) : RecyclerView.ViewHolder(itemView) {
@SuppressLint("SetTextI18n")
fun bind(card: Any) {
if (card is ResultEpisode) {
val (parentView, otherView) = if (card.poster == null) {
itemView.episode_holder to itemView.episode_holder_large
} else {
itemView.episode_holder_large to itemView.episode_holder
}
val episodeText: TextView? = parentView.episode_text
val episodeFiller: MaterialButton? = parentView.episode_filler
val episodeRating: TextView? = parentView.episode_rating
val episodeDescript: TextView? = parentView.episode_descript
val episodeProgress: ContentLoadingProgressBar? = parentView.episode_progress
val episodePoster: ImageView? = parentView.episode_poster
parentView.isVisible = true
otherView.isVisible = false
episodeText?.apply {
val name =
if (card.name == null) "${context.getString(R.string.episode)} ${card.episode}" else "${card.episode}. ${card.name}"
text = name
isSelected = true
}
episodeFiller?.isVisible = card.isFiller == true
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(PlayerEpisodeClickEvent(ACTION_SHOW_DESCRIPTION, card))
//}
}
parentView.setOnClickListener {
clickCallback.invoke(PlayerEpisodeClickEvent(0, card))
}
if (isTrueTvSettings()) {
parentView.isFocusable = true
parentView.isFocusableInTouchMode = true
parentView.touchscreenBlocksFocus = false
}
}
}
}
}
class EpisodeDiffCallback(
private val oldList: List<Any>,
private val newList: List<Any>
) :
DiffUtil.Callback() {
override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
val a = oldList[oldItemPosition]
val b = newList[newItemPosition]
return if (a is ResultEpisode && b is ResultEpisode) {
a.id == b.id
} else {
a == b
}
}
override fun getOldListSize() = oldList.size
override fun getNewListSize() = newList.size
override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int) =
oldList[oldItemPosition] == newList[newItemPosition]
}

View File

@ -4,16 +4,15 @@ import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.FrameLayout import android.widget.FrameLayout
import android.widget.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.R import androidx.viewbinding.ViewBinding
import com.lagradost.cloudstream3.SearchResponse import com.lagradost.cloudstream3.SearchResponse
import com.lagradost.cloudstream3.databinding.SearchResultGridBinding
import com.lagradost.cloudstream3.databinding.SearchResultGridExpandedBinding
import com.lagradost.cloudstream3.ui.AutofitRecyclerView import com.lagradost.cloudstream3.ui.AutofitRecyclerView
import com.lagradost.cloudstream3.utils.Coroutines.main
import com.lagradost.cloudstream3.utils.UIHelper.IsBottomLayout import com.lagradost.cloudstream3.utils.UIHelper.IsBottomLayout
import com.lagradost.cloudstream3.utils.UIHelper.toPx import com.lagradost.cloudstream3.utils.UIHelper.toPx
import kotlinx.android.synthetic.main.search_result_compact.view.*
import kotlin.math.roundToInt import kotlin.math.roundToInt
/** Click */ /** Click */
@ -39,10 +38,23 @@ class SearchAdapter(
var hasNext: Boolean = false var hasNext: Boolean = false
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
val layout = val layout =
if (parent.context.IsBottomLayout()) R.layout.search_result_grid_expanded else R.layout.search_result_grid if (parent.context.IsBottomLayout()) SearchResultGridExpandedBinding.inflate(
LayoutInflater.from(parent.context),
parent,
false
) else SearchResultGridBinding.inflate(
LayoutInflater.from(parent.context),
parent,
false
) //R.layout.search_result_grid_expanded else R.layout.search_result_grid
return CardViewHolder( return CardViewHolder(
LayoutInflater.from(parent.context).inflate(layout, parent, false), layout,
clickCallback, clickCallback,
resView resView
) )
@ -73,12 +85,11 @@ class SearchAdapter(
class CardViewHolder class CardViewHolder
constructor( constructor(
itemView: View, val binding: ViewBinding,
private val clickCallback: (SearchClickCallback) -> Unit, private val clickCallback: (SearchClickCallback) -> Unit,
resView: AutofitRecyclerView resView: AutofitRecyclerView
) : ) :
RecyclerView.ViewHolder(itemView) { RecyclerView.ViewHolder(binding.root) {
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 =
@ -86,7 +97,7 @@ class SearchAdapter(
fun bind(card: SearchResponse, position: Int) { fun bind(card: SearchResponse, position: Int) {
if (!compactView) { if (!compactView) {
cardView.apply { binding.root.apply {
layoutParams = FrameLayout.LayoutParams( layoutParams = FrameLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT,
coverHeight coverHeight

View File

@ -104,6 +104,7 @@ class SearchFragment : Fragment() {
val layout = 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
val root = inflater.inflate(layout, container, false) val root = inflater.inflate(layout, container, false)
// TODO TRYCATCH
binding = FragmentSearchBinding.bind(root) binding = FragmentSearchBinding.bind(root)
return root return root

View File

@ -15,6 +15,9 @@ import androidx.recyclerview.widget.RecyclerView
import com.lagradost.cloudstream3.AcraApplication.Companion.openBrowser import com.lagradost.cloudstream3.AcraApplication.Companion.openBrowser
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.AccountManagmentBinding
import com.lagradost.cloudstream3.databinding.AccountSwitchBinding
import com.lagradost.cloudstream3.databinding.AddAccountInputBinding
import com.lagradost.cloudstream3.mvvm.logError import com.lagradost.cloudstream3.mvvm.logError
import com.lagradost.cloudstream3.syncproviders.AccountManager import com.lagradost.cloudstream3.syncproviders.AccountManager
import com.lagradost.cloudstream3.syncproviders.AccountManager.Companion.aniListApi import com.lagradost.cloudstream3.syncproviders.AccountManager.Companion.aniListApi
@ -31,9 +34,6 @@ import com.lagradost.cloudstream3.utils.Coroutines.ioSafe
import com.lagradost.cloudstream3.utils.UIHelper.dismissSafe import com.lagradost.cloudstream3.utils.UIHelper.dismissSafe
import com.lagradost.cloudstream3.utils.UIHelper.hideKeyboard import com.lagradost.cloudstream3.utils.UIHelper.hideKeyboard
import com.lagradost.cloudstream3.utils.UIHelper.setImage import com.lagradost.cloudstream3.utils.UIHelper.setImage
import kotlinx.android.synthetic.main.account_managment.*
import kotlinx.android.synthetic.main.account_switch.*
import kotlinx.android.synthetic.main.add_account_input.*
class SettingsAccount : PreferenceFragmentCompat() { class SettingsAccount : PreferenceFragmentCompat() {
companion object { companion object {
@ -43,15 +43,18 @@ class SettingsAccount : PreferenceFragmentCompat() {
api: AccountManager, api: AccountManager,
info: AuthAPI.LoginInfo info: AuthAPI.LoginInfo
) { ) {
if (activity == null) return
val binding: AccountManagmentBinding =
AccountManagmentBinding.inflate(activity.layoutInflater, null, false)
val builder = val builder =
AlertDialog.Builder(activity ?: return, R.style.AlertDialogCustom) AlertDialog.Builder(activity, R.style.AlertDialogCustom)
.setView(R.layout.account_managment) .setView(binding.root)
val dialog = builder.show() val dialog = builder.show()
dialog.account_main_profile_picture_holder?.isVisible = binding.accountMainProfilePictureHolder.isVisible =
dialog.account_main_profile_picture?.setImage(info.profilePicture) == true binding.accountMainProfilePicture.setImage(info.profilePicture)
dialog.account_logout?.setOnClickListener { binding.accountLogout.setOnClickListener {
api.logOut() api.logOut()
dialog.dismissSafe(activity) dialog.dismissSafe(activity)
} }
@ -60,26 +63,28 @@ class SettingsAccount : PreferenceFragmentCompat() {
dialog.findViewById<TextView>(R.id.account_name)?.text = it dialog.findViewById<TextView>(R.id.account_name)?.text = it
} }
dialog.account_site?.text = api.name binding.accountSite.text = api.name
dialog.account_switch_account?.setOnClickListener { binding.accountSwitchAccount.setOnClickListener {
dialog.dismissSafe(activity) dialog.dismissSafe(activity)
showAccountSwitch(activity, api) showAccountSwitch(activity, api)
} }
if (isTvSettings()) { if (isTvSettings()) {
dialog.account_switch_account?.requestFocus() binding.accountSwitchAccount.requestFocus()
} }
} }
fun showAccountSwitch(activity: FragmentActivity, api: AccountManager) { private fun showAccountSwitch(activity: FragmentActivity, api: AccountManager) {
val accounts = api.getAccounts() ?: return val accounts = api.getAccounts() ?: return
val binding: AccountSwitchBinding =
AccountSwitchBinding.inflate(activity.layoutInflater, null, false)
val builder = val builder =
AlertDialog.Builder(activity, R.style.AlertDialogCustom) AlertDialog.Builder(activity, R.style.AlertDialogCustom)
.setView(R.layout.account_switch) .setView(binding.root)
val dialog = builder.show() val dialog = builder.show()
dialog.account_add?.setOnClickListener { binding.accountAdd.setOnClickListener {
addAccount(activity, api) addAccount(activity, api)
dialog?.dismissSafe(activity) dialog?.dismissSafe(activity)
} }
@ -111,17 +116,21 @@ class SettingsAccount : PreferenceFragmentCompat() {
is OAuth2API -> { is OAuth2API -> {
api.authenticate(activity) api.authenticate(activity)
} }
is InAppAuthAPI -> { is InAppAuthAPI -> {
if (activity == null) return
val binding: AddAccountInputBinding =
AddAccountInputBinding.inflate(activity.layoutInflater, null, false)
val builder = val builder =
AlertDialog.Builder(activity ?: return, R.style.AlertDialogCustom) AlertDialog.Builder(activity, R.style.AlertDialogCustom)
.setView(R.layout.add_account_input) .setView(binding.root)
val dialog = builder.show() val dialog = builder.show()
val visibilityMap = mapOf( val visibilityMap = listOf(
dialog.login_email_input to api.requiresEmail, binding.loginEmailInput to api.requiresEmail,
dialog.login_password_input to api.requiresPassword, binding.loginPasswordInput to api.requiresPassword,
dialog.login_server_input to api.requiresServer, binding.loginServerInput to api.requiresServer,
dialog.login_username_input to api.requiresUsername binding.loginUsernameInput to api.requiresUsername
) )
if (isTvSettings()) { if (isTvSettings()) {
@ -145,12 +154,12 @@ class SettingsAccount : PreferenceFragmentCompat() {
} }
} }
dialog.login_email_input?.isVisible = api.requiresEmail binding.loginEmailInput.isVisible = api.requiresEmail
dialog.login_password_input?.isVisible = api.requiresPassword binding.loginPasswordInput.isVisible = api.requiresPassword
dialog.login_server_input?.isVisible = api.requiresServer binding.loginServerInput.isVisible = api.requiresServer
dialog.login_username_input?.isVisible = api.requiresUsername binding.loginUsernameInput.isVisible = api.requiresUsername
dialog.create_account?.isGone = api.createAccountUrl.isNullOrBlank() binding.createAccount.isGone = api.createAccountUrl.isNullOrBlank()
dialog.create_account?.setOnClickListener { binding.createAccount.setOnClickListener {
openBrowser( openBrowser(
api.createAccountUrl ?: return@setOnClickListener, api.createAccountUrl ?: return@setOnClickListener,
activity activity
@ -159,43 +168,43 @@ class SettingsAccount : PreferenceFragmentCompat() {
} }
val displayedItems = listOf( val displayedItems = listOf(
dialog.login_username_input, binding.loginUsernameInput,
dialog.login_email_input, binding.loginEmailInput,
dialog.login_server_input, binding.loginServerInput,
dialog.login_password_input binding.loginPasswordInput
).filter { it.isVisible } ).filter { it.isVisible }
displayedItems.foldRight(displayedItems.firstOrNull()) { item, previous -> displayedItems.foldRight(displayedItems.firstOrNull()) { item, previous ->
item?.id?.let { previous?.nextFocusDownId = it } item.id.let { previous?.nextFocusDownId = it }
previous?.id?.let { item?.nextFocusUpId = it } previous?.id?.let { item.nextFocusUpId = it }
item item
} }
displayedItems.firstOrNull()?.let { displayedItems.firstOrNull()?.let {
dialog.create_account?.nextFocusDownId = it.id binding.createAccount.nextFocusDownId = it.id
it.nextFocusUpId = dialog.create_account.id it.nextFocusUpId = binding.createAccount.id
} }
dialog.apply_btt?.id?.let { binding.applyBtt.id.let {
displayedItems.lastOrNull()?.nextFocusDownId = it displayedItems.lastOrNull()?.nextFocusDownId = it
} }
dialog.text1?.text = api.name binding.text1.text = api.name
if (api.storesPasswordInPlainText) { if (api.storesPasswordInPlainText) {
api.getLatestLoginData()?.let { data -> api.getLatestLoginData()?.let { data ->
dialog.login_email_input?.setText(data.email ?: "") binding.loginEmailInput.setText(data.email ?: "")
dialog.login_server_input?.setText(data.server ?: "") binding.loginServerInput.setText(data.server ?: "")
dialog.login_username_input?.setText(data.username ?: "") binding.loginUsernameInput.setText(data.username ?: "")
dialog.login_password_input?.setText(data.password ?: "") binding.loginPasswordInput.setText(data.password ?: "")
} }
} }
dialog.apply_btt?.setOnClickListener { binding.applyBtt.setOnClickListener {
val loginData = InAppAuthAPI.LoginData( val loginData = InAppAuthAPI.LoginData(
username = if (api.requiresUsername) dialog.login_username_input?.text?.toString() else null, username = if (api.requiresUsername) binding.loginUsernameInput.text?.toString() else null,
password = if (api.requiresPassword) dialog.login_password_input?.text?.toString() else null, password = if (api.requiresPassword) binding.loginPasswordInput.text?.toString() else null,
email = if (api.requiresEmail) dialog.login_email_input?.text?.toString() else null, email = if (api.requiresEmail) binding.loginEmailInput.text?.toString() else null,
server = if (api.requiresServer) dialog.login_server_input?.text?.toString() else null, server = if (api.requiresServer) binding.loginServerInput.text?.toString() else null,
) )
ioSafe { ioSafe {
val isSuccessful = try { val isSuccessful = try {
@ -220,10 +229,11 @@ class SettingsAccount : PreferenceFragmentCompat() {
} }
dialog.dismissSafe(activity) dialog.dismissSafe(activity)
} }
dialog.cancel_btt?.setOnClickListener { binding.cancelBtt.setOnClickListener {
dialog.dismissSafe(activity) dialog.dismissSafe(activity)
} }
} }
else -> { else -> {
throw NotImplementedError("You are trying to add an account that has an unknown login method") throw NotImplementedError("You are trying to add an account that has an unknown login method")
} }

View File

@ -14,7 +14,9 @@ import androidx.fragment.app.Fragment
import androidx.preference.Preference import androidx.preference.Preference
import androidx.preference.PreferenceFragmentCompat import androidx.preference.PreferenceFragmentCompat
import androidx.preference.PreferenceManager import androidx.preference.PreferenceManager
import com.google.android.material.appbar.MaterialToolbar
import com.lagradost.cloudstream3.R import com.lagradost.cloudstream3.R
import com.lagradost.cloudstream3.databinding.MainSettingsBinding
import com.lagradost.cloudstream3.mvvm.logError import com.lagradost.cloudstream3.mvvm.logError
import com.lagradost.cloudstream3.syncproviders.AccountManager.Companion.accountManagers import com.lagradost.cloudstream3.syncproviders.AccountManager.Companion.accountManagers
import com.lagradost.cloudstream3.ui.home.HomeFragment import com.lagradost.cloudstream3.ui.home.HomeFragment
@ -22,16 +24,14 @@ import com.lagradost.cloudstream3.utils.UIHelper.fixPaddingStatusbar
import com.lagradost.cloudstream3.utils.UIHelper.navigate import com.lagradost.cloudstream3.utils.UIHelper.navigate
import com.lagradost.cloudstream3.utils.UIHelper.setImage import com.lagradost.cloudstream3.utils.UIHelper.setImage
import com.lagradost.cloudstream3.utils.UIHelper.toPx import com.lagradost.cloudstream3.utils.UIHelper.toPx
import kotlinx.android.synthetic.main.main_settings.*
import kotlinx.android.synthetic.main.standard_toolbar.*
import java.io.File import java.io.File
class SettingsFragment : Fragment() { class SettingsFragment : Fragment() {
companion object { companion object {
var beneneCount = 0 var beneneCount = 0
private var isTv : Boolean = false private var isTv: Boolean = false
private var isTrueTv : Boolean = false private var isTrueTv: Boolean = false
fun PreferenceFragmentCompat?.getPref(id: Int): Preference? { fun PreferenceFragmentCompat?.getPref(id: Int): Preference? {
if (this == null) return null if (this == null) return null
@ -55,26 +55,30 @@ class SettingsFragment : Fragment() {
fun Fragment?.setUpToolbar(title: String) { fun Fragment?.setUpToolbar(title: String) {
if (this == null) return if (this == null) return
settings_toolbar?.apply { val settingsToolbar = view?.findViewById<MaterialToolbar>(R.id.settings_toolbar) ?: return
settingsToolbar.apply {
setTitle(title) setTitle(title)
setNavigationIcon(R.drawable.ic_baseline_arrow_back_24) setNavigationIcon(R.drawable.ic_baseline_arrow_back_24)
setNavigationOnClickListener { setNavigationOnClickListener {
activity?.onBackPressed() activity?.onBackPressed()
} }
} }
fixPaddingStatusbar(settings_toolbar) fixPaddingStatusbar(settingsToolbar)
} }
fun Fragment?.setUpToolbar(@StringRes title: Int) { fun Fragment?.setUpToolbar(@StringRes title: Int) {
if (this == null) return if (this == null) return
settings_toolbar?.apply { val settingsToolbar = view?.findViewById<MaterialToolbar>(R.id.settings_toolbar) ?: return
settingsToolbar.apply {
setTitle(title) setTitle(title)
setNavigationIcon(R.drawable.ic_baseline_arrow_back_24) setNavigationIcon(R.drawable.ic_baseline_arrow_back_24)
setNavigationOnClickListener { setNavigationOnClickListener {
activity?.onBackPressed() activity?.onBackPressed()
} }
} }
fixPaddingStatusbar(settings_toolbar) fixPaddingStatusbar(settingsToolbar)
} }
fun getFolderSize(dir: File): Long { fun getFolderSize(dir: File): Long {
@ -139,12 +143,21 @@ class SettingsFragment : Fragment() {
} }
} }
override fun onDestroyView() {
binding = null
super.onDestroyView()
}
var binding: MainSettingsBinding? = 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.main_settings, container, false) val localBinding = MainSettingsBinding.inflate(inflater, container, false)
binding = localBinding
return localBinding.root
//return inflater.inflate(R.layout.main_settings, container, false)
} }
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
@ -157,36 +170,34 @@ class SettingsFragment : Fragment() {
for (syncApi in accountManagers) { for (syncApi in accountManagers) {
val login = syncApi.loginInfo() val login = syncApi.loginInfo()
val pic = login?.profilePicture ?: continue val pic = login?.profilePicture ?: continue
if (settings_profile_pic?.setImage( if (binding?.settingsProfilePic?.setImage(
pic, pic,
errorImageDrawable = HomeFragment.errorProfilePic errorImageDrawable = HomeFragment.errorProfilePic
) == true ) == true
) { ) {
settings_profile_text?.text = login.name binding?.settingsProfileText?.text = login.name
settings_profile?.isVisible = true binding?.settingsProfile?.isVisible = true
break break
} }
} }
binding?.apply {
listOf( listOf(
Pair(settings_general, R.id.action_navigation_settings_to_navigation_settings_general), settingsGeneral to R.id.action_navigation_settings_to_navigation_settings_general,
Pair(settings_player, R.id.action_navigation_settings_to_navigation_settings_player), settingsPlayer to R.id.action_navigation_settings_to_navigation_settings_player,
Pair(settings_credits, R.id.action_navigation_settings_to_navigation_settings_account), settingsCredits to R.id.action_navigation_settings_to_navigation_settings_account,
Pair(settings_ui, R.id.action_navigation_settings_to_navigation_settings_ui), settingsUi to R.id.action_navigation_settings_to_navigation_settings_ui,
Pair(settings_providers, R.id.action_navigation_settings_to_navigation_settings_providers), settingsProviders to R.id.action_navigation_settings_to_navigation_settings_providers,
Pair(settings_updates, R.id.action_navigation_settings_to_navigation_settings_updates), settingsUpdates to R.id.action_navigation_settings_to_navigation_settings_updates,
Pair( settingsExtensions to R.id.action_navigation_settings_to_navigation_settings_extensions,
settings_extensions, ).forEach { (view, navigationId) ->
R.id.action_navigation_settings_to_navigation_settings_extensions view.apply {
), setOnClickListener {
).forEach { (view, navigationId) -> navigate(navigationId)
view?.apply { }
setOnClickListener { if (isTrueTv) {
navigate(navigationId) isFocusable = true
} isFocusableInTouchMode = true
if (isTrueTv) { }
isFocusable = true
isFocusableInTouchMode = true
} }
} }
} }

View File

@ -22,6 +22,8 @@ import com.lagradost.cloudstream3.CommonActivity
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.app import com.lagradost.cloudstream3.app
import com.lagradost.cloudstream3.databinding.AddRemoveSitesBinding
import com.lagradost.cloudstream3.databinding.AddSiteInputBinding
import com.lagradost.cloudstream3.mvvm.logError import com.lagradost.cloudstream3.mvvm.logError
import com.lagradost.cloudstream3.mvvm.normalSafeApiCall import com.lagradost.cloudstream3.mvvm.normalSafeApiCall
import com.lagradost.cloudstream3.network.initClient import com.lagradost.cloudstream3.network.initClient
@ -38,8 +40,6 @@ import com.lagradost.cloudstream3.utils.UIHelper.hideKeyboard
import com.lagradost.cloudstream3.utils.USER_PROVIDER_API import com.lagradost.cloudstream3.utils.USER_PROVIDER_API
import com.lagradost.cloudstream3.utils.VideoDownloadManager import com.lagradost.cloudstream3.utils.VideoDownloadManager
import com.lagradost.cloudstream3.utils.VideoDownloadManager.getBasePath import com.lagradost.cloudstream3.utils.VideoDownloadManager.getBasePath
import kotlinx.android.synthetic.main.add_remove_sites.*
import kotlinx.android.synthetic.main.add_site_input.*
import java.io.File import java.io.File
fun getCurrentLocale(context: Context): String { fun getCurrentLocale(context: Context): String {
@ -197,18 +197,20 @@ class SettingsGeneral : PreferenceFragmentCompat() {
{}) { selection -> {}) { selection ->
val provider = providers.getOrNull(selection) ?: return@showDialog val provider = providers.getOrNull(selection) ?: return@showDialog
val binding : AddSiteInputBinding = AddSiteInputBinding.inflate(layoutInflater,null,false)
val builder = val builder =
AlertDialog.Builder(context ?: return@showDialog, R.style.AlertDialogCustom) AlertDialog.Builder(context ?: return@showDialog, R.style.AlertDialogCustom)
.setView(R.layout.add_site_input) .setView(binding.root)
val dialog = builder.create() val dialog = builder.create()
dialog.show() dialog.show()
dialog.text2?.text = provider.name binding.text2.text = provider.name
dialog.apply_btt?.setOnClickListener { binding.applyBtt.setOnClickListener {
val name = dialog.site_name_input?.text?.toString() val name = binding.siteNameInput.text?.toString()
val url = dialog.site_url_input?.text?.toString() val url = binding.siteUrlInput.text?.toString()
val lang = dialog.site_lang_input?.text?.toString() val lang = binding.siteLangInput.text?.toString()
val realLang = if (lang.isNullOrBlank()) provider.lang else lang val realLang = if (lang.isNullOrBlank()) provider.lang else lang
if (url.isNullOrBlank() || name.isNullOrBlank() || realLang.length != 2) { if (url.isNullOrBlank() || name.isNullOrBlank() || realLang.length != 2) {
showToast(activity, R.string.error_invalid_data, Toast.LENGTH_SHORT) showToast(activity, R.string.error_invalid_data, Toast.LENGTH_SHORT)
@ -222,7 +224,7 @@ class SettingsGeneral : PreferenceFragmentCompat() {
dialog.dismissSafe(activity) dialog.dismissSafe(activity)
} }
dialog.cancel_btt?.setOnClickListener { binding.cancelBtt.setOnClickListener {
dialog.dismissSafe(activity) dialog.dismissSafe(activity)
} }
} }
@ -242,18 +244,19 @@ class SettingsGeneral : PreferenceFragmentCompat() {
} }
fun showAddOrDelete() { fun showAddOrDelete() {
val binding : AddRemoveSitesBinding = AddRemoveSitesBinding.inflate(layoutInflater,null,false)
val builder = val builder =
AlertDialog.Builder(context ?: return, R.style.AlertDialogCustom) AlertDialog.Builder(context ?: return, R.style.AlertDialogCustom)
.setView(R.layout.add_remove_sites) .setView(binding.root)
val dialog = builder.create() val dialog = builder.create()
dialog.show() dialog.show()
dialog.add_site?.setOnClickListener { binding.addSite.setOnClickListener {
showAdd() showAdd()
dialog.dismissSafe(activity) dialog.dismissSafe(activity)
} }
dialog.remove_site?.setOnClickListener { binding.removeSite.setOnClickListener {
showDelete() showDelete()
dialog.dismissSafe(activity) dialog.dismissSafe(activity)
} }

View File

@ -13,6 +13,7 @@ import androidx.preference.PreferenceFragmentCompat
import androidx.preference.PreferenceManager import androidx.preference.PreferenceManager
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.LogcatBinding
import com.lagradost.cloudstream3.mvvm.logError import com.lagradost.cloudstream3.mvvm.logError
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.getPref import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.getPref
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.setPaddingBottom import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.setPaddingBottom
@ -25,7 +26,6 @@ import com.lagradost.cloudstream3.utils.SingleSelectionHelper.showBottomDialog
import com.lagradost.cloudstream3.utils.UIHelper.dismissSafe import com.lagradost.cloudstream3.utils.UIHelper.dismissSafe
import com.lagradost.cloudstream3.utils.UIHelper.hideKeyboard import com.lagradost.cloudstream3.utils.UIHelper.hideKeyboard
import com.lagradost.cloudstream3.utils.VideoDownloadManager import com.lagradost.cloudstream3.utils.VideoDownloadManager
import kotlinx.android.synthetic.main.logcat.*
import okhttp3.internal.closeQuietly import okhttp3.internal.closeQuietly
import java.io.BufferedReader import java.io.BufferedReader
import java.io.InputStreamReader import java.io.InputStreamReader
@ -60,7 +60,9 @@ class SettingsUpdates : PreferenceFragmentCompat() {
getPref(R.string.show_logcat_key)?.setOnPreferenceClickListener { pref -> getPref(R.string.show_logcat_key)?.setOnPreferenceClickListener { pref ->
val builder = val builder =
AlertDialog.Builder(pref.context, R.style.AlertDialogCustom) AlertDialog.Builder(pref.context, R.style.AlertDialogCustom)
.setView(R.layout.logcat)
val binding = LogcatBinding.inflate(layoutInflater,null,false )
builder.setView(binding.root)
val dialog = builder.create() val dialog = builder.create()
dialog.show() dialog.show()
@ -81,9 +83,9 @@ class SettingsUpdates : PreferenceFragmentCompat() {
} }
val text = log.toString() val text = log.toString()
dialog.text1?.text = text binding.text1.text = text
dialog.copy_btt?.setOnClickListener { binding.copyBtt.setOnClickListener {
// Can crash on too much text // Can crash on too much text
try { try {
val serviceClipboard = val serviceClipboard =
@ -96,11 +98,11 @@ class SettingsUpdates : PreferenceFragmentCompat() {
showToast(activity, R.string.clipboard_too_large) showToast(activity, R.string.clipboard_too_large)
} }
} }
dialog.clear_btt?.setOnClickListener { binding.clearBtt.setOnClickListener {
Runtime.getRuntime().exec("logcat -c") Runtime.getRuntime().exec("logcat -c")
dialog.dismissSafe(activity) dialog.dismissSafe(activity)
} }
dialog.save_btt?.setOnClickListener { binding.saveBtt.setOnClickListener {
var fileStream: OutputStream? = null var fileStream: OutputStream? = null
try { try {
fileStream = fileStream =
@ -119,7 +121,7 @@ class SettingsUpdates : PreferenceFragmentCompat() {
dialog.dismissSafe(activity) dialog.dismissSafe(activity)
} }
} }
dialog.close_btt?.setOnClickListener { binding.closeBtt.setOnClickListener {
dialog.dismissSafe(activity) dialog.dismissSafe(activity)
} }
return@setOnPreferenceClickListener true return@setOnPreferenceClickListener true

View File

@ -18,6 +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.databinding.AddRepoInputBinding
import com.lagradost.cloudstream3.databinding.FragmentExtensionsBinding
import com.lagradost.cloudstream3.mvvm.observe import com.lagradost.cloudstream3.mvvm.observe
import com.lagradost.cloudstream3.mvvm.observeNullable import com.lagradost.cloudstream3.mvvm.observeNullable
import com.lagradost.cloudstream3.plugins.RepositoryManager import com.lagradost.cloudstream3.plugins.RepositoryManager
@ -30,16 +32,22 @@ import com.lagradost.cloudstream3.utils.Coroutines.ioSafe
import com.lagradost.cloudstream3.utils.Coroutines.main import com.lagradost.cloudstream3.utils.Coroutines.main
import com.lagradost.cloudstream3.utils.UIHelper.dismissSafe import com.lagradost.cloudstream3.utils.UIHelper.dismissSafe
import com.lagradost.cloudstream3.widget.LinearRecycleViewLayoutManager import com.lagradost.cloudstream3.widget.LinearRecycleViewLayoutManager
import kotlinx.android.synthetic.main.add_repo_input.*
import kotlinx.android.synthetic.main.fragment_extensions.*
class ExtensionsFragment : Fragment() { class ExtensionsFragment : Fragment() {
var binding: FragmentExtensionsBinding? = null
override fun onDestroyView() {
binding = null
super.onDestroyView()
}
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.fragment_extensions, container, false) val localBinding = FragmentExtensionsBinding.inflate(inflater, container, false)
binding = localBinding
return localBinding.root//inflater.inflate(R.layout.fragment_extensions, container, false)
} }
private fun View.setLayoutWidth(weight: Int) { private fun View.setLayoutWidth(weight: Int) {
@ -74,7 +82,7 @@ class ExtensionsFragment : Fragment() {
setUpToolbar(R.string.extensions) setUpToolbar(R.string.extensions)
repo_recycler_view?.adapter = RepoAdapter(false, { binding?.repoRecyclerView?.adapter = RepoAdapter(false, {
findNavController().navigate( findNavController().navigate(
R.id.navigation_settings_extensions_to_navigation_settings_plugins, R.id.navigation_settings_extensions_to_navigation_settings_plugins,
PluginsFragment.newInstance( PluginsFragment.newInstance(
@ -113,12 +121,12 @@ class ExtensionsFragment : Fragment() {
}) })
observe(extensionViewModel.repositories) { observe(extensionViewModel.repositories) {
repo_recycler_view?.isVisible = it.isNotEmpty() binding?.repoRecyclerView?.isVisible = it.isNotEmpty()
blank_repo_screen?.isVisible = it.isEmpty() binding?.blankRepoScreen?.isVisible = it.isEmpty()
(repo_recycler_view?.adapter as? RepoAdapter)?.updateList(it) (binding?.repoRecyclerView?.adapter as? RepoAdapter)?.updateList(it)
} }
repo_recycler_view?.apply { binding?.repoRecyclerView?.apply {
context?.let { ctx -> context?.let { ctx ->
layoutManager = LinearRecycleViewLayoutManager(ctx, nextFocusUpId, nextFocusDownId) layoutManager = LinearRecycleViewLayoutManager(ctx, nextFocusUpId, nextFocusDownId)
} }
@ -140,28 +148,30 @@ class ExtensionsFragment : Fragment() {
// } // }
observeNullable(extensionViewModel.pluginStats) { value -> observeNullable(extensionViewModel.pluginStats) { value ->
if (value == null) { binding?.apply {
plugin_storage_appbar?.isVisible = false if (value == null) {
pluginStorageAppbar.isVisible = false
return@observeNullable return@observeNullable
} }
plugin_storage_appbar?.isVisible = true pluginStorageAppbar.isVisible = true
if (value.total == 0) { if (value.total == 0) {
plugin_download?.setLayoutWidth(1) pluginDownload.setLayoutWidth(1)
plugin_disabled?.setLayoutWidth(0) pluginDisabled.setLayoutWidth(0)
plugin_not_downloaded?.setLayoutWidth(0) pluginNotDownloaded.setLayoutWidth(0)
} else { } else {
plugin_download?.setLayoutWidth(value.downloaded) pluginDownload.setLayoutWidth(value.downloaded)
plugin_disabled?.setLayoutWidth(value.disabled) pluginDisabled.setLayoutWidth(value.disabled)
plugin_not_downloaded?.setLayoutWidth(value.notDownloaded) pluginNotDownloaded.setLayoutWidth(value.notDownloaded)
}
pluginNotDownloadedTxt.setText(value.notDownloadedText)
pluginDisabledTxt.setText(value.disabledText)
pluginDownloadTxt.setText(value.downloadedText)
} }
plugin_not_downloaded_txt.setText(value.notDownloadedText)
plugin_disabled_txt.setText(value.disabledText)
plugin_download_txt.setText(value.downloadedText)
} }
plugin_storage_appbar?.setOnClickListener { binding?.pluginStorageAppbar?.setOnClickListener {
findNavController().navigate( findNavController().navigate(
R.id.navigation_settings_extensions_to_navigation_settings_plugins, R.id.navigation_settings_extensions_to_navigation_settings_plugins,
PluginsFragment.newInstance( PluginsFragment.newInstance(
@ -173,16 +183,18 @@ class ExtensionsFragment : Fragment() {
} }
val addRepositoryClick = View.OnClickListener { val addRepositoryClick = View.OnClickListener {
val ctx = context ?: return@OnClickListener
val binding = AddRepoInputBinding.inflate(LayoutInflater.from(ctx), null, false)
val builder = val builder =
AlertDialog.Builder(context ?: return@OnClickListener, R.style.AlertDialogCustom) AlertDialog.Builder(ctx, R.style.AlertDialogCustom)
.setView(R.layout.add_repo_input) .setView(binding.root)
val dialog = builder.create() val dialog = builder.create()
dialog.show() dialog.show()
(activity?.getSystemService(Context.CLIPBOARD_SERVICE) as? ClipboardManager?)?.primaryClip?.getItemAt( (activity?.getSystemService(Context.CLIPBOARD_SERVICE) as? ClipboardManager?)?.primaryClip?.getItemAt(
0 0
)?.text?.toString()?.let { copy -> )?.text?.toString()?.let { copy ->
dialog.repo_url_input?.setText(copy) binding.repoUrlInput.setText(copy)
} }
// dialog.list_repositories?.setOnClickListener { // dialog.list_repositories?.setOnClickListener {
@ -192,10 +204,10 @@ class ExtensionsFragment : Fragment() {
// } // }
// dialog.text2?.text = provider.name // dialog.text2?.text = provider.name
dialog.apply_btt?.setOnClickListener secondListener@{ binding.applyBtt.setOnClickListener secondListener@{
val name = dialog.repo_name_input?.text?.toString() val name = binding.repoNameInput.text?.toString()
ioSafe { ioSafe {
val url = dialog.repo_url_input?.text?.toString() val url = binding.repoUrlInput.text?.toString()
?.let { it1 -> RepositoryManager.parseRepoUrl(it1) } ?.let { it1 -> RepositoryManager.parseRepoUrl(it1) }
if (url.isNullOrBlank()) { if (url.isNullOrBlank()) {
main { main {
@ -214,22 +226,23 @@ class ExtensionsFragment : Fragment() {
} }
dialog.dismissSafe(activity) dialog.dismissSafe(activity)
} }
dialog.cancel_btt?.setOnClickListener { binding.cancelBtt.setOnClickListener {
dialog.dismissSafe(activity) dialog.dismissSafe(activity)
} }
} }
val isTv = isTrueTvSettings() val isTv = isTrueTvSettings()
add_repo_button?.isGone = isTv binding?.apply {
add_repo_button_imageview_holder?.isVisible = isTv addRepoButton.isGone = isTv
addRepoButtonImageviewHolder.isVisible = isTv
// Band-aid for Fire TV // Band-aid for Fire TV
plugin_storage_appbar?.isFocusableInTouchMode = isTv pluginStorageAppbar.isFocusableInTouchMode = isTv
add_repo_button_imageview?.isFocusableInTouchMode = isTv addRepoButtonImageview.isFocusableInTouchMode = isTv
add_repo_button?.setOnClickListener(addRepositoryClick)
add_repo_button_imageview?.setOnClickListener(addRepositoryClick)
addRepoButton.setOnClickListener(addRepositoryClick)
addRepoButtonImageview.setOnClickListener(addRepositoryClick)
}
reloadRepositories() reloadRepositories()
} }
} }

View File

@ -1,14 +1,15 @@
package com.lagradost.cloudstream3.ui.settings.extensions package com.lagradost.cloudstream3.ui.settings.extensions
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 androidx.viewbinding.ViewBinding
import com.lagradost.cloudstream3.R import com.lagradost.cloudstream3.R
import com.lagradost.cloudstream3.databinding.RepositoryItemBinding
import com.lagradost.cloudstream3.databinding.RepositoryItemTvBinding
import com.lagradost.cloudstream3.plugins.RepositoryManager.PREBUILT_REPOSITORIES import com.lagradost.cloudstream3.plugins.RepositoryManager.PREBUILT_REPOSITORIES
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTrueTvSettings import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTrueTvSettings
import kotlinx.android.synthetic.main.repository_item.view.*
class RepoAdapter( class RepoAdapter(
val isSetup: Boolean, val isSetup: Boolean,
@ -20,9 +21,17 @@ class RepoAdapter(
private val repositories: MutableList<RepositoryData> = mutableListOf() private val repositories: MutableList<RepositoryData> = mutableListOf()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
val layout = if(isTrueTvSettings()) R.layout.repository_item_tv else R.layout.repository_item val layout = if (isTrueTvSettings()) RepositoryItemTvBinding.inflate(
LayoutInflater.from(parent.context),
parent,
false
) else RepositoryItemBinding.inflate(
LayoutInflater.from(parent.context),
parent,
false
) //R.layout.repository_item_tv else R.layout.repository_item
return RepoViewHolder( return RepoViewHolder(
LayoutInflater.from(parent.context).inflate(layout, parent, false) layout
) )
} }
@ -57,30 +66,57 @@ class RepoAdapter(
diffResult.dispatchUpdatesTo(this) diffResult.dispatchUpdatesTo(this)
} }
inner class RepoViewHolder(itemView: View) : inner class RepoViewHolder(
RecyclerView.ViewHolder(itemView) { val binding: ViewBinding
) :
RecyclerView.ViewHolder(binding.root) {
fun bind( fun bind(
repositoryData: RepositoryData repositoryData: RepositoryData
) { ) {
val isPrebuilt = PREBUILT_REPOSITORIES.contains(repositoryData) val isPrebuilt = PREBUILT_REPOSITORIES.contains(repositoryData)
val drawable = val drawable =
if (isSetup) R.drawable.netflix_download else R.drawable.ic_baseline_delete_outline_24 if (isSetup) R.drawable.netflix_download else R.drawable.ic_baseline_delete_outline_24
when (binding) {
is RepositoryItemTvBinding -> {
binding.apply {
// Only shows icon if on setup or if it isn't a prebuilt repo.
// No delete buttons on prebuilt repos.
if (!isPrebuilt || isSetup) {
actionButton.setImageResource(drawable)
}
// Only shows icon if on setup or if it isn't a prebuilt repo. actionButton.setOnClickListener {
// No delete buttons on prebuilt repos. imageClickCallback(repositoryData)
if (!isPrebuilt || isSetup) { }
itemView.action_button?.setImageResource(drawable)
}
itemView.action_button?.setOnClickListener { repositoryItemRoot.setOnClickListener {
imageClickCallback(repositoryData) clickCallback(repositoryData)
} }
mainText.text = repositoryData.name
subText.text = repositoryData.url
}
}
itemView.repository_item_root?.setOnClickListener { is RepositoryItemBinding -> {
clickCallback(repositoryData) binding.apply {
// Only shows icon if on setup or if it isn't a prebuilt repo.
// No delete buttons on prebuilt repos.
if (!isPrebuilt || isSetup) {
actionButton.setImageResource(drawable)
}
actionButton.setOnClickListener {
imageClickCallback(repositoryData)
}
repositoryItemRoot.setOnClickListener {
clickCallback(repositoryData)
}
mainText.text = repositoryData.name
subText.text = repositoryData.url
}
}
} }
itemView.main_text?.text = repositoryData.name
itemView.sub_text?.text = repositoryData.url
} }
} }
} }

View File

@ -1,97 +1,105 @@
package com.lagradost.cloudstream3.ui.settings.testing package com.lagradost.cloudstream3.ui.settings.testing
import android.os.Bundle import android.os.Bundle
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
import androidx.coordinatorlayout.widget.CoordinatorLayout import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels import androidx.fragment.app.activityViewModels
import com.lagradost.cloudstream3.R import com.lagradost.cloudstream3.R
import com.lagradost.cloudstream3.databinding.FragmentTestingBinding
import com.lagradost.cloudstream3.mvvm.normalSafeApiCall import com.lagradost.cloudstream3.mvvm.normalSafeApiCall
import com.lagradost.cloudstream3.mvvm.observe import com.lagradost.cloudstream3.mvvm.observe
import com.lagradost.cloudstream3.mvvm.observeNullable import com.lagradost.cloudstream3.mvvm.observeNullable
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.setUpToolbar import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.setUpToolbar
import kotlinx.android.synthetic.main.fragment_testing.*
import kotlinx.android.synthetic.main.view_test.*
class TestFragment : Fragment() { class TestFragment : Fragment() {
private val testViewModel: TestViewModel by activityViewModels() private val testViewModel: TestViewModel by activityViewModels()
var binding: FragmentTestingBinding? = null
override fun onDestroyView() {
binding = null
super.onDestroyView()
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
setUpToolbar(R.string.category_provider_test) setUpToolbar(R.string.category_provider_test)
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
provider_test_recycler_view?.adapter = TestResultAdapter( binding?.apply {
mutableListOf() providerTestRecyclerView.adapter = TestResultAdapter(
) mutableListOf()
)
testViewModel.init() testViewModel.init()
if (testViewModel.isRunningTest) { if (testViewModel.isRunningTest) {
provider_test?.setState(TestView.TestState.Running) providerTest.setState(TestView.TestState.Running)
}
observe(testViewModel.providerProgress) { (passed, failed, total) ->
provider_test?.setProgress(passed, failed, total)
}
observeNullable(testViewModel.providerResults) {
normalSafeApiCall {
val newItems = it.sortedBy { api -> api.first.name }
(provider_test_recycler_view?.adapter as? TestResultAdapter)?.updateList(
newItems
)
} }
}
provider_test?.setOnPlayButtonListener { state -> observe(testViewModel.providerProgress) { (passed, failed, total) ->
when (state) { providerTest.setProgress(passed, failed, total)
TestView.TestState.Stopped -> testViewModel.stopTest()
TestView.TestState.Running -> testViewModel.startTest()
TestView.TestState.None -> testViewModel.startTest()
} }
}
if (isTrueTvSettings()) { observeNullable(testViewModel.providerResults) {
tests_play_pause?.isFocusableInTouchMode = true normalSafeApiCall {
tests_play_pause?.requestFocus() val newItems = it.sortedBy { api -> api.first.name }
} (providerTestRecyclerView.adapter as? TestResultAdapter)?.updateList(
newItems
provider_test?.playPauseButton?.setOnFocusChangeListener { _, hasFocus -> )
if (hasFocus) { }
provider_test_appbar?.setExpanded(true, true) }
providerTest.setOnPlayButtonListener { state ->
when (state) {
TestView.TestState.Stopped -> testViewModel.stopTest()
TestView.TestState.Running -> testViewModel.startTest()
TestView.TestState.None -> testViewModel.startTest()
}
} }
}
fun focusRecyclerView() {
// Hack to make it possible to focus the recyclerview.
if (isTrueTvSettings()) { if (isTrueTvSettings()) {
provider_test_recycler_view?.requestFocus() providerTest.playPauseButton?.isFocusableInTouchMode = true
provider_test_appbar?.setExpanded(false, true) providerTest.playPauseButton?.requestFocus()
} }
}
provider_test?.setOnMainClick { providerTest.playPauseButton?.setOnFocusChangeListener { _, hasFocus ->
testViewModel.setFilterMethod(TestViewModel.ProviderFilter.All) if (hasFocus) {
focusRecyclerView() providerTestAppbar.setExpanded(true, true)
} }
provider_test?.setOnFailedClick { }
testViewModel.setFilterMethod(TestViewModel.ProviderFilter.Failed)
focusRecyclerView() fun focusRecyclerView() {
} // Hack to make it possible to focus the recyclerview.
provider_test?.setOnPassedClick { if (isTrueTvSettings()) {
testViewModel.setFilterMethod(TestViewModel.ProviderFilter.Passed) providerTestRecyclerView.requestFocus()
focusRecyclerView() providerTestAppbar.setExpanded(false, true)
}
}
providerTest.setOnMainClick {
testViewModel.setFilterMethod(TestViewModel.ProviderFilter.All)
focusRecyclerView()
}
providerTest.setOnFailedClick {
testViewModel.setFilterMethod(TestViewModel.ProviderFilter.Failed)
focusRecyclerView()
}
providerTest.setOnPassedClick {
testViewModel.setFilterMethod(TestViewModel.ProviderFilter.Passed)
focusRecyclerView()
}
} }
} }
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_testing, container, false) val localBinding = FragmentTestingBinding.inflate(inflater, container, false)
binding = localBinding
return localBinding.root//inflater.inflate(R.layout.fragment_testing, container, false)
} }
} }